@pentoshi/clai 4.8.4 → 4.10.0
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 +91 -4
- package/dist/agent/compaction-executor.d.ts +3 -5
- package/dist/agent/compaction-executor.js +165 -28
- package/dist/agent/compaction-executor.js.map +1 -1
- package/dist/agent/finalize-gate.js +0 -9
- package/dist/agent/finalize-gate.js.map +1 -1
- package/dist/agent/plan-mode-reminders.js +5 -5
- package/dist/agent/plan-mode-reminders.js.map +1 -1
- package/dist/agent/plan-tool.d.ts +1 -0
- package/dist/agent/plan-tool.js +50 -21
- package/dist/agent/plan-tool.js.map +1 -1
- package/dist/agent/reliability-policy.d.ts +9 -0
- package/dist/agent/reliability-policy.js +36 -1
- package/dist/agent/reliability-policy.js.map +1 -1
- package/dist/agent/runner.d.ts +4 -0
- package/dist/agent/runner.js +193 -116
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/task-analyzer.d.ts +8 -18
- package/dist/agent/task-analyzer.js +75 -182
- package/dist/agent/task-analyzer.js.map +1 -1
- package/dist/agent/task-evidence.js +10 -0
- package/dist/agent/task-evidence.js.map +1 -1
- package/dist/agent/tool-call-parser.js +14 -13
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/app/adapters/current-agent-adapter.d.ts +5 -1
- package/dist/app/adapters/current-agent-adapter.js +2 -1
- package/dist/app/adapters/current-agent-adapter.js.map +1 -1
- package/dist/app/commands/catalog.js +10 -0
- package/dist/app/commands/catalog.js.map +1 -1
- package/dist/app/commands/registry.js +1 -0
- package/dist/app/commands/registry.js.map +1 -1
- package/dist/app/controllers/session-compact-helper.js +3 -6
- package/dist/app/controllers/session-compact-helper.js.map +1 -1
- package/dist/app/ports/transcript-item.d.ts +4 -0
- package/dist/classic/app/ClassicApp.js +1 -1
- package/dist/classic/app/ClassicApp.js.map +1 -1
- package/dist/classic/app/action-handlers.js +4 -0
- package/dist/classic/app/action-handlers.js.map +1 -1
- package/dist/classic/app/app-wiring.js +1 -0
- package/dist/classic/app/app-wiring.js.map +1 -1
- package/dist/classic/app/wiring-lifecycle.js +1 -0
- package/dist/classic/app/wiring-lifecycle.js.map +1 -1
- package/dist/classic/blocks/compacted-lines.js +3 -0
- package/dist/classic/blocks/compacted-lines.js.map +1 -1
- package/dist/classic/blocks/thinking-lines.js +11 -2
- package/dist/classic/blocks/thinking-lines.js.map +1 -1
- package/dist/classic/bootstrap/start-classic.d.ts +1 -0
- package/dist/classic/bootstrap/start-classic.js +16 -0
- package/dist/classic/bootstrap/start-classic.js.map +1 -1
- package/dist/classic/chrome/Composer.d.ts +6 -0
- package/dist/classic/chrome/Composer.js +2 -3
- package/dist/classic/chrome/Composer.js.map +1 -1
- package/dist/classic/chrome/composer-controller.d.ts +6 -1
- package/dist/classic/chrome/composer-controller.js +18 -8
- package/dist/classic/chrome/composer-controller.js.map +1 -1
- package/dist/classic/chrome/editor-view.d.ts +2 -1
- package/dist/classic/chrome/editor-view.js +1 -1
- package/dist/classic/chrome/editor-view.js.map +1 -1
- package/dist/classic/chrome/status-rows.js +3 -2
- package/dist/classic/chrome/status-rows.js.map +1 -1
- package/dist/classic/panels/TextEditorPanel.d.ts +3 -0
- package/dist/classic/panels/TextEditorPanel.js +7 -0
- package/dist/classic/panels/TextEditorPanel.js.map +1 -0
- package/dist/classic/panels/panel-controller.js +28 -1
- package/dist/classic/panels/panel-controller.js.map +1 -1
- package/dist/classic/panels/panel-effect.d.ts +3 -0
- package/dist/classic/panels/panel-effect.js.map +1 -1
- package/dist/classic/panels/panel-effects.js +3 -0
- package/dist/classic/panels/panel-effects.js.map +1 -1
- package/dist/classic/panels/panel-host.js +3 -0
- package/dist/classic/panels/panel-host.js.map +1 -1
- package/dist/classic/panels/panel-types.d.ts +2 -0
- package/dist/classic/panels/secret-panel.d.ts +1 -1
- package/dist/classic/panels/secret-panel.js +4 -2
- package/dist/classic/panels/secret-panel.js.map +1 -1
- package/dist/classic/panels/text-editor-panel.d.ts +33 -0
- package/dist/classic/panels/text-editor-panel.js +101 -0
- package/dist/classic/panels/text-editor-panel.js.map +1 -0
- package/dist/index.js +60 -7
- package/dist/index.js.map +1 -1
- package/dist/interactive-session/transport-node-pty.d.ts +10 -1
- package/dist/interactive-session/transport-node-pty.js +36 -12
- package/dist/interactive-session/transport-node-pty.js.map +1 -1
- package/dist/llm/adapters/anthropic-tools.d.ts +2 -1
- package/dist/llm/adapters/anthropic-tools.js +55 -4
- package/dist/llm/adapters/anthropic-tools.js.map +1 -1
- package/dist/llm/anthropic.js +1 -1
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/aws-mantle.js +2 -0
- package/dist/llm/aws-mantle.js.map +1 -1
- package/dist/llm/meta.js +62 -68
- package/dist/llm/meta.js.map +1 -1
- package/dist/llm/operation-ledger.js +6 -2
- package/dist/llm/operation-ledger.js.map +1 -1
- package/dist/llm/provider.js +7 -7
- package/dist/llm/request-plan.js +7 -2
- package/dist/llm/request-plan.js.map +1 -1
- package/dist/llm/tool-protocol.d.ts +1 -0
- package/dist/llm/tool-protocol.js +7 -0
- package/dist/llm/tool-protocol.js.map +1 -1
- package/dist/mcp/client.d.ts +27 -0
- package/dist/mcp/client.js +119 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/config-file.d.ts +35 -0
- package/dist/mcp/config-file.js +217 -0
- package/dist/mcp/config-file.js.map +1 -0
- package/dist/mcp/discovery.d.ts +4 -0
- package/dist/mcp/discovery.js +409 -0
- package/dist/mcp/discovery.js.map +1 -0
- package/dist/mcp/format.d.ts +17 -0
- package/dist/mcp/format.js +122 -0
- package/dist/mcp/format.js.map +1 -0
- package/dist/mcp/index.d.ts +15 -0
- package/dist/mcp/index.js +16 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/jsonrpc.d.ts +40 -0
- package/dist/mcp/jsonrpc.js +175 -0
- package/dist/mcp/jsonrpc.js.map +1 -0
- package/dist/mcp/manager.d.ts +36 -0
- package/dist/mcp/manager.js +300 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/mentions.d.ts +9 -0
- package/dist/mcp/mentions.js +44 -0
- package/dist/mcp/mentions.js.map +1 -0
- package/dist/mcp/names.d.ts +15 -0
- package/dist/mcp/names.js +59 -0
- package/dist/mcp/names.js.map +1 -0
- package/dist/mcp/results.d.ts +6 -0
- package/dist/mcp/results.js +182 -0
- package/dist/mcp/results.js.map +1 -0
- package/dist/mcp/runtime.d.ts +107 -0
- package/dist/mcp/runtime.js +505 -0
- package/dist/mcp/runtime.js.map +1 -0
- package/dist/mcp/substitution.d.ts +13 -0
- package/dist/mcp/substitution.js +74 -0
- package/dist/mcp/substitution.js.map +1 -0
- package/dist/mcp/transport-http.d.ts +53 -0
- package/dist/mcp/transport-http.js +433 -0
- package/dist/mcp/transport-http.js.map +1 -0
- package/dist/mcp/transport-stdio.d.ts +39 -0
- package/dist/mcp/transport-stdio.js +268 -0
- package/dist/mcp/transport-stdio.js.map +1 -0
- package/dist/mcp/transport.d.ts +20 -0
- package/dist/mcp/transport.js +44 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/mcp/types.d.ts +179 -0
- package/dist/mcp/types.js +30 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/mcp/validation.d.ts +16 -0
- package/dist/mcp/validation.js +222 -0
- package/dist/mcp/validation.js.map +1 -0
- package/dist/modes/agent.d.ts +2 -0
- package/dist/modes/agent.js.map +1 -1
- package/dist/noninteractive/start-noninteractive.js +4 -0
- package/dist/noninteractive/start-noninteractive.js.map +1 -1
- package/dist/prompts/embedded.js +2 -2
- package/dist/prompts/embedded.js.map +1 -1
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.js +70 -55
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/system.agent.md +34 -10
- package/dist/prompts/system.ask.md +8 -0
- package/dist/safety/classifier.js +4 -0
- package/dist/safety/classifier.js.map +1 -1
- package/dist/session-runtime/binding.d.ts +5 -0
- package/dist/session-runtime/binding.js +28 -0
- package/dist/session-runtime/binding.js.map +1 -0
- package/dist/session-runtime/child-bridge.d.ts +31 -0
- package/dist/session-runtime/child-bridge.js +169 -0
- package/dist/session-runtime/child-bridge.js.map +1 -0
- package/dist/session-runtime/client.d.ts +8 -0
- package/dist/session-runtime/client.js +448 -0
- package/dist/session-runtime/client.js.map +1 -0
- package/dist/session-runtime/discovery.d.ts +6 -0
- package/dist/session-runtime/discovery.js +100 -0
- package/dist/session-runtime/discovery.js.map +1 -0
- package/dist/session-runtime/host.d.ts +77 -0
- package/dist/session-runtime/host.js +758 -0
- package/dist/session-runtime/host.js.map +1 -0
- package/dist/session-runtime/launch.d.ts +11 -0
- package/dist/session-runtime/launch.js +68 -0
- package/dist/session-runtime/launch.js.map +1 -0
- package/dist/session-runtime/paths.d.ts +8 -0
- package/dist/session-runtime/paths.js +92 -0
- package/dist/session-runtime/paths.js.map +1 -0
- package/dist/session-runtime/protocol.d.ts +22 -0
- package/dist/session-runtime/protocol.js +149 -0
- package/dist/session-runtime/protocol.js.map +1 -0
- package/dist/session-runtime/replay-buffer.d.ts +12 -0
- package/dist/session-runtime/replay-buffer.js +50 -0
- package/dist/session-runtime/replay-buffer.js.map +1 -0
- package/dist/session-runtime/store.d.ts +14 -0
- package/dist/session-runtime/store.js +143 -0
- package/dist/session-runtime/store.js.map +1 -0
- package/dist/session-runtime/types.d.ts +102 -0
- package/dist/session-runtime/types.js +2 -0
- package/dist/session-runtime/types.js.map +1 -0
- package/dist/store/logs.js +17 -6
- package/dist/store/logs.js.map +1 -1
- package/dist/store/plan.d.ts +2 -0
- package/dist/store/plan.js.map +1 -1
- package/dist/store/session-workspace.js +2 -1
- package/dist/store/session-workspace.js.map +1 -1
- package/dist/tools/definitions.js +18 -0
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/external-tools.d.ts +30 -0
- package/dist/tools/external-tools.js +52 -0
- package/dist/tools/external-tools.js.map +1 -0
- package/dist/tools/registry.js +36 -5
- package/dist/tools/registry.js.map +1 -1
- package/dist/tui-v2/bootstrap/start-tui-v2.d.ts +1 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js +16 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
- package/dist/tui-v2/components/completion/completion-menu.d.ts +4 -6
- package/dist/tui-v2/components/completion/completion-menu.js +34 -16
- package/dist/tui-v2/components/completion/completion-menu.js.map +1 -1
- package/dist/tui-v2/components/composer/composer-input-box.js +3 -1
- package/dist/tui-v2/components/composer/composer-input-box.js.map +1 -1
- package/dist/tui-v2/components/modal/secret-modal.js +6 -4
- package/dist/tui-v2/components/modal/secret-modal.js.map +1 -1
- package/dist/tui-v2/components/modal/text-editor-modal.d.ts +19 -0
- package/dist/tui-v2/components/modal/text-editor-modal.js +85 -0
- package/dist/tui-v2/components/modal/text-editor-modal.js.map +1 -0
- package/dist/tui-v2/components/overlay/overlay-host.js +2 -1
- package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js +12 -3
- package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/thinking-block.d.ts +9 -1
- package/dist/tui-v2/components/transcript/thinking-block.js +253 -49
- package/dist/tui-v2/components/transcript/thinking-block.js.map +1 -1
- package/dist/tui-v2/components/transcript/thinking-presentation.d.ts +46 -0
- package/dist/tui-v2/components/transcript/thinking-presentation.js +84 -0
- package/dist/tui-v2/components/transcript/thinking-presentation.js.map +1 -0
- package/dist/tui-v2/components/transcript/transcript-row.d.ts +2 -0
- package/dist/tui-v2/components/transcript/transcript-row.js +7 -2
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-view.js +195 -83
- package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +54 -39
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/composer/composer-highlight.d.ts +20 -0
- package/dist/tui-v2/composer/composer-highlight.js +97 -0
- package/dist/tui-v2/composer/composer-highlight.js.map +1 -0
- package/dist/tui-v2/composer/textarea-keybindings.d.ts +5 -0
- package/dist/tui-v2/composer/textarea-keybindings.js +12 -0
- package/dist/tui-v2/composer/textarea-keybindings.js.map +1 -1
- package/dist/ui/mentions.js +4 -1
- package/dist/ui/mentions.js.map +1 -1
- package/dist/ui-core/actions/action-id.d.ts +1 -1
- package/dist/ui-core/actions/action-id.js +1 -0
- package/dist/ui-core/actions/action-id.js.map +1 -1
- package/dist/ui-core/actions/format-shortcuts.js +5 -0
- package/dist/ui-core/actions/format-shortcuts.js.map +1 -1
- package/dist/ui-core/actions/keymap.js +3 -0
- package/dist/ui-core/actions/keymap.js.map +1 -1
- package/dist/ui-core/bootstrap/composition-root.d.ts +7 -0
- package/dist/ui-core/bootstrap/composition-root.js +7 -1
- package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
- package/dist/ui-core/commands/command-handlers.js +5 -2
- package/dist/ui-core/commands/command-handlers.js.map +1 -1
- package/dist/ui-core/commands/config-commands.d.ts +1 -0
- package/dist/ui-core/commands/config-commands.js +6 -0
- package/dist/ui-core/commands/config-commands.js.map +1 -1
- package/dist/ui-core/commands/mcp-commands.d.ts +3 -0
- package/dist/ui-core/commands/mcp-commands.js +310 -0
- package/dist/ui-core/commands/mcp-commands.js.map +1 -0
- package/dist/ui-core/commands/picker-commands.d.ts +1 -1
- package/dist/ui-core/commands/picker-commands.js +70 -27
- package/dist/ui-core/commands/picker-commands.js.map +1 -1
- package/dist/ui-core/commands/session-commands.js +1 -0
- package/dist/ui-core/commands/session-commands.js.map +1 -1
- package/dist/ui-core/composer/completion-viewport.d.ts +40 -0
- package/dist/ui-core/composer/completion-viewport.js +105 -0
- package/dist/ui-core/composer/completion-viewport.js.map +1 -0
- package/dist/ui-core/controllers/overlay-controller.d.ts +24 -3
- package/dist/ui-core/controllers/overlay-controller.js +35 -4
- package/dist/ui-core/controllers/overlay-controller.js.map +1 -1
- package/dist/ui-core/rendering/artifact-pager-source.d.ts +1 -0
- package/dist/ui-core/rendering/artifact-pager-source.js +67 -1
- package/dist/ui-core/rendering/artifact-pager-source.js.map +1 -1
- package/dist/ui-core/rendering/duration.d.ts +3 -1
- package/dist/ui-core/rendering/duration.js +14 -0
- package/dist/ui-core/rendering/duration.js.map +1 -1
- package/dist/ui-core/rendering/exit-summary.js +4 -4
- package/dist/ui-core/rendering/format-help.js +4 -0
- package/dist/ui-core/rendering/format-help.js.map +1 -1
- package/dist/ui-core/rendering/intro-header.js +4 -4
- package/dist/ui-core/rendering/open-tool-output.js +90 -32
- package/dist/ui-core/rendering/open-tool-output.js.map +1 -1
- package/dist/ui-core/rendering/theme.d.ts +5 -3
- package/dist/ui-core/rendering/theme.js +8 -4
- package/dist/ui-core/rendering/theme.js.map +1 -1
- package/dist/ui-core/rendering/wordmark.d.ts +2 -2
- package/dist/ui-core/rendering/wordmark.js +62 -62
- package/dist/ui-core/rendering/wordmark.js.map +1 -1
- package/dist/ui-core/state/thinking-copy.d.ts +13 -0
- package/dist/ui-core/state/thinking-copy.js +33 -0
- package/dist/ui-core/state/thinking-copy.js.map +1 -0
- package/dist/ui-core/state/transcript-hydrate.js +20 -0
- package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
- package/dist/ui-core/state/transcript-reducer.js +140 -62
- package/dist/ui-core/state/transcript-reducer.js.map +1 -1
- package/dist/ui-core/state/transcript-store.d.ts +10 -0
- package/dist/ui-core/state/transcript-store.js +235 -31
- package/dist/ui-core/state/transcript-store.js.map +1 -1
- package/dist/ui-core/state/transcript-types.d.ts +10 -0
- package/dist/ui-core/state/transcript-types.js +1 -0
- package/dist/ui-core/state/transcript-types.js.map +1 -1
- package/dist/ui-core/state/transcript-window.d.ts +32 -0
- package/dist/ui-core/state/transcript-window.js +63 -0
- package/dist/ui-core/state/transcript-window.js.map +1 -0
- package/dist/version.generated.d.ts +2 -2
- package/dist/version.generated.js +2 -2
- package/dist/version.generated.js.map +1 -1
- package/package.json +1 -1
- package/dist/tui-v2/composer/skill-highlight.d.ts +0 -3
- package/dist/tui-v2/composer/skill-highlight.js +0 -63
- package/dist/tui-v2/composer/skill-highlight.js.map +0 -1
package/dist/agent/runner.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
+
import { hasMcpMentionSyntax } from "../mcp/mentions.js";
|
|
3
|
+
import { isCanonicalToolName } from "../mcp/names.js";
|
|
2
4
|
import { streamWithProvider } from "../llm/router.js";
|
|
3
5
|
import { isProviderFailureStatus } from "../llm/key-rotation.js";
|
|
4
6
|
import { REQUEST_CONTEXT_PREFIX, upsertRequestContextMessage, } from "../llm/system-messages.js";
|
|
@@ -6,6 +8,7 @@ import { operationUsageFromError } from "../llm/operation-ledger.js";
|
|
|
6
8
|
import { contextAttemptFromOperationUsage } from "../llm/context-snapshot.js";
|
|
7
9
|
import { modelContextWindow } from "../llm/token-usage.js";
|
|
8
10
|
import { providerInputTokenBudget } from "../llm/context-windows.js";
|
|
11
|
+
import { resolveBuiltInProfile } from "../llm/provider-profiles.js";
|
|
9
12
|
import { streamAlreadyEmitted } from "../llm/stream-progress.js";
|
|
10
13
|
import { classifyStreamFailure, planStreamRecovery, recordRecoveryAttempt, createStreamRecoveryState, resetStreamRecoveryState, } from "./stream-recovery.js";
|
|
11
14
|
import { modelSupportsVision, resolveToolDialect } from "../llm/capabilities.js";
|
|
@@ -49,7 +52,7 @@ import { compactMessagesWithSummary, shouldApplyAutoCompact, COMPACTION_MEMORY_P
|
|
|
49
52
|
import { buildContextBreakdown, contextBreakdownAuditPayload, describeDominantContextBlock, toolSchemaHash, } from "./context-breakdown.js";
|
|
50
53
|
import { recordRequestTokenObservation } from "../llm/token-estimate-calibration.js";
|
|
51
54
|
import { accountAssembledRequest, RequestOverLimitError, } from "./request-accounting.js";
|
|
52
|
-
import { autoCompactTriggerTokens, dedupeToolContextOutput, freeTierGuardNotices, getReliabilityPolicy, resolveStepMaxTokens, } from "./reliability-policy.js";
|
|
55
|
+
import { autoCompactTriggerTokens, dedupeToolContextOutput, freeTierGuardNotices, getReliabilityPolicy, MAX_OUTPUT_BUDGET_CONTINUATIONS, MAX_STEP_COMPLETION_TOKENS, outputBudgetWasExhausted, resolveStepMaxTokens, } from "./reliability-policy.js";
|
|
53
56
|
import { auditLog } from "../store/logs.js";
|
|
54
57
|
import { loadProjectContext } from "../store/project.js";
|
|
55
58
|
import { loadAgentInstructions } from "../instructions/load.js";
|
|
@@ -378,6 +381,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
378
381
|
emit({ type: "turn-end", outcome, finalAnswer: rendered, steps });
|
|
379
382
|
return outcome;
|
|
380
383
|
};
|
|
384
|
+
let mcpLease;
|
|
381
385
|
try {
|
|
382
386
|
emit({
|
|
383
387
|
type: "turn-start",
|
|
@@ -387,6 +391,17 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
387
391
|
: {}),
|
|
388
392
|
});
|
|
389
393
|
const config = getConfig();
|
|
394
|
+
const mcpRuntime = options.mcp;
|
|
395
|
+
const mcpMentioned = hasMcpMentionSyntax(prompt);
|
|
396
|
+
if (mcpRuntime &&
|
|
397
|
+
(mcpRuntime.getState().selection.mode !== "off" || mcpMentioned)) {
|
|
398
|
+
await mcpRuntime.ensureReady();
|
|
399
|
+
}
|
|
400
|
+
if (mcpRuntime && mcpMentioned)
|
|
401
|
+
mcpRuntime.applyMentionSelection(prompt);
|
|
402
|
+
const mcpToolDefinitions = mcpRuntime?.toolDefinitions({ ...(agentMode === "ask" ? { askMode: true } : {}) }) ?? [];
|
|
403
|
+
mcpLease = mcpRuntime?.beginTurn();
|
|
404
|
+
const mcpToolNames = mcpToolDefinitions.map((definition) => definition.name);
|
|
390
405
|
const maxSteps = options.maxSteps ?? 70;
|
|
391
406
|
const confirmPort = options.confirm ?? stdioConfirmPort;
|
|
392
407
|
const projectContext = await loadProjectContext();
|
|
@@ -402,7 +417,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
402
417
|
// image.view is different from optimistic user-attachment handling: once
|
|
403
418
|
// the tool succeeds, the model must actually receive and inspect its bytes.
|
|
404
419
|
// Offer it only with affirmative capability evidence for the active route.
|
|
405
|
-
const routeToolNames = (routeProvider, routeModel) => availableToolNames().filter((name) => {
|
|
420
|
+
const routeToolNames = (routeProvider, routeModel) => [...availableToolNames(), ...mcpToolNames].filter((name) => {
|
|
406
421
|
if (name === "image.ocr")
|
|
407
422
|
return imageOcrEnabled;
|
|
408
423
|
if (name === "image.view") {
|
|
@@ -448,16 +463,17 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
448
463
|
const inputTokenBudget = providerInputTokenBudget(provider, model);
|
|
449
464
|
const useCompactSystemPrompt = inputTokenBudget !== undefined;
|
|
450
465
|
const resolveNativeTools = (p, m) => {
|
|
451
|
-
const dialect = resolveToolDialect(p, m, config.toolCalling);
|
|
466
|
+
const dialect = resolveToolDialect(p, m, options.toolCalling ?? config.toolCalling);
|
|
452
467
|
return { dialect, native: dialect !== "none" };
|
|
453
468
|
};
|
|
454
469
|
let { dialect: toolDialect, native: nativeToolsActive } = resolveNativeTools(provider, model);
|
|
455
470
|
const selectToolDefs = (native, compact, routeProvider = provider, routeModel = model) => {
|
|
456
471
|
if (!native)
|
|
457
472
|
return undefined;
|
|
458
|
-
const base =
|
|
459
|
-
? getCompactToolDefinitions()
|
|
460
|
-
|
|
473
|
+
const base = [
|
|
474
|
+
...(compact ? getCompactToolDefinitions() : getToolDefinitions()),
|
|
475
|
+
...mcpToolDefinitions,
|
|
476
|
+
];
|
|
461
477
|
const allow = new Set([
|
|
462
478
|
...routeToolNames(routeProvider, routeModel),
|
|
463
479
|
...RUNNER_META_TOOL_NAMES,
|
|
@@ -570,6 +586,12 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
570
586
|
const systemSections = [
|
|
571
587
|
renderRequestEnvironmentContext({ plan: activePlan }),
|
|
572
588
|
];
|
|
589
|
+
const mcpContext = mcpRuntime?.promptContext({
|
|
590
|
+
nativeTools: false,
|
|
591
|
+
...(agentMode === "ask" ? { askMode: true } : {}),
|
|
592
|
+
});
|
|
593
|
+
if (mcpContext)
|
|
594
|
+
systemSections.push(mcpContext);
|
|
573
595
|
if (projectContext) {
|
|
574
596
|
systemSections.push(`Project context from .clai/context.md:\n${projectContext}`);
|
|
575
597
|
}
|
|
@@ -723,13 +745,16 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
723
745
|
? "mode"
|
|
724
746
|
: content.includes("OUTCOME")
|
|
725
747
|
? "outcome"
|
|
726
|
-
: content.includes("WORKFLOW") ||
|
|
748
|
+
: content.includes("WORKFLOW") ||
|
|
749
|
+
content.includes("FOCUS") ||
|
|
750
|
+
content.startsWith("WORK PROFILE")
|
|
727
751
|
? "focus"
|
|
728
752
|
: "context",
|
|
729
753
|
content,
|
|
730
754
|
mandatory: content.startsWith(SKILLS_CATALOG_PREFIX)
|
|
731
755
|
? selectedSkillNames.length > 0
|
|
732
756
|
: content.startsWith("ACTIVE PLAN") ||
|
|
757
|
+
content.startsWith("MCP TOOL CONTEXT") ||
|
|
733
758
|
content.startsWith("ENGAGEMENT SCOPE") ||
|
|
734
759
|
content.startsWith("REQUEST ENVIRONMENT") ||
|
|
735
760
|
content.startsWith("Project context from .clai/context.md:") ||
|
|
@@ -923,7 +948,6 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
923
948
|
});
|
|
924
949
|
};
|
|
925
950
|
const loopGuard = new LoopGuard();
|
|
926
|
-
let lastExactPromptTokens = 0;
|
|
927
951
|
// Uncalibrated estimate for the request currently in flight. Paired with the
|
|
928
952
|
// provider's reported prompt size below so the estimator learns this route's
|
|
929
953
|
// bias instead of permanently over-reporting it.
|
|
@@ -961,6 +985,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
961
985
|
// to actually act instead of silently returning an empty answer.
|
|
962
986
|
let emptyVisibleRetries = 0;
|
|
963
987
|
let truncatedBudgetRounds = 0;
|
|
988
|
+
let continuationBudgetFloor = 0;
|
|
964
989
|
let retryWithoutThinking = false;
|
|
965
990
|
// Robust stream-failure recovery. When a provider stream/complete fails we
|
|
966
991
|
// try working approaches (backoff, compaction, thinking-off, provider
|
|
@@ -1276,7 +1301,11 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
1276
1301
|
}
|
|
1277
1302
|
async function executeSingleTool(rawCall, toolEventId, parentSignal) {
|
|
1278
1303
|
const scratchDir = scratchDirFor(safeCwd());
|
|
1279
|
-
|
|
1304
|
+
const normalizedCall = normalizeToolCall(rawCall);
|
|
1305
|
+
const canonicalMcpName = mcpRuntime?.canonicalizeToolName(normalizedCall.name);
|
|
1306
|
+
let call = canonicalMcpName && canonicalMcpName !== normalizedCall.name
|
|
1307
|
+
? { ...normalizedCall, name: canonicalMcpName }
|
|
1308
|
+
: normalizedCall;
|
|
1280
1309
|
const emitVisibleSyntheticReceipt = (result, summary) => {
|
|
1281
1310
|
if (!alreadyPrintedIds.has(toolEventId)) {
|
|
1282
1311
|
writeToolCall(toolEventId, call);
|
|
@@ -1630,7 +1659,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
1630
1659
|
}
|
|
1631
1660
|
}
|
|
1632
1661
|
const scope = await loadScopeForSession(session.sessionId);
|
|
1633
|
-
const decision = classifyToolCall(call, { scope });
|
|
1662
|
+
const decision = mcpRuntime?.classify(call.name) ?? classifyToolCall(call, { scope });
|
|
1634
1663
|
await auditLog("tool.classified", {
|
|
1635
1664
|
call,
|
|
1636
1665
|
decision,
|
|
@@ -1654,7 +1683,9 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
1654
1683
|
call.name === "terminal.send" ||
|
|
1655
1684
|
((call.name === "shell.exec" || call.name === "shell.start") &&
|
|
1656
1685
|
!isPlanModeAllowedShellCommand(cmd));
|
|
1657
|
-
const allowed = isPlanModeAllowedTool(call.name)
|
|
1686
|
+
const allowed = (isPlanModeAllowedTool(call.name) ||
|
|
1687
|
+
mcpRuntime?.classify(call.name)?.level === "safe") &&
|
|
1688
|
+
!shellBlocked;
|
|
1658
1689
|
if (!allowed) {
|
|
1659
1690
|
const reason = `plan mode — ${call.name} is blocked (gather-only). ` +
|
|
1660
1691
|
`Use any recon/enum/scan/research tool; do not write project files or run active exploits. ` +
|
|
@@ -2086,58 +2117,62 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2086
2117
|
* could freeze for minutes after "cancelling stalled tool".
|
|
2087
2118
|
*/
|
|
2088
2119
|
const runToolWithForcedSettle = () => {
|
|
2089
|
-
const work =
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2120
|
+
const work = mcpRuntime !== undefined &&
|
|
2121
|
+
(mcpRuntime.getTool(call.name) !== undefined ||
|
|
2122
|
+
isCanonicalToolName(call.name))
|
|
2123
|
+
? mcpRuntime.callTool(call.name, call.args, { signal: toolAc.signal })
|
|
2124
|
+
: runToolCall(call, {
|
|
2125
|
+
signal: toolAc.signal,
|
|
2126
|
+
requestSecret: options.requestSecret ?? stdioSecretRequester,
|
|
2127
|
+
onOutput: (chunk) => {
|
|
2128
|
+
if (toolAc.signal.aborted)
|
|
2129
|
+
return;
|
|
2130
|
+
resetStallTimer();
|
|
2131
|
+
printLive(chunk);
|
|
2132
|
+
},
|
|
2133
|
+
confirmed: true,
|
|
2134
|
+
userPrompt: prompt,
|
|
2135
|
+
// image.view needs the active route to check vision support and size
|
|
2136
|
+
// images to the provider's per-image budget.
|
|
2137
|
+
llmProvider: provider,
|
|
2138
|
+
llmModel: model,
|
|
2139
|
+
sessionId: session.sessionId,
|
|
2140
|
+
...(delegation?.taskId ? { taskId: delegation.taskId } : {}),
|
|
2141
|
+
...(delegation ? { delegationId: delegation.id } : {}),
|
|
2142
|
+
...(dispatchedTaskId ? { parentTaskId: dispatchedTaskId } : {}),
|
|
2143
|
+
wakeOnCompletion: true,
|
|
2144
|
+
monitor: {
|
|
2145
|
+
toolName: call.name,
|
|
2146
|
+
toolEventId,
|
|
2147
|
+
},
|
|
2148
|
+
...(engagementAction && scope
|
|
2149
|
+
? {
|
|
2150
|
+
engagementAuthorization: {
|
|
2151
|
+
target: engagementDecision?.normalizedTarget || engagementAction.target,
|
|
2152
|
+
...(scope.expiresAt ? { expiresAt: scope.expiresAt } : {}),
|
|
2153
|
+
},
|
|
2154
|
+
authorizeNetworkHop: async (url, resolvedAddresses) => {
|
|
2155
|
+
const hop = actionFromUrl({
|
|
2156
|
+
url,
|
|
2157
|
+
method: engagementAction.method,
|
|
2158
|
+
phase: engagementAction.phase,
|
|
2159
|
+
capability: engagementAction.capability,
|
|
2160
|
+
resolvedAddresses,
|
|
2161
|
+
});
|
|
2162
|
+
const hopDecision = evaluateEngagementAction(scope, hop);
|
|
2163
|
+
await auditLog("engagement.policy.hop", {
|
|
2164
|
+
...(engagementGraph ? { engagementId: engagementGraph.id } : {}),
|
|
2165
|
+
...(engagementRecord ? { actionId: engagementRecord.id } : {}),
|
|
2166
|
+
url,
|
|
2167
|
+
resolvedAddresses,
|
|
2168
|
+
allowed: hopDecision.allowed,
|
|
2169
|
+
reason: hopDecision.reason,
|
|
2170
|
+
});
|
|
2171
|
+
return { allowed: hopDecision.allowed, reason: hopDecision.reason };
|
|
2172
|
+
},
|
|
2173
|
+
}
|
|
2174
|
+
: {}),
|
|
2175
|
+
});
|
|
2141
2176
|
return new Promise((resolve, reject) => {
|
|
2142
2177
|
let settled = false;
|
|
2143
2178
|
const finishOk = (r) => {
|
|
@@ -2886,8 +2921,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
2886
2921
|
});
|
|
2887
2922
|
}
|
|
2888
2923
|
async function maybeAutoCompact(reason, force = false) {
|
|
2889
|
-
const
|
|
2890
|
-
const beforeTokens = Math.max(beforeRequestTokens, lastExactPromptTokens);
|
|
2924
|
+
const beforeTokens = estimateNextRequestTokens(messages);
|
|
2891
2925
|
const contextLimitTokens = currentContextLimitTokens();
|
|
2892
2926
|
const compactTrigger = autoCompactTriggerTokens(getReliabilityPolicy(), {
|
|
2893
2927
|
provider,
|
|
@@ -3025,7 +3059,6 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3025
3059
|
messages.splice(0, messages.length, ...candidateMessages);
|
|
3026
3060
|
compactionAttempts.recordSuccess(attemptKey);
|
|
3027
3061
|
loopGuard.resetReadOnly();
|
|
3028
|
-
lastExactPromptTokens = 0;
|
|
3029
3062
|
// The snapshot predates the rewrite: replaying it would resurrect the
|
|
3030
3063
|
// pre-compaction history. The next successful request re-seeds it.
|
|
3031
3064
|
lastSuccessfulRequestSnapshot = undefined;
|
|
@@ -3172,6 +3205,21 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3172
3205
|
}
|
|
3173
3206
|
}
|
|
3174
3207
|
const contextLimitTokens = currentContextLimitTokens();
|
|
3208
|
+
const routeOutputTokenLimit = resolveBuiltInProfile({
|
|
3209
|
+
provider,
|
|
3210
|
+
model,
|
|
3211
|
+
}).limits.outputTokens;
|
|
3212
|
+
stepMaxTokens = resolveStepMaxTokens({
|
|
3213
|
+
nativeToolsActive,
|
|
3214
|
+
toolsAttached,
|
|
3215
|
+
recoveryNudge: retryWithoutThinking,
|
|
3216
|
+
truncationDepth: truncatedBudgetRounds,
|
|
3217
|
+
thinkingEnabled: Boolean(config.thinking?.enabled) && !retryWithoutThinking,
|
|
3218
|
+
minimumTokens: continuationBudgetFloor,
|
|
3219
|
+
...(routeOutputTokenLimit !== undefined
|
|
3220
|
+
? { outputTokenLimit: routeOutputTokenLimit }
|
|
3221
|
+
: {}),
|
|
3222
|
+
});
|
|
3175
3223
|
await auditLog("agent.turn", {
|
|
3176
3224
|
provider,
|
|
3177
3225
|
model,
|
|
@@ -3187,13 +3235,10 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3187
3235
|
? { contextLimitTokens }
|
|
3188
3236
|
: {}),
|
|
3189
3237
|
}),
|
|
3190
|
-
maxTokensBudget:
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
truncationDepth: truncatedBudgetRounds,
|
|
3195
|
-
thinkingEnabled: Boolean(config.thinking?.enabled) && !retryWithoutThinking,
|
|
3196
|
-
}),
|
|
3238
|
+
maxTokensBudget: stepMaxTokens,
|
|
3239
|
+
...(routeOutputTokenLimit !== undefined
|
|
3240
|
+
? { outputTokenLimit: routeOutputTokenLimit }
|
|
3241
|
+
: {}),
|
|
3197
3242
|
});
|
|
3198
3243
|
// Resume / mid-turn abort can leave orphan tool rows or a user
|
|
3199
3244
|
// "continue" before tool results. Heal first so multi-key retry and
|
|
@@ -3202,14 +3247,6 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3202
3247
|
// ok=true so the model doesn't thrash on fake exit=130 failures.
|
|
3203
3248
|
repairToolProtocol(messages);
|
|
3204
3249
|
assertValidToolProtocol(messages);
|
|
3205
|
-
// E3: adaptive completion budget (still large enough for writes).
|
|
3206
|
-
stepMaxTokens = resolveStepMaxTokens({
|
|
3207
|
-
nativeToolsActive,
|
|
3208
|
-
toolsAttached,
|
|
3209
|
-
recoveryNudge: retryWithoutThinking,
|
|
3210
|
-
truncationDepth: truncatedBudgetRounds,
|
|
3211
|
-
thinkingEnabled: Boolean(config.thinking?.enabled) && !retryWithoutThinking,
|
|
3212
|
-
});
|
|
3213
3250
|
try {
|
|
3214
3251
|
// MR-007: the fit verdict is taken on the final assembled request —
|
|
3215
3252
|
// after protocol repair and every live-state reinjection — and a
|
|
@@ -3540,7 +3577,6 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3540
3577
|
model = completion.model;
|
|
3541
3578
|
if (completion.usage) {
|
|
3542
3579
|
if (completion.usage.exact && completion.usage.promptTokens > 0) {
|
|
3543
|
-
lastExactPromptTokens = completion.usage.promptTokens;
|
|
3544
3580
|
recordRequestTokenObservation({
|
|
3545
3581
|
provider: completion.provider,
|
|
3546
3582
|
model: completion.model,
|
|
@@ -3602,6 +3638,11 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3602
3638
|
...assistantTextResult,
|
|
3603
3639
|
visible: continuedVisible,
|
|
3604
3640
|
};
|
|
3641
|
+
const retryReasoning = completion.reasoningArtifacts?.length || completion.reasoningBlock
|
|
3642
|
+
? completion
|
|
3643
|
+
: assistantText.hasThinking
|
|
3644
|
+
? { reasoningBlock: { text: assistantText.thinkContent } }
|
|
3645
|
+
: completion;
|
|
3605
3646
|
const commitAssistantRetry = (historyText) => {
|
|
3606
3647
|
const hasShownToolCall = deferredToolCalls.some((entry) => entry.shown);
|
|
3607
3648
|
if (!hasShownToolCall) {
|
|
@@ -3619,7 +3660,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3619
3660
|
});
|
|
3620
3661
|
}
|
|
3621
3662
|
}
|
|
3622
|
-
pushAssistantHistory(historyText,
|
|
3663
|
+
pushAssistantHistory(historyText, retryReasoning);
|
|
3623
3664
|
interruptedVisible = "";
|
|
3624
3665
|
interruptedReasoning = "";
|
|
3625
3666
|
lowYieldResumptions = 0;
|
|
@@ -3805,45 +3846,72 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3805
3846
|
malformedNativeArgsRounds = 0;
|
|
3806
3847
|
}
|
|
3807
3848
|
}
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
assistantText.hasThinking &&
|
|
3828
|
-
truncatedBudgetRounds < 4) {
|
|
3849
|
+
const completionTokens = completion.usage?.completionTokens ?? 0;
|
|
3850
|
+
const completionRouteProfile = resolveBuiltInProfile({
|
|
3851
|
+
provider,
|
|
3852
|
+
model,
|
|
3853
|
+
});
|
|
3854
|
+
const completionBudget = completionRouteProfile.limits.outputTokens === undefined
|
|
3855
|
+
? stepMaxTokens
|
|
3856
|
+
: Math.min(stepMaxTokens, completionRouteProfile.limits.outputTokens);
|
|
3857
|
+
const hitOutputLimit = outputBudgetWasExhausted({
|
|
3858
|
+
finishReason: completion.finishReason,
|
|
3859
|
+
completionTokens,
|
|
3860
|
+
requestedMaxTokens: completionBudget,
|
|
3861
|
+
});
|
|
3862
|
+
const incompleteNativeStream = nativeToolCalls.length === 0 && streamedNativeCallNames.size > 0;
|
|
3863
|
+
const outputLimitLooksLikeTool = incompleteNativeStream ||
|
|
3864
|
+
countToolFences(assistantText.visible) > 0 ||
|
|
3865
|
+
looksLikeTruncatedToolCall(assistantText.visible);
|
|
3866
|
+
if (hitOutputLimit && !call && !outputLimitLooksLikeTool) {
|
|
3867
|
+
if (truncatedBudgetRounds < MAX_OUTPUT_BUDGET_CONTINUATIONS) {
|
|
3829
3868
|
truncatedBudgetRounds += 1;
|
|
3830
|
-
|
|
3869
|
+
const desiredContinuationBudget = Math.min(MAX_STEP_COMPLETION_TOKENS, Math.max(completionBudget, completionBudget * 2));
|
|
3870
|
+
continuationBudgetFloor =
|
|
3871
|
+
completionRouteProfile.limits.outputTokens === undefined
|
|
3872
|
+
? desiredContinuationBudget
|
|
3873
|
+
: Math.min(desiredContinuationBudget, completionRouteProfile.limits.outputTokens);
|
|
3874
|
+
retryWithoutThinking =
|
|
3875
|
+
completionRouteProfile.reasoning.generation !== "mandatory";
|
|
3876
|
+
if (assistantText.hasThinking) {
|
|
3877
|
+
interruptedReasoning = appendInterruptedReasoning(interruptedReasoning, assistantText.thinkContent);
|
|
3878
|
+
}
|
|
3831
3879
|
const preservedBudgetReasoning = interruptedReasoning;
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3880
|
+
if (canonicalAssistantVisible.trim()) {
|
|
3881
|
+
visibleCommitted = true;
|
|
3882
|
+
pushAssistantHistory(assistantText.visible, retryReasoning);
|
|
3883
|
+
interruptedVisible = canonicalAssistantVisible;
|
|
3884
|
+
lowYieldResumptions = 0;
|
|
3885
|
+
}
|
|
3886
|
+
else {
|
|
3887
|
+
commitAssistantRetry(assistantText.visible);
|
|
3888
|
+
interruptedReasoning = preservedBudgetReasoning;
|
|
3889
|
+
}
|
|
3890
|
+
writeNotice("warn", retryWithoutThinking
|
|
3891
|
+
? "response used the whole output budget — preserving it and continuing once with optional reasoning disabled"
|
|
3892
|
+
: "response used the whole output budget — preserving it and continuing once at the route limit");
|
|
3835
3893
|
messages.push(recoveryUserMessage([
|
|
3836
|
-
|
|
3837
|
-
"
|
|
3838
|
-
"
|
|
3894
|
+
canonicalAssistantVisible.trim()
|
|
3895
|
+
? "Your previous response was cut off by the output token limit. Continue from the exact stopping point without repeating any prior text."
|
|
3896
|
+
: "Your previous response spent the output budget before producing a visible answer. Do not restart the analysis; use the preserved conclusions and answer now.",
|
|
3897
|
+
retryWithoutThinking
|
|
3898
|
+
? "Optional reasoning is disabled for this continuation. Emit the next tool call or final answer directly and briefly."
|
|
3899
|
+
: "Finish the reasoning briefly, then emit the next tool call or final answer directly.",
|
|
3839
3900
|
interruptedReasoningBrief(interruptedReasoning),
|
|
3840
3901
|
]
|
|
3841
3902
|
.filter((part) => Boolean(part))
|
|
3842
3903
|
.join("\n\n")));
|
|
3843
3904
|
continue;
|
|
3844
3905
|
}
|
|
3845
|
-
|
|
3846
|
-
|
|
3906
|
+
writeNotice("warn", canonicalAssistantVisible.trim()
|
|
3907
|
+
? "response reached the output limit again after its bounded continuation — returning the preserved partial answer"
|
|
3908
|
+
: "response reached the output limit again after its bounded continuation — stopping without restarting the reasoning");
|
|
3909
|
+
if (!canonicalAssistantVisible.trim()) {
|
|
3910
|
+
commitAssistantRetry(assistantText.visible);
|
|
3911
|
+
return finishTurn("The model exhausted its output budget again after one preserved continuation. No visible answer was produced.", step + 1, "partial", ["Retry at a lower reasoning effort or choose a model with a larger output limit."], "The model exhausted the route's output budget twice without a visible answer.");
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
if (!canonicalAssistantVisible.trim() && !call) {
|
|
3847
3915
|
if (incompleteNativeStream) {
|
|
3848
3916
|
const reason = "The provider began this native tool call but never completed it. Nothing ran; reissue a complete call.";
|
|
3849
3917
|
for (const deferred of deferredToolCalls) {
|
|
@@ -3904,6 +3972,7 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
3904
3972
|
// Reset the counter on any successful visible output or recovered call.
|
|
3905
3973
|
emptyVisibleRetries = 0;
|
|
3906
3974
|
truncatedBudgetRounds = 0;
|
|
3975
|
+
continuationBudgetFloor = 0;
|
|
3907
3976
|
retryWithoutThinking = false;
|
|
3908
3977
|
interruptedReasoning = "";
|
|
3909
3978
|
}
|
|
@@ -4233,15 +4302,18 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
4233
4302
|
? "One or more required plan tasks failed."
|
|
4234
4303
|
: outcomeStatus === "partial"
|
|
4235
4304
|
? "Required outcome criteria remain unsupported by current evidence."
|
|
4236
|
-
: undefined, displayCleaned);
|
|
4305
|
+
: undefined, interruptedVisible ? cleaned : displayCleaned);
|
|
4237
4306
|
}
|
|
4238
4307
|
// A valid primary tool call exists for this fresh model turn. Show any
|
|
4239
4308
|
// prose / thinking that preceded it, record the assistant message ONCE.
|
|
4309
|
+
const toolDisplayText = interruptedVisible
|
|
4310
|
+
? canonicalAssistantVisible
|
|
4311
|
+
: assistantText.visible;
|
|
4240
4312
|
const beforeTool = recoveredFromBareJson
|
|
4241
4313
|
? ""
|
|
4242
4314
|
: nativeToolCalls.length
|
|
4243
|
-
?
|
|
4244
|
-
: textBeforeToolCall(
|
|
4315
|
+
? toolDisplayText.trim()
|
|
4316
|
+
: textBeforeToolCall(toolDisplayText);
|
|
4245
4317
|
if (beforeTool) {
|
|
4246
4318
|
writeAssistantMessage(beforeTool);
|
|
4247
4319
|
}
|
|
@@ -4486,6 +4558,8 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
4486
4558
|
}
|
|
4487
4559
|
const scopeForBatch = await loadScopeForSession(session.sessionId).catch(() => undefined);
|
|
4488
4560
|
const isParallelSafe = (c) => {
|
|
4561
|
+
if (mcpRuntime?.isParallelSafe(c.name))
|
|
4562
|
+
return true;
|
|
4489
4563
|
if (c.name === "pentest.recon" ||
|
|
4490
4564
|
c.name === "net.context" ||
|
|
4491
4565
|
c.name === "tool.batch" ||
|
|
@@ -5030,6 +5104,9 @@ export async function runAgentTurn(prompt, options = {}) {
|
|
|
5030
5104
|
});
|
|
5031
5105
|
throw error;
|
|
5032
5106
|
}
|
|
5107
|
+
finally {
|
|
5108
|
+
mcpLease?.release();
|
|
5109
|
+
}
|
|
5033
5110
|
}
|
|
5034
5111
|
/** Compatibility boundary for callers that consume visible assistant text. */
|
|
5035
5112
|
export async function runAgentLoop(prompt, options = {}) {
|