@pentoshi/clai 3.5.1 → 3.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent/compaction-summary.d.ts +17 -0
- package/dist/agent/compaction-summary.js +64 -0
- package/dist/agent/compaction-summary.js.map +1 -0
- package/dist/agent/confirm-port.d.ts +3 -1
- package/dist/agent/confirm-port.js +5 -1
- package/dist/agent/confirm-port.js.map +1 -1
- package/dist/agent/context-manager.js +53 -24
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/events.d.ts +6 -0
- package/dist/agent/evidence-governor.d.ts +37 -0
- package/dist/agent/evidence-governor.js +70 -0
- package/dist/agent/evidence-governor.js.map +1 -0
- package/dist/agent/loop-guard.d.ts +29 -9
- package/dist/agent/loop-guard.js +117 -26
- package/dist/agent/loop-guard.js.map +1 -1
- package/dist/agent/must-continue.d.ts +56 -0
- package/dist/agent/must-continue.js +240 -0
- package/dist/agent/must-continue.js.map +1 -0
- package/dist/agent/outcomes.d.ts +101 -0
- package/dist/agent/outcomes.js +359 -0
- package/dist/agent/outcomes.js.map +1 -0
- package/dist/agent/plan-decision.d.ts +33 -0
- package/dist/agent/plan-decision.js +104 -0
- package/dist/agent/plan-decision.js.map +1 -0
- package/dist/agent/plan-tool.d.ts +34 -0
- package/dist/agent/plan-tool.js +594 -76
- package/dist/agent/plan-tool.js.map +1 -1
- package/dist/agent/project-root.d.ts +33 -0
- package/dist/agent/project-root.js +161 -0
- package/dist/agent/project-root.js.map +1 -0
- package/dist/agent/prompt-composer.d.ts +21 -0
- package/dist/agent/prompt-composer.js +46 -0
- package/dist/agent/prompt-composer.js.map +1 -0
- package/dist/agent/runner.d.ts +11 -1
- package/dist/agent/runner.js +1915 -886
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/scope-context.d.ts +3 -0
- package/dist/agent/scope-context.js +24 -0
- package/dist/agent/scope-context.js.map +1 -0
- package/dist/agent/scratch-write.d.ts +4 -0
- package/dist/agent/scratch-write.js +54 -0
- package/dist/agent/scratch-write.js.map +1 -0
- package/dist/agent/session-policy.d.ts +7 -0
- package/dist/agent/session-policy.js +61 -0
- package/dist/agent/session-policy.js.map +1 -1
- package/dist/agent/session-state.d.ts +41 -0
- package/dist/agent/session-state.js +107 -0
- package/dist/agent/session-state.js.map +1 -0
- package/dist/agent/step-budget.d.ts +14 -0
- package/dist/agent/step-budget.js +26 -0
- package/dist/agent/step-budget.js.map +1 -0
- package/dist/agent/task-analyzer.d.ts +12 -3
- package/dist/agent/task-analyzer.js +263 -23
- package/dist/agent/task-analyzer.js.map +1 -1
- package/dist/agent/task-evidence.d.ts +173 -0
- package/dist/agent/task-evidence.js +802 -0
- package/dist/agent/task-evidence.js.map +1 -0
- package/dist/agent/task-plan.d.ts +57 -0
- package/dist/agent/task-plan.js +147 -1
- package/dist/agent/task-plan.js.map +1 -1
- package/dist/agent/tool-call-parser.d.ts +19 -11
- package/dist/agent/tool-call-parser.js +96 -71
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/agent/tool-history.d.ts +34 -0
- package/dist/agent/tool-history.js +200 -0
- package/dist/agent/tool-history.js.map +1 -0
- package/dist/agent/tool-output-formatting.d.ts +13 -1
- package/dist/agent/tool-output-formatting.js +75 -22
- package/dist/agent/tool-output-formatting.js.map +1 -1
- package/dist/agent/turn-outcome.d.ts +11 -0
- package/dist/agent/turn-outcome.js +17 -0
- package/dist/agent/turn-outcome.js.map +1 -0
- package/dist/agent/turn-state.d.ts +11 -0
- package/dist/agent/turn-state.js +28 -0
- package/dist/agent/turn-state.js.map +1 -0
- package/dist/agent/workspace-orient.d.ts +75 -0
- package/dist/agent/workspace-orient.js +509 -0
- package/dist/agent/workspace-orient.js.map +1 -0
- package/dist/app/adapters/agent-event-adapter.d.ts +2 -13
- package/dist/app/adapters/agent-event-adapter.js +63 -25
- package/dist/app/adapters/agent-event-adapter.js.map +1 -1
- package/dist/app/adapters/current-agent-adapter.d.ts +0 -5
- package/dist/app/adapters/current-agent-adapter.js +4 -7
- package/dist/app/adapters/current-agent-adapter.js.map +1 -1
- package/dist/app/adapters/current-jobs-adapter.js +1 -0
- package/dist/app/adapters/current-jobs-adapter.js.map +1 -1
- package/dist/app/adapters/current-terminal-adapter.d.ts +0 -7
- package/dist/app/adapters/current-terminal-adapter.js +0 -7
- package/dist/app/adapters/current-terminal-adapter.js.map +1 -1
- package/dist/app/adapters/current-updates-adapter.d.ts +0 -5
- package/dist/app/adapters/current-updates-adapter.js +0 -5
- package/dist/app/adapters/current-updates-adapter.js.map +1 -1
- package/dist/app/adapters/in-memory-clipboard-adapter.d.ts +0 -5
- package/dist/app/adapters/in-memory-clipboard-adapter.js +0 -5
- package/dist/app/adapters/in-memory-clipboard-adapter.js.map +1 -1
- package/dist/app/commands/command.d.ts +0 -5
- package/dist/app/commands/command.js.map +1 -1
- package/dist/app/commands/registry.d.ts +0 -14
- package/dist/app/commands/registry.js +0 -20
- package/dist/app/commands/registry.js.map +1 -1
- package/dist/app/controllers/disposable.d.ts +0 -5
- package/dist/app/controllers/disposable.js +0 -5
- package/dist/app/controllers/disposable.js.map +1 -1
- package/dist/app/controllers/job-controller.d.ts +1 -5
- package/dist/app/controllers/job-controller.js +0 -4
- package/dist/app/controllers/job-controller.js.map +1 -1
- package/dist/app/controllers/plan-controller.d.ts +5 -8
- package/dist/app/controllers/plan-controller.js +30 -12
- package/dist/app/controllers/plan-controller.js.map +1 -1
- package/dist/app/controllers/session-controller.d.ts +17 -32
- package/dist/app/controllers/session-controller.js +60 -35
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/app/controllers/turn-controller.d.ts +2 -6
- package/dist/app/controllers/turn-controller.js +8 -8
- package/dist/app/controllers/turn-controller.js.map +1 -1
- package/dist/app/events/app-event.d.ts +4 -7
- package/dist/app/events/app-event.js +0 -6
- package/dist/app/events/app-event.js.map +1 -1
- package/dist/app/events/event-buffer.d.ts +6 -17
- package/dist/app/events/event-buffer.js +27 -24
- package/dist/app/events/event-buffer.js.map +1 -1
- package/dist/app/events/sequencer.d.ts +0 -9
- package/dist/app/events/sequencer.js +0 -4
- package/dist/app/events/sequencer.js.map +1 -1
- package/dist/app/ports/agent-port.d.ts +13 -3
- package/dist/app/ports/clipboard-port.d.ts +0 -5
- package/dist/app/ports/confirm-port.d.ts +0 -7
- package/dist/app/ports/jobs-port.d.ts +2 -5
- package/dist/app/ports/persistence-port.d.ts +0 -4
- package/dist/app/ports/secret-port.d.ts +0 -5
- package/dist/app/ports/terminal-port.d.ts +0 -6
- package/dist/app/ports/updates-port.d.ts +0 -4
- package/dist/attachments/service.d.ts +29 -0
- package/dist/attachments/service.js +47 -0
- package/dist/attachments/service.js.map +1 -0
- package/dist/commands/doctor.js +3 -0
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/providers.js +0 -3
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/search-providers.d.ts +0 -33
- package/dist/commands/search-providers.js +0 -33
- package/dist/commands/search-providers.js.map +1 -1
- package/dist/commands/update.js +1 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +22 -42
- package/dist/index.js.map +1 -1
- package/dist/llm/adapters/anthropic-tools.d.ts +99 -0
- package/dist/llm/adapters/anthropic-tools.js +225 -0
- package/dist/llm/adapters/anthropic-tools.js.map +1 -0
- package/dist/llm/adapters/gemini-tools.d.ts +54 -0
- package/dist/llm/adapters/gemini-tools.js +139 -0
- package/dist/llm/adapters/gemini-tools.js.map +1 -0
- package/dist/llm/adapters/ollama-tools.d.ts +18 -0
- package/dist/llm/adapters/ollama-tools.js +58 -0
- package/dist/llm/adapters/ollama-tools.js.map +1 -0
- package/dist/llm/adapters/openai-tools.d.ts +39 -0
- package/dist/llm/adapters/openai-tools.js +71 -0
- package/dist/llm/adapters/openai-tools.js.map +1 -0
- package/dist/llm/agentrouter.js +23 -4
- package/dist/llm/agentrouter.js.map +1 -1
- package/dist/llm/anthropic.js +93 -92
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/aws-mantle.js +93 -56
- package/dist/llm/aws-mantle.js.map +1 -1
- package/dist/llm/bynara.js +23 -4
- package/dist/llm/bynara.js.map +1 -1
- package/dist/llm/capabilities.d.ts +13 -6
- package/dist/llm/capabilities.js +113 -13
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/llm/gemini.js +63 -48
- package/dist/llm/gemini.js.map +1 -1
- package/dist/llm/groq.js +23 -10
- package/dist/llm/groq.js.map +1 -1
- package/dist/llm/http.d.ts +22 -34
- package/dist/llm/http.js +97 -69
- package/dist/llm/http.js.map +1 -1
- package/dist/llm/kimchi.js +23 -4
- package/dist/llm/kimchi.js.map +1 -1
- package/dist/llm/nvidia.js +23 -4
- package/dist/llm/nvidia.js.map +1 -1
- package/dist/llm/ollama.js +49 -31
- package/dist/llm/ollama.js.map +1 -1
- package/dist/llm/openai.js +23 -4
- package/dist/llm/openai.js.map +1 -1
- package/dist/llm/openrouter.js +23 -4
- package/dist/llm/openrouter.js.map +1 -1
- package/dist/llm/qwen-cloud.js +23 -4
- package/dist/llm/qwen-cloud.js.map +1 -1
- package/dist/llm/router.d.ts +0 -6
- package/dist/llm/router.js +48 -21
- package/dist/llm/router.js.map +1 -1
- package/dist/llm/tool-protocol.d.ts +67 -0
- package/dist/llm/tool-protocol.js +278 -0
- package/dist/llm/tool-protocol.js.map +1 -0
- package/dist/modes/agent.d.ts +2 -1
- package/dist/modes/agent.js +4 -2
- package/dist/modes/agent.js.map +1 -1
- package/dist/modes/ask.d.ts +0 -18
- package/dist/modes/ask.js +71 -66
- package/dist/modes/ask.js.map +1 -1
- package/dist/os/cwd.d.ts +0 -21
- package/dist/os/cwd.js +0 -24
- package/dist/os/cwd.js.map +1 -1
- package/dist/os/pkgmgr.js +0 -6
- package/dist/os/pkgmgr.js.map +1 -1
- package/dist/prompts/index.d.ts +17 -21
- package/dist/prompts/index.js +131 -259
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/system.agent.md +242 -0
- package/dist/prompts/system.ask.md +56 -0
- package/dist/repl/prompt-line.js +0 -36
- package/dist/repl/prompt-line.js.map +1 -1
- package/dist/repl/slash-commands.d.ts +0 -9
- package/dist/repl/slash-commands.js +2 -23
- package/dist/repl/slash-commands.js.map +1 -1
- package/dist/repl.d.ts +5 -0
- package/dist/repl.js +176 -55
- package/dist/repl.js.map +1 -1
- package/dist/safety/classifier.js +17 -9
- package/dist/safety/classifier.js.map +1 -1
- package/dist/safety/engagement-policy.d.ts +46 -0
- package/dist/safety/engagement-policy.js +198 -0
- package/dist/safety/engagement-policy.js.map +1 -0
- package/dist/store/config.d.ts +7 -0
- package/dist/store/config.js +1 -0
- package/dist/store/config.js.map +1 -1
- package/dist/store/engagement.d.ts +115 -0
- package/dist/store/engagement.js +278 -0
- package/dist/store/engagement.js.map +1 -0
- package/dist/store/logs.d.ts +5 -0
- package/dist/store/logs.js +52 -2
- package/dist/store/logs.js.map +1 -1
- package/dist/store/plan.d.ts +59 -5
- package/dist/store/plan.js +182 -8
- package/dist/store/plan.js.map +1 -1
- package/dist/store/scope.d.ts +4 -1
- package/dist/store/scope.js +2 -2
- package/dist/store/scope.js.map +1 -1
- package/dist/tools/capabilities.d.ts +2 -0
- package/dist/tools/capabilities.js +101 -6
- package/dist/tools/capabilities.js.map +1 -1
- package/dist/tools/command-intent.d.ts +1 -0
- package/dist/tools/command-intent.js +31 -0
- package/dist/tools/command-intent.js.map +1 -1
- package/dist/tools/definitions.d.ts +20 -0
- package/dist/tools/definitions.js +578 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/elevated-shell.d.ts +60 -0
- package/dist/tools/elevated-shell.js +233 -0
- package/dist/tools/elevated-shell.js.map +1 -0
- package/dist/tools/file-diff.d.ts +125 -0
- package/dist/tools/file-diff.js +495 -0
- package/dist/tools/file-diff.js.map +1 -0
- package/dist/tools/fs.d.ts +11 -13
- package/dist/tools/fs.js +280 -80
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/http.d.ts +15 -0
- package/dist/tools/http.js +202 -61
- package/dist/tools/http.js.map +1 -1
- package/dist/tools/jobs.d.ts +71 -10
- package/dist/tools/jobs.js +403 -124
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/net-ping-sweep.js +69 -16
- package/dist/tools/net-ping-sweep.js.map +1 -1
- package/dist/tools/nmap-runner.d.ts +19 -7
- package/dist/tools/nmap-runner.js +182 -80
- package/dist/tools/nmap-runner.js.map +1 -1
- package/dist/tools/pentest-workflows.d.ts +8 -0
- package/dist/tools/pentest-workflows.js +71 -0
- package/dist/tools/pentest-workflows.js.map +1 -0
- package/dist/tools/registry.d.ts +9 -0
- package/dist/tools/registry.js +272 -63
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/shell.d.ts +3 -0
- package/dist/tools/shell.js +35 -13
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/tool-types.d.ts +11 -0
- package/dist/tools/validate.d.ts +11 -0
- package/dist/tools/validate.js +53 -0
- package/dist/tools/validate.js.map +1 -1
- package/dist/tools/web/search.js +48 -4
- package/dist/tools/web/search.js.map +1 -1
- package/dist/tui-v2/app/App.js +25 -39
- package/dist/tui-v2/app/App.js.map +1 -1
- package/dist/tui-v2/app/command-handlers.js +20 -1
- package/dist/tui-v2/app/command-handlers.js.map +1 -1
- package/dist/tui-v2/app/commands/picker-commands.js +3 -0
- package/dist/tui-v2/app/commands/picker-commands.js.map +1 -1
- package/dist/tui-v2/app/commands/session-commands.js +5 -0
- package/dist/tui-v2/app/commands/session-commands.js.map +1 -1
- package/dist/tui-v2/app/plan-lifecycle.d.ts +25 -3
- package/dist/tui-v2/app/plan-lifecycle.js +87 -24
- package/dist/tui-v2/app/plan-lifecycle.js.map +1 -1
- package/dist/tui-v2/bootstrap/patch-opentui-text.d.ts +6 -0
- package/dist/tui-v2/bootstrap/patch-opentui-text.js +53 -0
- package/dist/tui-v2/bootstrap/patch-opentui-text.js.map +1 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js +7 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
- package/dist/tui-v2/components/jobs/jobs-panel.js +23 -14
- package/dist/tui-v2/components/jobs/jobs-panel.js.map +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.d.ts +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.js +18 -7
- package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
- package/dist/tui-v2/components/pager/pager.d.ts +6 -0
- package/dist/tui-v2/components/pager/pager.js +313 -67
- package/dist/tui-v2/components/pager/pager.js.map +1 -1
- package/dist/tui-v2/components/status/status-line.d.ts +9 -0
- package/dist/tui-v2/components/status/status-line.js +17 -3
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/tui-v2/components/transcript/assistant-message.js +1 -1
- package/dist/tui-v2/components/transcript/assistant-message.js.map +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/tool-card.d.ts +9 -1
- package/dist/tui-v2/components/transcript/tool-card.js +115 -10
- package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-row.js +2 -2
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +16 -0
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/controllers/overlay-controller.d.ts +16 -2
- package/dist/tui-v2/controllers/overlay-controller.js +92 -12
- package/dist/tui-v2/controllers/overlay-controller.js.map +1 -1
- package/dist/tui-v2/rendering/artifact-pager-source.d.ts +19 -0
- package/dist/tui-v2/rendering/artifact-pager-source.js +103 -0
- package/dist/tui-v2/rendering/artifact-pager-source.js.map +1 -0
- package/dist/tui-v2/rendering/file-diff-view.d.ts +63 -0
- package/dist/tui-v2/rendering/file-diff-view.js +263 -0
- package/dist/tui-v2/rendering/file-diff-view.js.map +1 -0
- package/dist/tui-v2/rendering/open-tool-output.d.ts +9 -1
- package/dist/tui-v2/rendering/open-tool-output.js +65 -12
- package/dist/tui-v2/rendering/open-tool-output.js.map +1 -1
- package/dist/tui-v2/rendering/pager-chrome.d.ts +12 -0
- package/dist/tui-v2/rendering/pager-chrome.js +56 -0
- package/dist/tui-v2/rendering/pager-chrome.js.map +1 -0
- package/dist/tui-v2/rendering/plan-view.js +1 -1
- package/dist/tui-v2/rendering/plan-view.js.map +1 -1
- package/dist/tui-v2/rendering/syntax-highlight.d.ts +37 -0
- package/dist/tui-v2/rendering/syntax-highlight.js +1303 -0
- package/dist/tui-v2/rendering/syntax-highlight.js.map +1 -0
- package/dist/tui-v2/rendering/theme.d.ts +28 -0
- package/dist/tui-v2/rendering/theme.js +28 -0
- package/dist/tui-v2/rendering/theme.js.map +1 -1
- package/dist/tui-v2/rendering/tool-presenter.d.ts +11 -1
- package/dist/tui-v2/rendering/tool-presenter.js +101 -5
- package/dist/tui-v2/rendering/tool-presenter.js.map +1 -1
- package/dist/tui-v2/state/transcript-hydrate.js +5 -0
- package/dist/tui-v2/state/transcript-hydrate.js.map +1 -1
- package/dist/tui-v2/state/transcript-reducer.js +12 -2
- package/dist/tui-v2/state/transcript-reducer.js.map +1 -1
- package/dist/tui-v2/state/transcript-store.d.ts +7 -0
- package/dist/tui-v2/state/transcript-store.js +46 -0
- package/dist/tui-v2/state/transcript-store.js.map +1 -1
- package/dist/tui-v2/state/transcript-types.d.ts +12 -0
- package/dist/tui-v2/state/transcript-types.js +9 -0
- package/dist/tui-v2/state/transcript-types.js.map +1 -1
- package/dist/types.d.ts +75 -1
- package/dist/ui/ansi-box.d.ts +2 -0
- package/dist/ui/ansi-box.js +8 -1
- package/dist/ui/ansi-box.js.map +1 -1
- package/dist/ui/mentions.d.ts +6 -0
- package/dist/ui/mentions.js +50 -12
- package/dist/ui/mentions.js.map +1 -1
- package/dist/ui/plan-pane.js +1 -1
- package/dist/ui/plan-pane.js.map +1 -1
- package/package.json +16 -11
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/** Max argument JSON size while streaming (~32 MB). */
|
|
2
|
+
export const MAX_TOOL_ARG_BYTES = 32 * 1024 * 1024;
|
|
3
|
+
/** Primary wire form: dots → underscores, keep camelCase (fs.writeMany → fs_writeMany). */
|
|
4
|
+
export function toWireName(canonical) {
|
|
5
|
+
return canonical.replace(/\./g, "_");
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Full snake_case wire form models sometimes emit
|
|
9
|
+
* (fs.writeMany → fs_write_many). Used as a reverse alias only.
|
|
10
|
+
*/
|
|
11
|
+
export function toSnakeWireName(canonical) {
|
|
12
|
+
return canonical
|
|
13
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1_$2")
|
|
14
|
+
.replace(/\./g, "_")
|
|
15
|
+
.toLowerCase();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Reverse wire → canonical for known tools. Unknown wires return undefined
|
|
19
|
+
* so the runner can surface a clear error.
|
|
20
|
+
*/
|
|
21
|
+
const wireToCanonical = new Map();
|
|
22
|
+
export function registerWireName(canonical, wire) {
|
|
23
|
+
const w = wire ?? toWireName(canonical);
|
|
24
|
+
wireToCanonical.set(w, canonical);
|
|
25
|
+
}
|
|
26
|
+
/** Register primary wire + snake_case alias when they differ. */
|
|
27
|
+
export function registerWireNamesFor(canonical) {
|
|
28
|
+
const wire = toWireName(canonical);
|
|
29
|
+
registerWireName(canonical, wire);
|
|
30
|
+
const snake = toSnakeWireName(canonical);
|
|
31
|
+
if (snake !== wire) {
|
|
32
|
+
registerWireName(canonical, snake);
|
|
33
|
+
}
|
|
34
|
+
return wire;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Strip model channel / commentary / XML junk from tool names
|
|
38
|
+
* (e.g. `fs.write<|channel|>commentary` → `fs.write`).
|
|
39
|
+
*/
|
|
40
|
+
export function sanitizeToolName(raw) {
|
|
41
|
+
let n = raw.trim();
|
|
42
|
+
if (!n)
|
|
43
|
+
return n;
|
|
44
|
+
// GPT-OSS / channel style: <|channel|>, <|tool_call_begin|>, …
|
|
45
|
+
n = n.replace(/<\|[^|]*\|>/g, "");
|
|
46
|
+
// XML-ish tags
|
|
47
|
+
n = n.replace(/<\/?[A-Za-z][^>]*>/g, "");
|
|
48
|
+
n = n.replace(/^(?:functions\.|tools\.|tool\.)/i, "");
|
|
49
|
+
n = n.replace(/:\d+$/, "");
|
|
50
|
+
// Drop trailing non-name junk after a clean dotted/underscored stem
|
|
51
|
+
n = n.replace(/[^A-Za-z0-9._-]+.*$/, "");
|
|
52
|
+
// Role words models glue after tags (fs.writecommentary)
|
|
53
|
+
n = n.replace(/(?:commentary|analysis|channel|tool_call|toolcall|final)$/i, "");
|
|
54
|
+
n = n.replace(/(?:[_./-]+(?:commentary|analysis|channel|final))+$/i, "");
|
|
55
|
+
n = n.trim().replace(/^[_./-]+|[_./-]+$/g, "");
|
|
56
|
+
return n;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Longest registered wire/canonical prefix match for polluted names.
|
|
60
|
+
* e.g. `fs_write_channel_commentary` → `fs_write` if registered.
|
|
61
|
+
*/
|
|
62
|
+
function longestRegisteredPrefix(cleaned) {
|
|
63
|
+
if (!cleaned)
|
|
64
|
+
return undefined;
|
|
65
|
+
if (wireToCanonical.has(cleaned))
|
|
66
|
+
return cleaned;
|
|
67
|
+
// Try stripping trailing segments after _ or .
|
|
68
|
+
let best;
|
|
69
|
+
for (const [wire] of wireToCanonical) {
|
|
70
|
+
if (cleaned === wire ||
|
|
71
|
+
cleaned.startsWith(wire + "_") ||
|
|
72
|
+
cleaned.startsWith(wire + ".") ||
|
|
73
|
+
cleaned.startsWith(wire + "<")) {
|
|
74
|
+
if (!best || wire.length > best.length)
|
|
75
|
+
best = wire;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return best;
|
|
79
|
+
}
|
|
80
|
+
export function fromWireName(wire) {
|
|
81
|
+
const cleaned = sanitizeToolName(wire);
|
|
82
|
+
if (!cleaned)
|
|
83
|
+
return undefined;
|
|
84
|
+
if (wireToCanonical.has(cleaned))
|
|
85
|
+
return wireToCanonical.get(cleaned);
|
|
86
|
+
// Polluted name that still starts with a registered wire form
|
|
87
|
+
const prefix = longestRegisteredPrefix(cleaned);
|
|
88
|
+
if (prefix)
|
|
89
|
+
return wireToCanonical.get(prefix);
|
|
90
|
+
// Also try original if sanitize changed nothing useful
|
|
91
|
+
if (wireToCanonical.has(wire))
|
|
92
|
+
return wireToCanonical.get(wire);
|
|
93
|
+
// Fallback: underscore → first-dot heuristic for unregistered names.
|
|
94
|
+
if (cleaned.includes("."))
|
|
95
|
+
return cleaned;
|
|
96
|
+
const idx = cleaned.indexOf("_");
|
|
97
|
+
if (idx <= 0)
|
|
98
|
+
return undefined;
|
|
99
|
+
return `${cleaned.slice(0, idx)}.${cleaned.slice(idx + 1).replace(/_/g, ".")}`;
|
|
100
|
+
}
|
|
101
|
+
export function parseToolArguments(raw) {
|
|
102
|
+
if (raw == null)
|
|
103
|
+
return {};
|
|
104
|
+
if (typeof raw === "object" && !Array.isArray(raw)) {
|
|
105
|
+
return raw;
|
|
106
|
+
}
|
|
107
|
+
if (typeof raw === "string") {
|
|
108
|
+
const t = raw.trim();
|
|
109
|
+
if (!t)
|
|
110
|
+
return {};
|
|
111
|
+
try {
|
|
112
|
+
const parsed = JSON.parse(t);
|
|
113
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
114
|
+
return parsed;
|
|
115
|
+
}
|
|
116
|
+
return { _parseError: true, _raw: t };
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return { _parseError: true, _raw: t };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
let syntheticToolCallSequence = 0;
|
|
125
|
+
export function syntheticToolCallId(index) {
|
|
126
|
+
syntheticToolCallSequence += 1;
|
|
127
|
+
return `call_${index}_${Date.now().toString(36)}_${syntheticToolCallSequence.toString(36)}`;
|
|
128
|
+
}
|
|
129
|
+
export function isToolsUnsupportedError(error) {
|
|
130
|
+
const status = error && typeof error === "object" && "status" in error
|
|
131
|
+
? Number(error.status)
|
|
132
|
+
: undefined;
|
|
133
|
+
const body = error && typeof error === "object" && "body" in error
|
|
134
|
+
? String(error.body ?? "")
|
|
135
|
+
: "";
|
|
136
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
137
|
+
const hay = `${message}\n${body}`.toLowerCase();
|
|
138
|
+
// Explicit capability rejections (any HTTP status).
|
|
139
|
+
if (/tools?\s+(is|are)\s+not\s+supported|does not support tools|function calling is not enabled|tool[_ ]?use is not supported|tools? not supported|tool calling is not supported|does not support function|function[_ ]?call(ing)? (is )?(not supported|disabled|unavailable)|unknown (request )?parameter ['"]?tools?|['"]tools?['"] is not (a )?valid|tool_choice.*(not supported|unknown|disabled)/i.test(hay)) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
// 400 bodies that mention tools — only when they clearly mean unsupported.
|
|
143
|
+
// Do NOT treat schema/arg validation as unsupported (no bare /tool/i).
|
|
144
|
+
if (status === 400 &&
|
|
145
|
+
/\btools?\b|\btool_choice\b|\bfunction[_ ]?call/i.test(hay)) {
|
|
146
|
+
if (/invalid schema|invalid argument|missing required|parse error|type error|validation|must be|expected/i.test(hay)) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
return /not support|unsupported|disabled|not enabled|not available|unknown parameter|unrecognized/i.test(hay);
|
|
150
|
+
}
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
export function mapToolChoiceToOpenAi(choice) {
|
|
154
|
+
if (choice === undefined || choice === "auto")
|
|
155
|
+
return "auto";
|
|
156
|
+
if (choice === "none")
|
|
157
|
+
return "none";
|
|
158
|
+
if (choice === "required")
|
|
159
|
+
return "required";
|
|
160
|
+
if (typeof choice === "object" && choice.type === "function") {
|
|
161
|
+
return {
|
|
162
|
+
type: "function",
|
|
163
|
+
function: { name: toWireName(choice.name) },
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return "auto";
|
|
167
|
+
}
|
|
168
|
+
export function mapToolChoiceToAnthropic(choice) {
|
|
169
|
+
if (choice === undefined || choice === "auto")
|
|
170
|
+
return { type: "auto" };
|
|
171
|
+
if (choice === "none")
|
|
172
|
+
return { type: "none" };
|
|
173
|
+
if (choice === "required")
|
|
174
|
+
return { type: "any" };
|
|
175
|
+
if (typeof choice === "object" && choice.type === "function") {
|
|
176
|
+
return { type: "tool", name: toWireName(choice.name) };
|
|
177
|
+
}
|
|
178
|
+
return { type: "auto" };
|
|
179
|
+
}
|
|
180
|
+
export function mapToolChoiceToGemini(choice) {
|
|
181
|
+
if (choice === "none")
|
|
182
|
+
return { mode: "NONE" };
|
|
183
|
+
if (choice === "required")
|
|
184
|
+
return { mode: "ANY" };
|
|
185
|
+
if (typeof choice === "object" && choice.type === "function") {
|
|
186
|
+
return {
|
|
187
|
+
mode: "ANY",
|
|
188
|
+
allowedFunctionNames: [toWireName(choice.name)],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
return { mode: "AUTO" };
|
|
192
|
+
}
|
|
193
|
+
/** Session-sticky models forced to text protocol after tools-unsupported. */
|
|
194
|
+
const textOnlyModels = new Set();
|
|
195
|
+
export function textOnlyKey(provider, model) {
|
|
196
|
+
return `${provider}::${model}`;
|
|
197
|
+
}
|
|
198
|
+
export function markTextOnlyModel(provider, model) {
|
|
199
|
+
textOnlyModels.add(textOnlyKey(provider, model));
|
|
200
|
+
}
|
|
201
|
+
export function isTextOnlyModel(provider, model) {
|
|
202
|
+
return textOnlyModels.has(textOnlyKey(provider, model));
|
|
203
|
+
}
|
|
204
|
+
export function clearTextOnlyModels() {
|
|
205
|
+
textOnlyModels.clear();
|
|
206
|
+
}
|
|
207
|
+
/** Accumulate OpenAI-style streaming tool_calls deltas by index. */
|
|
208
|
+
export function accumulateOpenAiToolCallDelta(state, entry) {
|
|
209
|
+
const index = entry.index ?? 0;
|
|
210
|
+
let acc = state.get(index);
|
|
211
|
+
if (!acc) {
|
|
212
|
+
acc = { arguments: "" };
|
|
213
|
+
state.set(index, acc);
|
|
214
|
+
}
|
|
215
|
+
const hadName = Boolean(acc.name);
|
|
216
|
+
if (entry.id)
|
|
217
|
+
acc.id = entry.id;
|
|
218
|
+
if (entry.function?.name) {
|
|
219
|
+
const nextName = sanitizeToolName(entry.function.name) || entry.function.name;
|
|
220
|
+
// X2: if this index already has a different clean name, do not clobber
|
|
221
|
+
// args with a second tool's payload — keep the first name.
|
|
222
|
+
if (acc.name &&
|
|
223
|
+
nextName &&
|
|
224
|
+
acc.name !== nextName &&
|
|
225
|
+
sanitizeToolName(acc.name) !== sanitizeToolName(nextName)) {
|
|
226
|
+
// Ignore subsequent name flips on the same index (stream corruption).
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
acc.name = nextName;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (typeof entry.function?.arguments === "string") {
|
|
233
|
+
acc.arguments += entry.function.arguments;
|
|
234
|
+
if (acc.arguments.length > MAX_TOOL_ARG_BYTES) {
|
|
235
|
+
throw new Error(`Tool call arguments exceeded ${MAX_TOOL_ARG_BYTES} bytes — split the file or reduce content size.`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
index,
|
|
240
|
+
...(acc.id !== undefined ? { id: acc.id } : {}),
|
|
241
|
+
...(acc.name !== undefined ? { name: acc.name } : {}),
|
|
242
|
+
nameBecameKnown: Boolean(acc.name) && !hadName,
|
|
243
|
+
argumentsBytes: acc.arguments.length,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
export function finalizeOpenAiToolCalls(state) {
|
|
247
|
+
const indices = [...state.keys()].sort((a, b) => a - b);
|
|
248
|
+
const out = [];
|
|
249
|
+
for (const index of indices) {
|
|
250
|
+
const acc = state.get(index);
|
|
251
|
+
const wire = acc.name ?? "";
|
|
252
|
+
const canonical = fromWireName(wire) ?? wire;
|
|
253
|
+
const rawArguments = acc.arguments;
|
|
254
|
+
const args = parseToolArguments(rawArguments);
|
|
255
|
+
out.push({
|
|
256
|
+
id: acc.id ?? syntheticToolCallId(index),
|
|
257
|
+
name: canonical,
|
|
258
|
+
args,
|
|
259
|
+
...(rawArguments ? { rawArguments } : {}),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
}
|
|
264
|
+
export function parseOpenAiMessageToolCalls(toolCalls) {
|
|
265
|
+
if (!toolCalls?.length)
|
|
266
|
+
return [];
|
|
267
|
+
return toolCalls.map((tc, i) => {
|
|
268
|
+
const wire = tc.function?.name ?? "";
|
|
269
|
+
const rawArguments = tc.function?.arguments ?? "";
|
|
270
|
+
return {
|
|
271
|
+
id: tc.id ?? syntheticToolCallId(i),
|
|
272
|
+
name: fromWireName(wire) ?? wire,
|
|
273
|
+
args: parseToolArguments(rawArguments),
|
|
274
|
+
...(rawArguments ? { rawArguments } : {}),
|
|
275
|
+
};
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
//# sourceMappingURL=tool-protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-protocol.js","sourceRoot":"","sources":["../../src/llm/tool-protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/modes/agent.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ChatMessage, ChatImage, ProviderId, ToolCall } from "../types.js";
|
|
1
|
+
import type { ChatMessage, ChatImage, Mode, ProviderId, ToolCall } from "../types.js";
|
|
2
2
|
import type { AgentEvent } from "../agent/events.js";
|
|
3
3
|
import { parseToolCall, createSessionPolicy, type ConfirmPort, type SessionPolicy } from "../agent/runner.js";
|
|
4
4
|
export interface AgentOptions {
|
|
@@ -23,6 +23,7 @@ export interface AgentOptions {
|
|
|
23
23
|
onEvent?: ((event: AgentEvent) => void) | undefined;
|
|
24
24
|
onMessages?: ((messages: ChatMessage[]) => void) | undefined;
|
|
25
25
|
confirm?: ConfirmPort | undefined;
|
|
26
|
+
mode?: Mode | undefined;
|
|
26
27
|
}
|
|
27
28
|
export { parseToolCall, createSessionPolicy };
|
|
28
29
|
export type { SessionPolicy };
|
package/dist/modes/agent.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { renderTurnOutcome } from "../agent/turn-outcome.js";
|
|
2
|
+
import { runAgentTurn, parseToolCall, createSessionPolicy, } from "../agent/runner.js";
|
|
2
3
|
export { parseToolCall, createSessionPolicy };
|
|
3
4
|
export async function runAgent(prompt, options = {}) {
|
|
4
|
-
|
|
5
|
+
const outcome = await runAgentTurn(prompt, options);
|
|
6
|
+
return renderTurnOutcome(outcome);
|
|
5
7
|
}
|
|
6
8
|
//# sourceMappingURL=agent.js.map
|
package/dist/modes/agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/modes/agent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/modes/agent.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EACL,YAAY,EACZ,aAAa,EACb,mBAAmB,GAGpB,MAAM,oBAAoB,CAAC;AAyB5B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC;AAG9C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAc,EACd,UAAwB,EAAE;IAE1B,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpD,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC"}
|
package/dist/modes/ask.d.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import type { ChatMessage, ChatImage, ProviderId } from "../types.js";
|
|
2
2
|
import type { AgentEvent } from "../agent/events.js";
|
|
3
|
-
/**
|
|
4
|
-
* Signal raised when the model, while in ask mode, tries to call a mutating
|
|
5
|
-
* tool (run a command, write a file, install a package, …). Ask mode is
|
|
6
|
-
* read-only, so instead of leaking the raw tool-call JSON as the "answer" we
|
|
7
|
-
* surface this so the caller can offer to switch into agent mode.
|
|
8
|
-
*/
|
|
9
3
|
export interface AskActionRequired {
|
|
10
4
|
/** The original prompt, so the caller can re-run it in agent mode. */
|
|
11
5
|
prompt: string;
|
|
@@ -20,19 +14,7 @@ export interface AskOptions {
|
|
|
20
14
|
history?: ChatMessage[] | undefined;
|
|
21
15
|
signal?: AbortSignal | undefined;
|
|
22
16
|
images?: ChatImage[] | undefined;
|
|
23
|
-
/**
|
|
24
|
-
* Invoked when the task needs actions ask mode can't perform. When set, the
|
|
25
|
-
* research loop returns an empty string and lets the caller drive the
|
|
26
|
-
* follow-up (e.g. prompt to switch to agent mode). When unset, ask mode
|
|
27
|
-
* falls back to a clean explanatory message instead of raw tool-call text.
|
|
28
|
-
*/
|
|
29
17
|
onActionRequired?: ((info: AskActionRequired) => void) | undefined;
|
|
30
|
-
/**
|
|
31
|
-
* Optional event sink for live research activity. Ask mode emits
|
|
32
|
-
* `tool-call`/`tool-result` events for each read-only research tool it runs
|
|
33
|
-
* (web.search, web.fetch, …) so the UI can show what it's searching or
|
|
34
|
-
* fetching, mirroring agent-mode tool cards.
|
|
35
|
-
*/
|
|
36
18
|
onEvent?: ((event: AgentEvent) => void) | undefined;
|
|
37
19
|
}
|
|
38
20
|
export declare function runAsk(prompt: string, options?: AskOptions): Promise<string>;
|
package/dist/modes/ask.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { streamWithProvider } from "../llm/router.js";
|
|
2
|
+
import { resolveToolDialect } from "../llm/capabilities.js";
|
|
3
|
+
import { syntheticToolCallId } from "../llm/tool-protocol.js";
|
|
2
4
|
import { renderAskSystemPrompt } from "../prompts/index.js";
|
|
3
5
|
import { getConfig } from "../store/config.js";
|
|
4
6
|
import { ensureProviderConfigured } from "../commands/providers.js";
|
|
5
7
|
import { loadProjectContext } from "../store/project.js";
|
|
6
8
|
import { parseAllToolCalls, formatToolArgs, looksLikePromptLeak } from "../agent/runner.js";
|
|
7
9
|
import { runToolCall } from "../tools/registry.js";
|
|
10
|
+
import { getToolDefinitions } from "../tools/definitions.js";
|
|
11
|
+
import { appendAssistantWithTools, appendToolResult, } from "../agent/tool-history.js";
|
|
8
12
|
/** Strip tool-call markup so only the model's prose preamble remains. */
|
|
9
13
|
function stripToolCallSyntax(text) {
|
|
10
14
|
return text
|
|
@@ -42,12 +46,6 @@ function researchResultSummary(call, ok) {
|
|
|
42
46
|
return "done";
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Read-only tools ask mode is allowed to call during its research loop.
|
|
47
|
-
* Everything here is non-mutating: web lookups and local file inspection
|
|
48
|
-
* only. Ask mode never runs shell commands, installs packages, or writes
|
|
49
|
-
* files.
|
|
50
|
-
*/
|
|
51
49
|
const ASK_RESEARCH_TOOLS = new Set([
|
|
52
50
|
"web.search",
|
|
53
51
|
"web.fetch",
|
|
@@ -88,17 +86,19 @@ async function buildAskMessages(prompt, options) {
|
|
|
88
86
|
const config = getConfig();
|
|
89
87
|
const provider = options.provider ?? config.defaultProvider;
|
|
90
88
|
await ensureProviderConfigured(provider);
|
|
89
|
+
const model = options.model ?? config.defaultModel;
|
|
91
90
|
const projectContext = await loadProjectContext();
|
|
91
|
+
const native = resolveToolDialect(provider, model, config.toolCalling) !== "none";
|
|
92
92
|
const systemPrompt = projectContext
|
|
93
|
-
? `${renderAskSystemPrompt()}\n\nProject context from .clai/context.md:\n${projectContext}`
|
|
94
|
-
: renderAskSystemPrompt();
|
|
93
|
+
? `${renderAskSystemPrompt({ nativeTools: native })}\n\nProject context from .clai/context.md:\n${projectContext}`
|
|
94
|
+
: renderAskSystemPrompt({ nativeTools: native });
|
|
95
95
|
const userMessage = { role: "user", content: prompt };
|
|
96
96
|
if (options.images && options.images.length > 0) {
|
|
97
97
|
userMessage.images = options.images;
|
|
98
98
|
}
|
|
99
99
|
return {
|
|
100
100
|
provider,
|
|
101
|
-
model
|
|
101
|
+
model,
|
|
102
102
|
messages: [
|
|
103
103
|
{ role: "system", content: systemPrompt },
|
|
104
104
|
...(options.history ?? []),
|
|
@@ -106,13 +106,6 @@ async function buildAskMessages(prompt, options) {
|
|
|
106
106
|
],
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Find where (if anywhere) a tool-call block begins in `text`. Ask mode
|
|
111
|
-
* streams each model round to the live display, but a round may turn out to
|
|
112
|
-
* be a tool call rather than prose. We mirror tokens to the screen only up to
|
|
113
|
-
* the point a tool-call delimiter appears, so raw tool JSON never streams to
|
|
114
|
-
* the user. Returns -1 when no tool-call marker is present.
|
|
115
|
-
*/
|
|
116
109
|
function toolCallStartIndex(text) {
|
|
117
110
|
const indicators = [
|
|
118
111
|
/```\s*tool/i,
|
|
@@ -130,24 +123,18 @@ function toolCallStartIndex(text) {
|
|
|
130
123
|
}
|
|
131
124
|
return min;
|
|
132
125
|
}
|
|
133
|
-
/**
|
|
134
|
-
* Run one model round as a stream, mirroring visible prose tokens to `onToken`
|
|
135
|
-
* as they arrive (so the user sees the answer build up live) while suppressing
|
|
136
|
-
* anything from a tool-call delimiter onward. Returns the round's full raw
|
|
137
|
-
* text so the caller can detect/parse tool calls. Providers without a native
|
|
138
|
-
* stream fall back to a single onToken call inside streamWithProvider.
|
|
139
|
-
*/
|
|
140
126
|
async function streamAskRound(request, messages, onToken) {
|
|
141
127
|
let full = "";
|
|
142
128
|
let forwardedLen = 0;
|
|
143
129
|
let suppressed = false;
|
|
144
|
-
await streamWithProvider({ ...request, messages }, (token) => {
|
|
130
|
+
const completion = await streamWithProvider({ ...request, messages }, (token) => {
|
|
145
131
|
full += token;
|
|
146
132
|
if (suppressed)
|
|
147
133
|
return;
|
|
134
|
+
// When native tools are attached, do not suppress prose on fence markers
|
|
135
|
+
// (there should be none); still suppress if the model emits fences anyway.
|
|
148
136
|
const toolAt = toolCallStartIndex(full);
|
|
149
137
|
if (toolAt >= 0) {
|
|
150
|
-
// Forward only the clean prefix before the tool-call marker, once.
|
|
151
138
|
if (toolAt > forwardedLen)
|
|
152
139
|
onToken(full.slice(forwardedLen, toolAt));
|
|
153
140
|
forwardedLen = full.length;
|
|
@@ -159,23 +146,30 @@ async function streamAskRound(request, messages, onToken) {
|
|
|
159
146
|
forwardedLen = full.length;
|
|
160
147
|
}
|
|
161
148
|
});
|
|
162
|
-
|
|
149
|
+
const text = full || completion.text;
|
|
150
|
+
if (completion.toolCalls?.length) {
|
|
151
|
+
return {
|
|
152
|
+
text,
|
|
153
|
+
toolCalls: completion.toolCalls.map((tc) => ({
|
|
154
|
+
name: tc.name,
|
|
155
|
+
args: tc.args,
|
|
156
|
+
})),
|
|
157
|
+
nativeIds: completion.toolCalls.map((tc) => tc.id),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return { text };
|
|
163
161
|
}
|
|
164
|
-
/**
|
|
165
|
-
* Drive ask mode to its final answer.
|
|
166
|
-
*
|
|
167
|
-
* Ask mode is non-agentic for the user — there is no plan, no confirmations,
|
|
168
|
-
* no system changes — but it MAY ground its answer in current facts via a
|
|
169
|
-
* bounded loop of read-only tools (web.search/web.fetch/tool.batch and
|
|
170
|
-
* read-only fs.*). Each round is streamed to `onToken`: prose answers appear
|
|
171
|
-
* live, and rounds that turn out to be tool calls are suppressed mid-stream so
|
|
172
|
-
* raw tool JSON never reaches the screen. The returned string is always the
|
|
173
|
-
* clean final answer, which callers treat as authoritative even if the live
|
|
174
|
-
* stream briefly showed a tool-call preamble.
|
|
175
|
-
*/
|
|
176
162
|
async function resolveAskAnswer(originalPrompt, provider, model, messages, options, onToken) {
|
|
177
163
|
const config = getConfig();
|
|
178
164
|
const maxTokens = config.thinking?.enabled ? 8_192 : 4_096;
|
|
165
|
+
const native = resolveToolDialect(provider, model, config.toolCalling) !== "none";
|
|
166
|
+
// Research tools + agent.handoff (meta; not executed as research — action UX).
|
|
167
|
+
const askDefs = native
|
|
168
|
+
? [
|
|
169
|
+
...getToolDefinitions({ askMode: true }).filter((d) => ASK_RESEARCH_TOOLS.has(d.name)),
|
|
170
|
+
...getToolDefinitions({ names: ["agent.handoff"] }),
|
|
171
|
+
]
|
|
172
|
+
: undefined;
|
|
179
173
|
const baseRequest = {
|
|
180
174
|
provider,
|
|
181
175
|
model,
|
|
@@ -183,6 +177,9 @@ async function resolveAskAnswer(originalPrompt, provider, model, messages, optio
|
|
|
183
177
|
maxTokens,
|
|
184
178
|
thinking: config.thinking,
|
|
185
179
|
...(options.signal ? { signal: options.signal } : {}),
|
|
180
|
+
...(askDefs?.length
|
|
181
|
+
? { tools: askDefs, toolChoice: "auto" }
|
|
182
|
+
: {}),
|
|
186
183
|
};
|
|
187
184
|
// Surface research activity (web.search/web.fetch/…) to the UI as tool
|
|
188
185
|
// events so the user can see what's being searched/fetched.
|
|
@@ -219,34 +216,26 @@ async function resolveAskAnswer(originalPrompt, provider, model, messages, optio
|
|
|
219
216
|
role: "user",
|
|
220
217
|
content: `Fresh web.search was run before answering because the user requested current/web-backed information.\n` +
|
|
221
218
|
`Query: ${query}\nResult:\n${truncateToolOutput(output, "web.search")}\n\n` +
|
|
222
|
-
"Answer from these current results.
|
|
219
|
+
"Answer from these current results. Prefer high-trust hosts (.gov, major news). Treat a single junk/contradictory snippet as unverified until confirmed. If insufficient, call web.search/web.fetch again before answering. Your final answer MUST cite 1–3 URLs from tool results.",
|
|
223
220
|
});
|
|
224
221
|
}
|
|
225
222
|
for (let round = 0; round < ASK_MAX_RESEARCH_ROUNDS; round += 1) {
|
|
226
223
|
options.signal?.throwIfAborted();
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
// If the model's response contains distinctive system-prompt markers,
|
|
230
|
-
// it is repeating its instructions (e.g. in response to "repeat your
|
|
231
|
-
// instructions verbatim"). Any ```tool blocks in that output are
|
|
232
|
-
// EXAMPLES from the prompt, not real tool requests. Treat the whole
|
|
233
|
-
// response as a final text answer to avoid executing stale examples.
|
|
224
|
+
const roundResult = await streamAskRound(baseRequest, messages, onToken);
|
|
225
|
+
const text = roundResult.text;
|
|
234
226
|
if (looksLikePromptLeak(text)) {
|
|
235
227
|
return text;
|
|
236
228
|
}
|
|
237
|
-
|
|
229
|
+
// Prefer native toolCalls; fall back to text fences.
|
|
230
|
+
const allCalls = roundResult.toolCalls?.length
|
|
231
|
+
? roundResult.toolCalls
|
|
232
|
+
: parseAllToolCalls(text);
|
|
233
|
+
const nativeIds = roundResult.nativeIds ??
|
|
234
|
+
allCalls.map((_, i) => syntheticToolCallId(i));
|
|
238
235
|
const calls = allCalls.filter((call) => ASK_RESEARCH_TOOLS.has(call.name));
|
|
239
236
|
if (calls.length === 0) {
|
|
240
|
-
// No allowed research tool requested. If the model instead asked for a
|
|
241
|
-
// mutating/action tool, this is an agent task — surface it rather than
|
|
242
|
-
// returning the raw tool-call JSON as the answer.
|
|
243
237
|
const actionCalls = allCalls.filter((call) => !ASK_RESEARCH_TOOLS.has(call.name));
|
|
244
238
|
if (actionCalls.length > 0) {
|
|
245
|
-
// The model signals it wants to act either via an explicit
|
|
246
|
-
// `agent.handoff` call (preferred — see the ask system prompt) or by
|
|
247
|
-
// emitting a real mutating tool call. Pull the reason out of a handoff
|
|
248
|
-
// when present, and never surface "agent.handoff" itself as a tool the
|
|
249
|
-
// user would recognize.
|
|
250
239
|
const handoff = actionCalls.find((call) => call.name === "agent.handoff" || call.name === "agent.run");
|
|
251
240
|
const reason = handoff && typeof handoff.args.reason === "string"
|
|
252
241
|
? handoff.args.reason.trim()
|
|
@@ -279,8 +268,19 @@ async function resolveAskAnswer(originalPrompt, provider, model, messages, optio
|
|
|
279
268
|
}
|
|
280
269
|
// Record the model's tool-call turn, then run the read-only tools and
|
|
281
270
|
// feed their outputs back so the next round can synthesize.
|
|
282
|
-
|
|
283
|
-
|
|
271
|
+
if (roundResult.toolCalls?.length) {
|
|
272
|
+
appendAssistantWithTools(messages, stripToolCallSyntax(text), roundResult.toolCalls.map((c, i) => ({
|
|
273
|
+
id: nativeIds[i] ?? syntheticToolCallId(i),
|
|
274
|
+
name: c.name,
|
|
275
|
+
args: c.args,
|
|
276
|
+
})));
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
messages.push({ role: "assistant", content: text });
|
|
280
|
+
}
|
|
281
|
+
for (const [callIndex, call] of calls
|
|
282
|
+
.slice(0, ASK_MAX_TOOLS_PER_ROUND)
|
|
283
|
+
.entries()) {
|
|
284
284
|
options.signal?.throwIfAborted();
|
|
285
285
|
const id = `ask-${(toolSeq += 1)}`;
|
|
286
286
|
emit({
|
|
@@ -308,19 +308,27 @@ async function resolveAskAnswer(originalPrompt, provider, model, messages, optio
|
|
|
308
308
|
ok,
|
|
309
309
|
summary: researchResultSummary(call, ok),
|
|
310
310
|
});
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
311
|
+
const resultBody = `Result of ${call.name}(${JSON.stringify(call.args)}):\n${truncateToolOutput(output, call.name)}`;
|
|
312
|
+
if (roundResult.toolCalls?.length) {
|
|
313
|
+
const sourceIndex = allCalls.indexOf(call);
|
|
314
|
+
appendToolResult(messages, nativeIds[sourceIndex] ?? syntheticToolCallId(callIndex), resultBody, call.name, ok);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
messages.push({
|
|
318
|
+
role: "user",
|
|
319
|
+
content: resultBody,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
315
322
|
}
|
|
316
323
|
}
|
|
317
324
|
// Round cap reached — force a tool-free final answer from what we gathered.
|
|
318
325
|
options.signal?.throwIfAborted();
|
|
319
326
|
messages.push({
|
|
320
327
|
role: "user",
|
|
321
|
-
content: "Stop researching now. Using only what you have already gathered above, give your final answer to the original question. Do NOT call any more tools.",
|
|
328
|
+
content: "Stop researching now. Using only what you have already gathered above, give your final answer to the original question. Do NOT call any more tools. Prefer high-trust sources; only claim a page confirms a fact if that fact appears in the tool output; include 1–3 source URLs from the results above.",
|
|
322
329
|
});
|
|
323
|
-
|
|
330
|
+
const finalRound = await streamAskRound(baseRequest, messages, onToken);
|
|
331
|
+
return finalRound.text;
|
|
324
332
|
}
|
|
325
333
|
export async function runAsk(prompt, options = {}) {
|
|
326
334
|
const request = await buildAskMessages(prompt, options);
|
|
@@ -329,9 +337,6 @@ export async function runAsk(prompt, options = {}) {
|
|
|
329
337
|
}
|
|
330
338
|
export async function runAskStream(prompt, onToken, options = {}) {
|
|
331
339
|
const request = await buildAskMessages(prompt, options);
|
|
332
|
-
// The answer is streamed to onToken live (with tool-call rounds suppressed),
|
|
333
|
-
// and the returned string is the authoritative final answer for callers that
|
|
334
|
-
// commit/persist it.
|
|
335
340
|
return resolveAskAnswer(prompt, request.provider, request.model, request.messages, options, onToken);
|
|
336
341
|
}
|
|
337
342
|
//# sourceMappingURL=ask.js.map
|