Add personal data tools, 2nd Brain trust toggle, and research agents
Personal Data Tools: native Calendar, Reminders, Contacts (hidden pending Apple TCC fix in beta), and Location & Maps access via EventKit, Contacts framework, and MapKit. Write actions (create event/reminder, complete reminder) gate through an approval sheet. Four hardened-runtime entitlements added to oAI.entitlements; Info.plist usage strings added for all services. Personal Data section shows a β badge while Contacts is hidden. 2nd Brain always-trust: inline toggle on the Agent Skills row for the skill named "2nd Brain" skips the bash approval dialog when the command contains .brain_helper.py, gated by three runtime checks in MCPService. Research agents: spawn_research_agents tool runs up to 5 concurrent read-only sub-agents (read_file, list_directory, search_files, web_search — no write, no bash, no nesting). Bounded by maxConcurrentAgents setting (default 3) and a hard ceiling of 8 tasks. Added items field to Tool.Function.Parameters.Property for JSON Schema array support; wired into AnthropicProvider.convertParametersToDict. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -799,8 +799,10 @@ Don't narrate future actions ("Let me...") - just use the tools.
|
||||
let mcpActive = mcpEnabled || settings.mcpEnabled
|
||||
let anytypeActive = settings.anytypeMcpEnabled && settings.anytypeMcpConfigured
|
||||
let bashActive = settings.bashEnabled
|
||||
let personalDataActive = settings.calendarEnabled || settings.remindersEnabled || settings.contactsEnabled || settings.locationMapsEnabled
|
||||
let researchAgentsActive = settings.agentsEnabled
|
||||
let modelSupportTools = selectedModel?.capabilities.tools ?? false
|
||||
if modelSupportTools && (anytypeActive || bashActive || (mcpActive && !mcp.allowedFolders.isEmpty)) {
|
||||
if modelSupportTools && (anytypeActive || bashActive || personalDataActive || researchAgentsActive || (mcpActive && !mcp.allowedFolders.isEmpty)) {
|
||||
generateAIResponseWithTools(provider: provider, modelId: modelId)
|
||||
return
|
||||
}
|
||||
@@ -1354,6 +1356,7 @@ Don't narrate future actions ("Let me...") - just use the tools.
|
||||
var didContinueAfterImages = false // Only inject temp-file continuation once
|
||||
var totalUsage: ChatResponse.Usage?
|
||||
var hitIterationLimit = false // Track if we exited due to hitting the limit
|
||||
var finishedWithEmptyContent = false // Model stopped calling tools but said nothing
|
||||
|
||||
for iteration in 0..<maxIterations {
|
||||
if Task.isCancelled {
|
||||
@@ -1406,6 +1409,13 @@ Don't narrate future actions ("Let me...") - just use the tools.
|
||||
continue
|
||||
}
|
||||
}
|
||||
if finalContent.isEmpty {
|
||||
// Some models (observed with Qwen via OpenRouter) stop calling tools
|
||||
// after a long tool-call chain but return no summarizing text at all.
|
||||
// Surface a placeholder and nudge a follow-up turn instead of a silent blank bubble.
|
||||
finishedWithEmptyContent = true
|
||||
finalContent = "[No response from the model — retrying]"
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
@@ -1452,7 +1462,7 @@ Don't narrate future actions ("Let me...") - just use the tools.
|
||||
break
|
||||
}
|
||||
|
||||
let result = await mcp.executeTool(name: tc.functionName, arguments: tc.arguments)
|
||||
let result = await mcp.executeTool(name: tc.functionName, arguments: tc.arguments, agentProvider: provider, agentModelId: effectiveModelId)
|
||||
let resultJSON: String
|
||||
if let data = try? JSONSerialization.data(withJSONObject: result),
|
||||
let str = String(data: data, encoding: .utf8) {
|
||||
@@ -1537,8 +1547,8 @@ Don't narrate future actions ("Let me...") - just use the tools.
|
||||
isGenerating = false
|
||||
streamingTask = nil
|
||||
|
||||
// If we hit the iteration limit and weren't cancelled, start auto-continue
|
||||
if hitIterationLimit && !wasCancelled {
|
||||
// If we hit the iteration limit, or the model returned no text at all, nudge a follow-up turn
|
||||
if (hitIterationLimit || finishedWithEmptyContent) && !wasCancelled {
|
||||
startAutoContinue()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user