@sema-ai/core 1.275.1
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/CHANGELOG.md +5433 -0
- package/LICENSE +27 -0
- package/NOTICE.md +30 -0
- package/README.md +1040 -0
- package/dist/agents/agent-definition.d.ts +10 -0
- package/dist/agents/agent-definition.d.ts.map +1 -0
- package/dist/agents/agent-definition.js +18 -0
- package/dist/agents/agent-definition.js.map +1 -0
- package/dist/agents/builtin-agents.d.ts +69 -0
- package/dist/agents/builtin-agents.d.ts.map +1 -0
- package/dist/agents/builtin-agents.js +177 -0
- package/dist/agents/builtin-agents.js.map +1 -0
- package/dist/agents/cascade.d.ts +101 -0
- package/dist/agents/cascade.d.ts.map +1 -0
- package/dist/agents/cascade.js +189 -0
- package/dist/agents/cascade.js.map +1 -0
- package/dist/agents/observer.d.ts +209 -0
- package/dist/agents/observer.d.ts.map +1 -0
- package/dist/agents/observer.js +495 -0
- package/dist/agents/observer.js.map +1 -0
- package/dist/agents/repair-loop.d.ts +236 -0
- package/dist/agents/repair-loop.d.ts.map +1 -0
- package/dist/agents/repair-loop.js +293 -0
- package/dist/agents/repair-loop.js.map +1 -0
- package/dist/agents/session-util.d.ts +8 -0
- package/dist/agents/session-util.d.ts.map +1 -0
- package/dist/agents/session-util.js +9 -0
- package/dist/agents/session-util.js.map +1 -0
- package/dist/agents/subagent-steps.d.ts +93 -0
- package/dist/agents/subagent-steps.d.ts.map +1 -0
- package/dist/agents/subagent-steps.js +206 -0
- package/dist/agents/subagent-steps.js.map +1 -0
- package/dist/agents/subagent.d.ts +441 -0
- package/dist/agents/subagent.d.ts.map +1 -0
- package/dist/agents/subagent.js +2492 -0
- package/dist/agents/subagent.js.map +1 -0
- package/dist/agents/suspend-guard.d.ts +35 -0
- package/dist/agents/suspend-guard.d.ts.map +1 -0
- package/dist/agents/suspend-guard.js +48 -0
- package/dist/agents/suspend-guard.js.map +1 -0
- package/dist/agents/teacher.d.ts +137 -0
- package/dist/agents/teacher.d.ts.map +1 -0
- package/dist/agents/teacher.js +575 -0
- package/dist/agents/teacher.js.map +1 -0
- package/dist/agents/team.d.ts +211 -0
- package/dist/agents/team.d.ts.map +1 -0
- package/dist/agents/team.js +293 -0
- package/dist/agents/team.js.map +1 -0
- package/dist/agents/tool-filter.d.ts +29 -0
- package/dist/agents/tool-filter.d.ts.map +1 -0
- package/dist/agents/tool-filter.js +50 -0
- package/dist/agents/tool-filter.js.map +1 -0
- package/dist/agents/verify.d.ts +177 -0
- package/dist/agents/verify.d.ts.map +1 -0
- package/dist/agents/verify.js +305 -0
- package/dist/agents/verify.js.map +1 -0
- package/dist/bench/metrics.d.ts +714 -0
- package/dist/bench/metrics.d.ts.map +1 -0
- package/dist/bench/metrics.js +618 -0
- package/dist/bench/metrics.js.map +1 -0
- package/dist/bin/sema-tb.d.ts +3 -0
- package/dist/bin/sema-tb.d.ts.map +1 -0
- package/dist/bin/sema-tb.js +516 -0
- package/dist/bin/sema-tb.js.map +1 -0
- package/dist/bin/tb-env.d.ts +13 -0
- package/dist/bin/tb-env.d.ts.map +1 -0
- package/dist/bin/tb-env.js +26 -0
- package/dist/bin/tb-env.js.map +1 -0
- package/dist/brain/anthropic.d.ts +46 -0
- package/dist/brain/anthropic.d.ts.map +1 -0
- package/dist/brain/anthropic.js +830 -0
- package/dist/brain/anthropic.js.map +1 -0
- package/dist/brain/circuit-breaker.d.ts +46 -0
- package/dist/brain/circuit-breaker.d.ts.map +1 -0
- package/dist/brain/circuit-breaker.js +173 -0
- package/dist/brain/circuit-breaker.js.map +1 -0
- package/dist/brain/degrading.d.ts +98 -0
- package/dist/brain/degrading.d.ts.map +1 -0
- package/dist/brain/degrading.js +249 -0
- package/dist/brain/degrading.js.map +1 -0
- package/dist/brain/errors.d.ts +31 -0
- package/dist/brain/errors.d.ts.map +1 -0
- package/dist/brain/errors.js +58 -0
- package/dist/brain/errors.js.map +1 -0
- package/dist/brain/failover.d.ts +18 -0
- package/dist/brain/failover.d.ts.map +1 -0
- package/dist/brain/failover.js +118 -0
- package/dist/brain/failover.js.map +1 -0
- package/dist/brain/model-presets.d.ts +36 -0
- package/dist/brain/model-presets.d.ts.map +1 -0
- package/dist/brain/model-presets.js +54 -0
- package/dist/brain/model-presets.js.map +1 -0
- package/dist/brain/openai.d.ts +43 -0
- package/dist/brain/openai.d.ts.map +1 -0
- package/dist/brain/openai.js +784 -0
- package/dist/brain/openai.js.map +1 -0
- package/dist/brain/reasoning.d.ts +138 -0
- package/dist/brain/reasoning.d.ts.map +1 -0
- package/dist/brain/reasoning.js +146 -0
- package/dist/brain/reasoning.js.map +1 -0
- package/dist/brain/repetition.d.ts +60 -0
- package/dist/brain/repetition.d.ts.map +1 -0
- package/dist/brain/repetition.js +121 -0
- package/dist/brain/repetition.js.map +1 -0
- package/dist/brain/request-params.d.ts +29 -0
- package/dist/brain/request-params.d.ts.map +1 -0
- package/dist/brain/request-params.js +78 -0
- package/dist/brain/request-params.js.map +1 -0
- package/dist/brain/retry.d.ts +18 -0
- package/dist/brain/retry.d.ts.map +1 -0
- package/dist/brain/retry.js +42 -0
- package/dist/brain/retry.js.map +1 -0
- package/dist/brain/routing.d.ts +19 -0
- package/dist/brain/routing.d.ts.map +1 -0
- package/dist/brain/routing.js +44 -0
- package/dist/brain/routing.js.map +1 -0
- package/dist/brain/status-sink.d.ts +46 -0
- package/dist/brain/status-sink.d.ts.map +1 -0
- package/dist/brain/status-sink.js +36 -0
- package/dist/brain/status-sink.js.map +1 -0
- package/dist/brain/stream-engine.d.ts +85 -0
- package/dist/brain/stream-engine.d.ts.map +1 -0
- package/dist/brain/stream-engine.js +391 -0
- package/dist/brain/stream-engine.js.map +1 -0
- package/dist/brain/timeout.d.ts +44 -0
- package/dist/brain/timeout.d.ts.map +1 -0
- package/dist/brain/timeout.js +41 -0
- package/dist/brain/timeout.js.map +1 -0
- package/dist/brain/tool-call-repair.d.ts +15 -0
- package/dist/brain/tool-call-repair.d.ts.map +1 -0
- package/dist/brain/tool-call-repair.js +67 -0
- package/dist/brain/tool-call-repair.js.map +1 -0
- package/dist/brain/walltime.d.ts +14 -0
- package/dist/brain/walltime.d.ts.map +1 -0
- package/dist/brain/walltime.js +14 -0
- package/dist/brain/walltime.js.map +1 -0
- package/dist/core/arg-summary.d.ts +19 -0
- package/dist/core/arg-summary.d.ts.map +1 -0
- package/dist/core/arg-summary.js +96 -0
- package/dist/core/arg-summary.js.map +1 -0
- package/dist/core/ask-question.d.ts +113 -0
- package/dist/core/ask-question.d.ts.map +1 -0
- package/dist/core/ask-question.js +246 -0
- package/dist/core/ask-question.js.map +1 -0
- package/dist/core/auto-compaction.d.ts +341 -0
- package/dist/core/auto-compaction.d.ts.map +1 -0
- package/dist/core/auto-compaction.js +495 -0
- package/dist/core/auto-compaction.js.map +1 -0
- package/dist/core/auto-promote.d.ts +126 -0
- package/dist/core/auto-promote.d.ts.map +1 -0
- package/dist/core/auto-promote.js +171 -0
- package/dist/core/auto-promote.js.map +1 -0
- package/dist/core/background-shell.d.ts +128 -0
- package/dist/core/background-shell.d.ts.map +1 -0
- package/dist/core/background-shell.js +42 -0
- package/dist/core/background-shell.js.map +1 -0
- package/dist/core/cache-break-detector.d.ts +63 -0
- package/dist/core/cache-break-detector.d.ts.map +1 -0
- package/dist/core/cache-break-detector.js +0 -0
- package/dist/core/cache-break-detector.js.map +1 -0
- package/dist/core/canonical-json.d.ts +45 -0
- package/dist/core/canonical-json.d.ts.map +1 -0
- package/dist/core/canonical-json.js +132 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/checkpoint-store.d.ts +1101 -0
- package/dist/core/checkpoint-store.d.ts.map +1 -0
- package/dist/core/checkpoint-store.js +514 -0
- package/dist/core/checkpoint-store.js.map +1 -0
- package/dist/core/consolidate-scope.d.ts +94 -0
- package/dist/core/consolidate-scope.d.ts.map +1 -0
- package/dist/core/consolidate-scope.js +158 -0
- package/dist/core/consolidate-scope.js.map +1 -0
- package/dist/core/context-edit.d.ts +82 -0
- package/dist/core/context-edit.d.ts.map +1 -0
- package/dist/core/context-edit.js +149 -0
- package/dist/core/context-edit.js.map +1 -0
- package/dist/core/context-guard.d.ts +43 -0
- package/dist/core/context-guard.d.ts.map +1 -0
- package/dist/core/context-guard.js +171 -0
- package/dist/core/context-guard.js.map +1 -0
- package/dist/core/dynamic-recall.d.ts +100 -0
- package/dist/core/dynamic-recall.d.ts.map +1 -0
- package/dist/core/dynamic-recall.js +108 -0
- package/dist/core/dynamic-recall.js.map +1 -0
- package/dist/core/exec-gate.d.ts +74 -0
- package/dist/core/exec-gate.d.ts.map +1 -0
- package/dist/core/exec-gate.js +143 -0
- package/dist/core/exec-gate.js.map +1 -0
- package/dist/core/exec-output-tail.d.ts +37 -0
- package/dist/core/exec-output-tail.d.ts.map +1 -0
- package/dist/core/exec-output-tail.js +63 -0
- package/dist/core/exec-output-tail.js.map +1 -0
- package/dist/core/file-snapshot-store.d.ts +137 -0
- package/dist/core/file-snapshot-store.d.ts.map +1 -0
- package/dist/core/file-snapshot-store.js +319 -0
- package/dist/core/file-snapshot-store.js.map +1 -0
- package/dist/core/git-worktree-env.d.ts +41 -0
- package/dist/core/git-worktree-env.d.ts.map +1 -0
- package/dist/core/git-worktree-env.js +64 -0
- package/dist/core/git-worktree-env.js.map +1 -0
- package/dist/core/hooks.d.ts +372 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +269 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/lsp-diagnostics.d.ts +74 -0
- package/dist/core/lsp-diagnostics.d.ts.map +1 -0
- package/dist/core/lsp-diagnostics.js +125 -0
- package/dist/core/lsp-diagnostics.js.map +1 -0
- package/dist/core/lsp-protocol.d.ts +28 -0
- package/dist/core/lsp-protocol.d.ts.map +1 -0
- package/dist/core/lsp-protocol.js +179 -0
- package/dist/core/lsp-protocol.js.map +1 -0
- package/dist/core/lsp-session.d.ts +56 -0
- package/dist/core/lsp-session.d.ts.map +1 -0
- package/dist/core/lsp-session.js +185 -0
- package/dist/core/lsp-session.js.map +1 -0
- package/dist/core/lsp.d.ts +132 -0
- package/dist/core/lsp.d.ts.map +1 -0
- package/dist/core/lsp.js +147 -0
- package/dist/core/lsp.js.map +1 -0
- package/dist/core/mcp.d.ts +294 -0
- package/dist/core/mcp.d.ts.map +1 -0
- package/dist/core/mcp.js +992 -0
- package/dist/core/mcp.js.map +1 -0
- package/dist/core/media-byte-cap.d.ts +34 -0
- package/dist/core/media-byte-cap.d.ts.map +1 -0
- package/dist/core/media-byte-cap.js +76 -0
- package/dist/core/media-byte-cap.js.map +1 -0
- package/dist/core/memory-engine/data-plane.d.ts +103 -0
- package/dist/core/memory-engine/data-plane.d.ts.map +1 -0
- package/dist/core/memory-engine/data-plane.js +272 -0
- package/dist/core/memory-engine/data-plane.js.map +1 -0
- package/dist/core/memory-engine/dual-root.d.ts +40 -0
- package/dist/core/memory-engine/dual-root.d.ts.map +1 -0
- package/dist/core/memory-engine/dual-root.js +95 -0
- package/dist/core/memory-engine/dual-root.js.map +1 -0
- package/dist/core/memory-engine/engine.d.ts +161 -0
- package/dist/core/memory-engine/engine.d.ts.map +1 -0
- package/dist/core/memory-engine/engine.js +1110 -0
- package/dist/core/memory-engine/engine.js.map +1 -0
- package/dist/core/memory-engine/file-backend.d.ts +162 -0
- package/dist/core/memory-engine/file-backend.d.ts.map +1 -0
- package/dist/core/memory-engine/file-backend.js +948 -0
- package/dist/core/memory-engine/file-backend.js.map +1 -0
- package/dist/core/memory-engine/frontmatter.d.ts +24 -0
- package/dist/core/memory-engine/frontmatter.d.ts.map +1 -0
- package/dist/core/memory-engine/frontmatter.js +135 -0
- package/dist/core/memory-engine/frontmatter.js.map +1 -0
- package/dist/core/memory-engine/index.d.ts +13 -0
- package/dist/core/memory-engine/index.d.ts.map +1 -0
- package/dist/core/memory-engine/index.js +28 -0
- package/dist/core/memory-engine/index.js.map +1 -0
- package/dist/core/memory-engine/layout.d.ts +123 -0
- package/dist/core/memory-engine/layout.d.ts.map +1 -0
- package/dist/core/memory-engine/layout.js +643 -0
- package/dist/core/memory-engine/layout.js.map +1 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts +22 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts.map +1 -0
- package/dist/core/memory-engine/memory-backend-contract.js +271 -0
- package/dist/core/memory-engine/memory-backend-contract.js.map +1 -0
- package/dist/core/memory-engine/migrate.d.ts +17 -0
- package/dist/core/memory-engine/migrate.d.ts.map +1 -0
- package/dist/core/memory-engine/migrate.js +35 -0
- package/dist/core/memory-engine/migrate.js.map +1 -0
- package/dist/core/memory-engine/scan.d.ts +20 -0
- package/dist/core/memory-engine/scan.d.ts.map +1 -0
- package/dist/core/memory-engine/scan.js +84 -0
- package/dist/core/memory-engine/scan.js.map +1 -0
- package/dist/core/memory-engine/scope-contract.d.ts +104 -0
- package/dist/core/memory-engine/scope-contract.d.ts.map +1 -0
- package/dist/core/memory-engine/scope-contract.js +288 -0
- package/dist/core/memory-engine/scope-contract.js.map +1 -0
- package/dist/core/memory-engine/sync-client.d.ts +100 -0
- package/dist/core/memory-engine/sync-client.d.ts.map +1 -0
- package/dist/core/memory-engine/sync-client.js +328 -0
- package/dist/core/memory-engine/sync-client.js.map +1 -0
- package/dist/core/memory-engine/sync.d.ts +97 -0
- package/dist/core/memory-engine/sync.d.ts.map +1 -0
- package/dist/core/memory-engine/sync.js +91 -0
- package/dist/core/memory-engine/sync.js.map +1 -0
- package/dist/core/memory-engine/types.d.ts +279 -0
- package/dist/core/memory-engine/types.d.ts.map +1 -0
- package/dist/core/memory-engine/types.js +9 -0
- package/dist/core/memory-engine/types.js.map +1 -0
- package/dist/core/memory-recall.d.ts +261 -0
- package/dist/core/memory-recall.d.ts.map +1 -0
- package/dist/core/memory-recall.js +600 -0
- package/dist/core/memory-recall.js.map +1 -0
- package/dist/core/memory-vector.d.ts +24 -0
- package/dist/core/memory-vector.d.ts.map +1 -0
- package/dist/core/memory-vector.js +51 -0
- package/dist/core/memory-vector.js.map +1 -0
- package/dist/core/memory.d.ts +502 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +881 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/message-utils.d.ts +7 -0
- package/dist/core/message-utils.d.ts.map +1 -0
- package/dist/core/message-utils.js +10 -0
- package/dist/core/message-utils.js.map +1 -0
- package/dist/core/oracle-isolation.d.ts +85 -0
- package/dist/core/oracle-isolation.d.ts.map +1 -0
- package/dist/core/oracle-isolation.js +121 -0
- package/dist/core/oracle-isolation.js.map +1 -0
- package/dist/core/permission-rules.d.ts +102 -0
- package/dist/core/permission-rules.d.ts.map +1 -0
- package/dist/core/permission-rules.js +357 -0
- package/dist/core/permission-rules.js.map +1 -0
- package/dist/core/present-plan-tool.d.ts +28 -0
- package/dist/core/present-plan-tool.d.ts.map +1 -0
- package/dist/core/present-plan-tool.js +119 -0
- package/dist/core/present-plan-tool.js.map +1 -0
- package/dist/core/pricing.d.ts +48 -0
- package/dist/core/pricing.d.ts.map +1 -0
- package/dist/core/pricing.js +46 -0
- package/dist/core/pricing.js.map +1 -0
- package/dist/core/property-harness.d.ts +126 -0
- package/dist/core/property-harness.d.ts.map +1 -0
- package/dist/core/property-harness.js +192 -0
- package/dist/core/property-harness.js.map +1 -0
- package/dist/core/push-queue.d.ts +10 -0
- package/dist/core/push-queue.d.ts.map +1 -0
- package/dist/core/push-queue.js +42 -0
- package/dist/core/push-queue.js.map +1 -0
- package/dist/core/remote-env.d.ts +432 -0
- package/dist/core/remote-env.d.ts.map +1 -0
- package/dist/core/remote-env.js +77 -0
- package/dist/core/remote-env.js.map +1 -0
- package/dist/core/roles.d.ts +74 -0
- package/dist/core/roles.d.ts.map +1 -0
- package/dist/core/roles.js +272 -0
- package/dist/core/roles.js.map +1 -0
- package/dist/core/runner/active-skill-scope.d.ts +64 -0
- package/dist/core/runner/active-skill-scope.d.ts.map +1 -0
- package/dist/core/runner/active-skill-scope.js +197 -0
- package/dist/core/runner/active-skill-scope.js.map +1 -0
- package/dist/core/runner/assemble-result.d.ts +191 -0
- package/dist/core/runner/assemble-result.d.ts.map +1 -0
- package/dist/core/runner/assemble-result.js +250 -0
- package/dist/core/runner/assemble-result.js.map +1 -0
- package/dist/core/runner/call-cap.d.ts +130 -0
- package/dist/core/runner/call-cap.d.ts.map +1 -0
- package/dist/core/runner/call-cap.js +151 -0
- package/dist/core/runner/call-cap.js.map +1 -0
- package/dist/core/runner/grounding-signal.d.ts +12 -0
- package/dist/core/runner/grounding-signal.d.ts.map +1 -0
- package/dist/core/runner/grounding-signal.js +94 -0
- package/dist/core/runner/grounding-signal.js.map +1 -0
- package/dist/core/runner/image.d.ts +23 -0
- package/dist/core/runner/image.d.ts.map +1 -0
- package/dist/core/runner/image.js +151 -0
- package/dist/core/runner/image.js.map +1 -0
- package/dist/core/runner/memory-consolidation.d.ts +112 -0
- package/dist/core/runner/memory-consolidation.d.ts.map +1 -0
- package/dist/core/runner/memory-consolidation.js +372 -0
- package/dist/core/runner/memory-consolidation.js.map +1 -0
- package/dist/core/runner/prepare-task.d.ts +583 -0
- package/dist/core/runner/prepare-task.d.ts.map +1 -0
- package/dist/core/runner/prepare-task.js +3612 -0
- package/dist/core/runner/prepare-task.js.map +1 -0
- package/dist/core/runner/prompt-suggestions.d.ts +33 -0
- package/dist/core/runner/prompt-suggestions.d.ts.map +1 -0
- package/dist/core/runner/prompt-suggestions.js +116 -0
- package/dist/core/runner/prompt-suggestions.js.map +1 -0
- package/dist/core/runner/runtask.d.ts +274 -0
- package/dist/core/runner/runtask.d.ts.map +1 -0
- package/dist/core/runner/runtask.js +4606 -0
- package/dist/core/runner/runtask.js.map +1 -0
- package/dist/core/runner/session-rule-policy.d.ts +28 -0
- package/dist/core/runner/session-rule-policy.d.ts.map +1 -0
- package/dist/core/runner/session-rule-policy.js +110 -0
- package/dist/core/runner/session-rule-policy.js.map +1 -0
- package/dist/core/runner/strict-output-schema.d.ts +36 -0
- package/dist/core/runner/strict-output-schema.d.ts.map +1 -0
- package/dist/core/runner/strict-output-schema.js +365 -0
- package/dist/core/runner/strict-output-schema.js.map +1 -0
- package/dist/core/runner/synthetic-tools.d.ts +72 -0
- package/dist/core/runner/synthetic-tools.d.ts.map +1 -0
- package/dist/core/runner/synthetic-tools.js +203 -0
- package/dist/core/runner/synthetic-tools.js.map +1 -0
- package/dist/core/runner/tool-disclosure.d.ts +117 -0
- package/dist/core/runner/tool-disclosure.d.ts.map +1 -0
- package/dist/core/runner/tool-disclosure.js +0 -0
- package/dist/core/runner/tool-disclosure.js.map +1 -0
- package/dist/core/runner/turn-attachments.d.ts +381 -0
- package/dist/core/runner/turn-attachments.d.ts.map +1 -0
- package/dist/core/runner/turn-attachments.js +596 -0
- package/dist/core/runner/turn-attachments.js.map +1 -0
- package/dist/core/runner/usage-accounting.d.ts +35 -0
- package/dist/core/runner/usage-accounting.d.ts.map +1 -0
- package/dist/core/runner/usage-accounting.js +45 -0
- package/dist/core/runner/usage-accounting.js.map +1 -0
- package/dist/core/runtime.d.ts +9 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +17 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/safety-axis-vocab.d.ts +33 -0
- package/dist/core/safety-axis-vocab.d.ts.map +1 -0
- package/dist/core/safety-axis-vocab.js +35 -0
- package/dist/core/safety-axis-vocab.js.map +1 -0
- package/dist/core/safety-merge-corpus.d.ts +48 -0
- package/dist/core/safety-merge-corpus.d.ts.map +1 -0
- package/dist/core/safety-merge-corpus.js +203 -0
- package/dist/core/safety-merge-corpus.js.map +1 -0
- package/dist/core/scheduler.d.ts +126 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +54 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/secret-env.d.ts +23 -0
- package/dist/core/secret-env.d.ts.map +1 -0
- package/dist/core/secret-env.js +35 -0
- package/dist/core/secret-env.js.map +1 -0
- package/dist/core/select-model.d.ts +26 -0
- package/dist/core/select-model.d.ts.map +1 -0
- package/dist/core/select-model.js +58 -0
- package/dist/core/select-model.js.map +1 -0
- package/dist/core/sensitive-path-policy.d.ts +24 -0
- package/dist/core/sensitive-path-policy.d.ts.map +1 -0
- package/dist/core/sensitive-path-policy.js +96 -0
- package/dist/core/sensitive-path-policy.js.map +1 -0
- package/dist/core/session-policy-store.d.ts +102 -0
- package/dist/core/session-policy-store.d.ts.map +1 -0
- package/dist/core/session-policy-store.js +177 -0
- package/dist/core/session-policy-store.js.map +1 -0
- package/dist/core/session-reconcile.d.ts +63 -0
- package/dist/core/session-reconcile.d.ts.map +1 -0
- package/dist/core/session-reconcile.js +71 -0
- package/dist/core/session-reconcile.js.map +1 -0
- package/dist/core/session-store.d.ts +99 -0
- package/dist/core/session-store.d.ts.map +1 -0
- package/dist/core/session-store.js +298 -0
- package/dist/core/session-store.js.map +1 -0
- package/dist/core/session.d.ts +144 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +56 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/spec-contract.d.ts +147 -0
- package/dist/core/spec-contract.d.ts.map +1 -0
- package/dist/core/spec-contract.js +340 -0
- package/dist/core/spec-contract.js.map +1 -0
- package/dist/core/strategy-store.d.ts +50 -0
- package/dist/core/strategy-store.d.ts.map +1 -0
- package/dist/core/strategy-store.js +100 -0
- package/dist/core/strategy-store.js.map +1 -0
- package/dist/core/stub-env.d.ts +35 -0
- package/dist/core/stub-env.d.ts.map +1 -0
- package/dist/core/stub-env.js +69 -0
- package/dist/core/stub-env.js.map +1 -0
- package/dist/core/task-notification.d.ts +115 -0
- package/dist/core/task-notification.d.ts.map +1 -0
- package/dist/core/task-notification.js +247 -0
- package/dist/core/task-notification.js.map +1 -0
- package/dist/core/task-outcome.d.ts +80 -0
- package/dist/core/task-outcome.d.ts.map +1 -0
- package/dist/core/task-outcome.js +40 -0
- package/dist/core/task-outcome.js.map +1 -0
- package/dist/core/task-registry.d.ts +349 -0
- package/dist/core/task-registry.d.ts.map +1 -0
- package/dist/core/task-registry.js +1751 -0
- package/dist/core/task-registry.js.map +1 -0
- package/dist/core/tighten-task-spec.d.ts +27 -0
- package/dist/core/tighten-task-spec.d.ts.map +1 -0
- package/dist/core/tighten-task-spec.js +95 -0
- package/dist/core/tighten-task-spec.js.map +1 -0
- package/dist/core/tool-detach.d.ts +31 -0
- package/dist/core/tool-detach.d.ts.map +1 -0
- package/dist/core/tool-detach.js +62 -0
- package/dist/core/tool-detach.js.map +1 -0
- package/dist/core/tool-errors.d.ts +72 -0
- package/dist/core/tool-errors.d.ts.map +1 -0
- package/dist/core/tool-errors.js +194 -0
- package/dist/core/tool-errors.js.map +1 -0
- package/dist/core/tool-name-aliases.d.ts +5 -0
- package/dist/core/tool-name-aliases.d.ts.map +1 -0
- package/dist/core/tool-name-aliases.js +130 -0
- package/dist/core/tool-name-aliases.js.map +1 -0
- package/dist/core/tool-policy.d.ts +295 -0
- package/dist/core/tool-policy.d.ts.map +1 -0
- package/dist/core/tool-policy.js +567 -0
- package/dist/core/tool-policy.js.map +1 -0
- package/dist/core/tool-result-budget.d.ts +44 -0
- package/dist/core/tool-result-budget.d.ts.map +1 -0
- package/dist/core/tool-result-budget.js +140 -0
- package/dist/core/tool-result-budget.js.map +1 -0
- package/dist/core/tool-result-store.d.ts +136 -0
- package/dist/core/tool-result-store.d.ts.map +1 -0
- package/dist/core/tool-result-store.js +219 -0
- package/dist/core/tool-result-store.js.map +1 -0
- package/dist/core/tools.d.ts +14 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +98 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/trace.d.ts +340 -0
- package/dist/core/trace.d.ts.map +1 -0
- package/dist/core/trace.js +12 -0
- package/dist/core/trace.js.map +1 -0
- package/dist/core/types.d.ts +2828 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/untrusted-egress.d.ts +32 -0
- package/dist/core/untrusted-egress.d.ts.map +1 -0
- package/dist/core/untrusted-egress.js +49 -0
- package/dist/core/untrusted-egress.js.map +1 -0
- package/dist/core/untrusted-text.d.ts +64 -0
- package/dist/core/untrusted-text.d.ts.map +1 -0
- package/dist/core/untrusted-text.js +119 -0
- package/dist/core/untrusted-text.js.map +1 -0
- package/dist/core/warm-resume.d.ts +23 -0
- package/dist/core/warm-resume.d.ts.map +1 -0
- package/dist/core/warm-resume.js +28 -0
- package/dist/core/warm-resume.js.map +1 -0
- package/dist/core/with-retry.d.ts +43 -0
- package/dist/core/with-retry.d.ts.map +1 -0
- package/dist/core/with-retry.js +59 -0
- package/dist/core/with-retry.js.map +1 -0
- package/dist/core/workflow-journal-store.d.ts +44 -0
- package/dist/core/workflow-journal-store.d.ts.map +1 -0
- package/dist/core/workflow-journal-store.js +47 -0
- package/dist/core/workflow-journal-store.js.map +1 -0
- package/dist/core/workflow-run-store-contract.d.ts +31 -0
- package/dist/core/workflow-run-store-contract.d.ts.map +1 -0
- package/dist/core/workflow-run-store-contract.js +191 -0
- package/dist/core/workflow-run-store-contract.js.map +1 -0
- package/dist/core/workflow-run-store.d.ts +149 -0
- package/dist/core/workflow-run-store.d.ts.map +1 -0
- package/dist/core/workflow-run-store.js +110 -0
- package/dist/core/workflow-run-store.js.map +1 -0
- package/dist/engine/compaction/compaction.d.ts +139 -0
- package/dist/engine/compaction/compaction.d.ts.map +1 -0
- package/dist/engine/compaction/compaction.js +1030 -0
- package/dist/engine/compaction/compaction.js.map +1 -0
- package/dist/engine/compaction/utils.d.ts +45 -0
- package/dist/engine/compaction/utils.d.ts.map +1 -0
- package/dist/engine/compaction/utils.js +203 -0
- package/dist/engine/compaction/utils.js.map +1 -0
- package/dist/engine/execution-env/kill-tree.d.ts +20 -0
- package/dist/engine/execution-env/kill-tree.d.ts.map +1 -0
- package/dist/engine/execution-env/kill-tree.js +183 -0
- package/dist/engine/execution-env/kill-tree.js.map +1 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +133 -0
- package/dist/engine/execution-env/node-execution-env.d.ts.map +1 -0
- package/dist/engine/execution-env/node-execution-env.js +1031 -0
- package/dist/engine/execution-env/node-execution-env.js.map +1 -0
- package/dist/engine/harness/agent-harness.d.ts +174 -0
- package/dist/engine/harness/agent-harness.d.ts.map +1 -0
- package/dist/engine/harness/agent-harness.js +1053 -0
- package/dist/engine/harness/agent-harness.js.map +1 -0
- package/dist/engine/harness/messages.d.ts +17 -0
- package/dist/engine/harness/messages.d.ts.map +1 -0
- package/dist/engine/harness/messages.js +122 -0
- package/dist/engine/harness/messages.js.map +1 -0
- package/dist/engine/harness/types.d.ts +713 -0
- package/dist/engine/harness/types.d.ts.map +1 -0
- package/dist/engine/harness/types.js +100 -0
- package/dist/engine/harness/types.js.map +1 -0
- package/dist/engine/llm/diagnostics.d.ts +23 -0
- package/dist/engine/llm/diagnostics.d.ts.map +1 -0
- package/dist/engine/llm/diagnostics.js +32 -0
- package/dist/engine/llm/diagnostics.js.map +1 -0
- package/dist/engine/llm/event-stream.d.ts +25 -0
- package/dist/engine/llm/event-stream.d.ts.map +1 -0
- package/dist/engine/llm/event-stream.js +103 -0
- package/dist/engine/llm/event-stream.js.map +1 -0
- package/dist/engine/llm/index.d.ts +12 -0
- package/dist/engine/llm/index.d.ts.map +1 -0
- package/dist/engine/llm/index.js +12 -0
- package/dist/engine/llm/index.js.map +1 -0
- package/dist/engine/llm/types.d.ts +753 -0
- package/dist/engine/llm/types.d.ts.map +1 -0
- package/dist/engine/llm/types.js +2 -0
- package/dist/engine/llm/types.js.map +1 -0
- package/dist/engine/llm/validation.d.ts +8 -0
- package/dist/engine/llm/validation.d.ts.map +1 -0
- package/dist/engine/llm/validation.js +318 -0
- package/dist/engine/llm/validation.js.map +1 -0
- package/dist/engine/loop/agent-loop.d.ts +74 -0
- package/dist/engine/loop/agent-loop.d.ts.map +1 -0
- package/dist/engine/loop/agent-loop.js +1490 -0
- package/dist/engine/loop/agent-loop.js.map +1 -0
- package/dist/engine/loop/runtime-deps.d.ts +17 -0
- package/dist/engine/loop/runtime-deps.d.ts.map +1 -0
- package/dist/engine/loop/runtime-deps.js +21 -0
- package/dist/engine/loop/runtime-deps.js.map +1 -0
- package/dist/engine/loop/types.d.ts +609 -0
- package/dist/engine/loop/types.d.ts.map +1 -0
- package/dist/engine/loop/types.js +2 -0
- package/dist/engine/loop/types.js.map +1 -0
- package/dist/engine/lsp/frame-decoder.d.ts +16 -0
- package/dist/engine/lsp/frame-decoder.d.ts.map +1 -0
- package/dist/engine/lsp/frame-decoder.js +53 -0
- package/dist/engine/lsp/frame-decoder.js.map +1 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +105 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts.map +1 -0
- package/dist/engine/lsp/node-lsp-manager.js +343 -0
- package/dist/engine/lsp/node-lsp-manager.js.map +1 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts +37 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts.map +1 -0
- package/dist/engine/lsp/stdio-lsp-transport.js +185 -0
- package/dist/engine/lsp/stdio-lsp-transport.js.map +1 -0
- package/dist/engine/session/import-validate.d.ts +44 -0
- package/dist/engine/session/import-validate.d.ts.map +1 -0
- package/dist/engine/session/import-validate.js +92 -0
- package/dist/engine/session/import-validate.js.map +1 -0
- package/dist/engine/session/memory-repo.d.ts +25 -0
- package/dist/engine/session/memory-repo.d.ts.map +1 -0
- package/dist/engine/session/memory-repo.js +59 -0
- package/dist/engine/session/memory-repo.js.map +1 -0
- package/dist/engine/session/memory-storage.d.ts +14 -0
- package/dist/engine/session/memory-storage.d.ts.map +1 -0
- package/dist/engine/session/memory-storage.js +17 -0
- package/dist/engine/session/memory-storage.js.map +1 -0
- package/dist/engine/session/repo-utils.d.ts +11 -0
- package/dist/engine/session/repo-utils.d.ts.map +1 -0
- package/dist/engine/session/repo-utils.js +40 -0
- package/dist/engine/session/repo-utils.js.map +1 -0
- package/dist/engine/session/session.d.ts +34 -0
- package/dist/engine/session/session.d.ts.map +1 -0
- package/dist/engine/session/session.js +227 -0
- package/dist/engine/session/session.js.map +1 -0
- package/dist/engine/session/storage-base.d.ts +38 -0
- package/dist/engine/session/storage-base.d.ts.map +1 -0
- package/dist/engine/session/storage-base.js +157 -0
- package/dist/engine/session/storage-base.js.map +1 -0
- package/dist/engine/session/timestamps.d.ts +3 -0
- package/dist/engine/session/timestamps.d.ts.map +1 -0
- package/dist/engine/session/timestamps.js +15 -0
- package/dist/engine/session/timestamps.js.map +1 -0
- package/dist/engine/session/uuid.d.ts +2 -0
- package/dist/engine/session/uuid.d.ts.map +1 -0
- package/dist/engine/session/uuid.js +50 -0
- package/dist/engine/session/uuid.js.map +1 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +374 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/harness.d.ts +26 -0
- package/dist/internal/harness.d.ts.map +1 -0
- package/dist/internal/harness.js +24 -0
- package/dist/internal/harness.js.map +1 -0
- package/dist/internal/llm.d.ts +9 -0
- package/dist/internal/llm.d.ts.map +1 -0
- package/dist/internal/llm.js +8 -0
- package/dist/internal/llm.js.map +1 -0
- package/dist/orchestration/builtin-workflows.d.ts +44 -0
- package/dist/orchestration/builtin-workflows.d.ts.map +1 -0
- package/dist/orchestration/builtin-workflows.js +165 -0
- package/dist/orchestration/builtin-workflows.js.map +1 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts +24 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts.map +1 -0
- package/dist/orchestration/dev-vm-script-runner.js +106 -0
- package/dist/orchestration/dev-vm-script-runner.js.map +1 -0
- package/dist/orchestration/goal.d.ts +97 -0
- package/dist/orchestration/goal.d.ts.map +1 -0
- package/dist/orchestration/goal.js +248 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/orchestration/run-spec.d.ts +63 -0
- package/dist/orchestration/run-spec.d.ts.map +1 -0
- package/dist/orchestration/run-spec.js +274 -0
- package/dist/orchestration/run-spec.js.map +1 -0
- package/dist/orchestration/run-workflow-tool.d.ts +187 -0
- package/dist/orchestration/run-workflow-tool.d.ts.map +1 -0
- package/dist/orchestration/run-workflow-tool.js +612 -0
- package/dist/orchestration/run-workflow-tool.js.map +1 -0
- package/dist/orchestration/workflow-governance.d.ts +70 -0
- package/dist/orchestration/workflow-governance.d.ts.map +1 -0
- package/dist/orchestration/workflow-governance.js +176 -0
- package/dist/orchestration/workflow-governance.js.map +1 -0
- package/dist/orchestration/workflow-meta.d.ts +41 -0
- package/dist/orchestration/workflow-meta.d.ts.map +1 -0
- package/dist/orchestration/workflow-meta.js +426 -0
- package/dist/orchestration/workflow-meta.js.map +1 -0
- package/dist/orchestration/workflow-observe.d.ts +77 -0
- package/dist/orchestration/workflow-observe.d.ts.map +1 -0
- package/dist/orchestration/workflow-observe.js +177 -0
- package/dist/orchestration/workflow-observe.js.map +1 -0
- package/dist/orchestration/workflow-primitives.d.ts +31 -0
- package/dist/orchestration/workflow-primitives.d.ts.map +1 -0
- package/dist/orchestration/workflow-primitives.js +104 -0
- package/dist/orchestration/workflow-primitives.js.map +1 -0
- package/dist/orchestration/workflow-sandbox-conformance.d.ts +34 -0
- package/dist/orchestration/workflow-sandbox-conformance.d.ts.map +1 -0
- package/dist/orchestration/workflow-sandbox-conformance.js +301 -0
- package/dist/orchestration/workflow-sandbox-conformance.js.map +1 -0
- package/dist/orchestration/workflow-script-runner.d.ts +127 -0
- package/dist/orchestration/workflow-script-runner.d.ts.map +1 -0
- package/dist/orchestration/workflow-script-runner.js +48 -0
- package/dist/orchestration/workflow-script-runner.js.map +1 -0
- package/dist/orchestration/workflow-script-store.d.ts +99 -0
- package/dist/orchestration/workflow-script-store.d.ts.map +1 -0
- package/dist/orchestration/workflow-script-store.js +133 -0
- package/dist/orchestration/workflow-script-store.js.map +1 -0
- package/dist/orchestration/workflow-size-guideline.d.ts +50 -0
- package/dist/orchestration/workflow-size-guideline.d.ts.map +1 -0
- package/dist/orchestration/workflow-size-guideline.js +78 -0
- package/dist/orchestration/workflow-size-guideline.js.map +1 -0
- package/dist/orchestration/workflow.d.ts +624 -0
- package/dist/orchestration/workflow.d.ts.map +1 -0
- package/dist/orchestration/workflow.js +1596 -0
- package/dist/orchestration/workflow.js.map +1 -0
- package/dist/prompts/default.d.ts +474 -0
- package/dist/prompts/default.d.ts.map +1 -0
- package/dist/prompts/default.js +676 -0
- package/dist/prompts/default.js.map +1 -0
- package/dist/prompts/supervisor.d.ts +60 -0
- package/dist/prompts/supervisor.d.ts.map +1 -0
- package/dist/prompts/supervisor.js +162 -0
- package/dist/prompts/supervisor.js.map +1 -0
- package/dist/scenarios/env.d.ts +41 -0
- package/dist/scenarios/env.d.ts.map +1 -0
- package/dist/scenarios/env.js +65 -0
- package/dist/scenarios/env.js.map +1 -0
- package/dist/scenarios/full-body.d.ts +47 -0
- package/dist/scenarios/full-body.d.ts.map +1 -0
- package/dist/scenarios/full-body.js +36 -0
- package/dist/scenarios/full-body.js.map +1 -0
- package/dist/scenarios/scenario-registry.d.ts +107 -0
- package/dist/scenarios/scenario-registry.d.ts.map +1 -0
- package/dist/scenarios/scenario-registry.js +192 -0
- package/dist/scenarios/scenario-registry.js.map +1 -0
- package/dist/scenarios/teacher-quickstart.d.ts +41 -0
- package/dist/scenarios/teacher-quickstart.d.ts.map +1 -0
- package/dist/scenarios/teacher-quickstart.js +32 -0
- package/dist/scenarios/teacher-quickstart.js.map +1 -0
- package/dist/server/http.d.ts +36 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +144 -0
- package/dist/server/http.js.map +1 -0
- package/dist/stores/file/checkpoint-store.d.ts +62 -0
- package/dist/stores/file/checkpoint-store.d.ts.map +1 -0
- package/dist/stores/file/checkpoint-store.js +250 -0
- package/dist/stores/file/checkpoint-store.js.map +1 -0
- package/dist/stores/file/file-snapshot-store.d.ts +43 -0
- package/dist/stores/file/file-snapshot-store.d.ts.map +1 -0
- package/dist/stores/file/file-snapshot-store.js +374 -0
- package/dist/stores/file/file-snapshot-store.js.map +1 -0
- package/dist/stores/file/fs-atomic.d.ts +95 -0
- package/dist/stores/file/fs-atomic.d.ts.map +1 -0
- package/dist/stores/file/fs-atomic.js +415 -0
- package/dist/stores/file/fs-atomic.js.map +1 -0
- package/dist/stores/file/index.d.ts +98 -0
- package/dist/stores/file/index.d.ts.map +1 -0
- package/dist/stores/file/index.js +109 -0
- package/dist/stores/file/index.js.map +1 -0
- package/dist/stores/file/memory-store.d.ts +95 -0
- package/dist/stores/file/memory-store.d.ts.map +1 -0
- package/dist/stores/file/memory-store.js +393 -0
- package/dist/stores/file/memory-store.js.map +1 -0
- package/dist/stores/file/session-policy-store.d.ts +24 -0
- package/dist/stores/file/session-policy-store.d.ts.map +1 -0
- package/dist/stores/file/session-policy-store.js +123 -0
- package/dist/stores/file/session-policy-store.js.map +1 -0
- package/dist/stores/file/session-store.d.ts +34 -0
- package/dist/stores/file/session-store.d.ts.map +1 -0
- package/dist/stores/file/session-store.js +175 -0
- package/dist/stores/file/session-store.js.map +1 -0
- package/dist/stores/file/tool-result-store.d.ts +23 -0
- package/dist/stores/file/tool-result-store.d.ts.map +1 -0
- package/dist/stores/file/tool-result-store.js +61 -0
- package/dist/stores/file/tool-result-store.js.map +1 -0
- package/dist/stores/file/workflow-journal-store.d.ts +36 -0
- package/dist/stores/file/workflow-journal-store.d.ts.map +1 -0
- package/dist/stores/file/workflow-journal-store.js +157 -0
- package/dist/stores/file/workflow-journal-store.js.map +1 -0
- package/dist/stores/file/workflow-run-store.d.ts +58 -0
- package/dist/stores/file/workflow-run-store.d.ts.map +1 -0
- package/dist/stores/file/workflow-run-store.js +178 -0
- package/dist/stores/file/workflow-run-store.js.map +1 -0
- package/dist/stores/pg.d.ts +210 -0
- package/dist/stores/pg.d.ts.map +1 -0
- package/dist/stores/pg.js +652 -0
- package/dist/stores/pg.js.map +1 -0
- package/dist/tools/fs/encoding.d.ts +51 -0
- package/dist/tools/fs/encoding.d.ts.map +1 -0
- package/dist/tools/fs/encoding.js +74 -0
- package/dist/tools/fs/encoding.js.map +1 -0
- package/dist/tools/fs/gh-rate-limit.d.ts +19 -0
- package/dist/tools/fs/gh-rate-limit.d.ts.map +1 -0
- package/dist/tools/fs/gh-rate-limit.js +35 -0
- package/dist/tools/fs/gh-rate-limit.js.map +1 -0
- package/dist/tools/fs/index.d.ts +246 -0
- package/dist/tools/fs/index.d.ts.map +1 -0
- package/dist/tools/fs/index.js +2130 -0
- package/dist/tools/fs/index.js.map +1 -0
- package/dist/tools/fs/pdf.d.ts +106 -0
- package/dist/tools/fs/pdf.d.ts.map +1 -0
- package/dist/tools/fs/pdf.js +178 -0
- package/dist/tools/fs/pdf.js.map +1 -0
- package/dist/tools/fs/repo-map.d.ts +15 -0
- package/dist/tools/fs/repo-map.d.ts.map +1 -0
- package/dist/tools/fs/repo-map.js +251 -0
- package/dist/tools/fs/repo-map.js.map +1 -0
- package/dist/tools/fs/safety.d.ts +168 -0
- package/dist/tools/fs/safety.d.ts.map +1 -0
- package/dist/tools/fs/safety.js +479 -0
- package/dist/tools/fs/safety.js.map +1 -0
- package/dist/tools/fs/search.d.ts +118 -0
- package/dist/tools/fs/search.d.ts.map +1 -0
- package/dist/tools/fs/search.js +650 -0
- package/dist/tools/fs/search.js.map +1 -0
- package/dist/tools/gitea-issue.d.ts +39 -0
- package/dist/tools/gitea-issue.d.ts.map +1 -0
- package/dist/tools/gitea-issue.js +91 -0
- package/dist/tools/gitea-issue.js.map +1 -0
- package/dist/tools/monitor.d.ts +64 -0
- package/dist/tools/monitor.d.ts.map +1 -0
- package/dist/tools/monitor.js +135 -0
- package/dist/tools/monitor.js.map +1 -0
- package/dist/tools/scheduler-tools.d.ts +48 -0
- package/dist/tools/scheduler-tools.d.ts.map +1 -0
- package/dist/tools/scheduler-tools.js +449 -0
- package/dist/tools/scheduler-tools.js.map +1 -0
- package/dist/tools/sql-adapters.d.ts +32 -0
- package/dist/tools/sql-adapters.d.ts.map +1 -0
- package/dist/tools/sql-adapters.js +31 -0
- package/dist/tools/sql-adapters.js.map +1 -0
- package/dist/tools/sql.d.ts +36 -0
- package/dist/tools/sql.d.ts.map +1 -0
- package/dist/tools/sql.js +131 -0
- package/dist/tools/sql.js.map +1 -0
- package/dist/tools/task-list.d.ts +26 -0
- package/dist/tools/task-list.d.ts.map +1 -0
- package/dist/tools/task-list.js +352 -0
- package/dist/tools/task-list.js.map +1 -0
- package/dist/tools/todo.d.ts +11 -0
- package/dist/tools/todo.d.ts.map +1 -0
- package/dist/tools/todo.js +126 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/web.d.ts +59 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +607 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/tools/worktree.d.ts +88 -0
- package/dist/tools/worktree.d.ts.map +1 -0
- package/dist/tools/worktree.js +434 -0
- package/dist/tools/worktree.js.map +1 -0
- package/docs/A1-ATTRIBUTION-ROUND1-2026-07-09.md +181 -0
- package/docs/AB-ORACLE-GATE-VERDICT-2026-07-10.md +100 -0
- package/docs/ANCHOR-GAP-INVENTORY-2026-07-09.md +143 -0
- package/docs/ARCHITECTURE.md +125 -0
- package/docs/BUGHUNT-2026-07-05-NIGHT.md +98 -0
- package/docs/BUILD.md +63 -0
- package/docs/CANCEL-ASYNC-ATTRIBUTION-2026-07-09.md +98 -0
- package/docs/CC-198-VS-201-DRIFT-2026-07-09.md +70 -0
- package/docs/CC-BASELINE-FAKE-ZERO-AUDIT-2026-07-09.md +51 -0
- package/docs/CC-DRIFT-198-206-AGENT-TYPES-2026-07-10.md +82 -0
- package/docs/CC-DRIFT-198-206-CHANGELOG-2026-07-10.md +82 -0
- package/docs/CC-DRIFT-198-206-REMINDERS-2026-07-10.md +96 -0
- package/docs/CC-DRIFT-198-206-ROADMAP-2026-07-10.md +110 -0
- package/docs/CC-DRIFT-198-206-TOOL-INVENTORY-2026-07-10.md +53 -0
- package/docs/CC-DRIFT-198-206-USAGE-CONSTANTS-2026-07-10.md +64 -0
- package/docs/CC-DRIFT-198-206-WORKFLOW-2026-07-10.md +83 -0
- package/docs/CC-PARITY-CHECKLIST.md +220 -0
- package/docs/CC-PARITY-DEEP-SWEEP-2026-07-07.md +149 -0
- package/docs/CC-SUBAGENT-PROMPT-STUDY-2026-07-09.md +219 -0
- package/docs/CC-TASK-REMINDER-CADENCE-STUDY-2026-07-09.md +396 -0
- package/docs/CC-TOOL-PARITY-SWEEP-2026-07.md +56 -0
- package/docs/CC-TOOL-PROMPT-DEEP-DIFF-2026-07-08.md +274 -0
- package/docs/CC-TOOLSURFACE-DEEP-DIVE-2026-07-07.md +197 -0
- package/docs/CC206-OBSERVER-ANCHORS-2026-07-11.md +463 -0
- package/docs/CC207-CORE-SWEEP-BACKLOG-2026-07-12.md +155 -0
- package/docs/CENTER-CONTROL-PLANE-SEAM.md +86 -0
- package/docs/CLEANUP-CONTRACT-ANCHOR-2026-07-09.md +83 -0
- package/docs/COLD-START-RSI-2026-07-09.md +72 -0
- package/docs/COMPACTION-LIVE-AUDIT-2026-07-09.md +114 -0
- package/docs/CONTEXT-lifecycle-extension-points-and-stop-attribution.md +71 -0
- package/docs/COREWARS-POLYGLOT-TRIAGE-2026-07-09.md +85 -0
- package/docs/DEADTARGET-OVERFULL-HBOX-2026-07-10.md +92 -0
- package/docs/DEADTARGET-PATH-TRACING-REVERSE-2026-07-10.md +87 -0
- package/docs/DEADTARGET-WINNING-AVG-COREWARS-2026-07-10.md +96 -0
- package/docs/DEEPSEEK-API-LIMITS-PROBE-2026-07-09.md +118 -0
- package/docs/DESIGN-140-MOCK-VERIFY-2026-07-11.md +79 -0
- package/docs/DESIGN-140-VERIFICATION-2026-07-11.md +43 -0
- package/docs/DESIGN-DRAFT-workflow-collab-2026-07-11.md +56 -0
- package/docs/DESIGN-ORACLE-GROUNDING-GATE-2026-07-10.md +167 -0
- package/docs/DESIGN-TFRAG-RECONCILE-SCAFFOLD-2026-07-09.md +102 -0
- package/docs/EXP-PA2-PE-DESIGN-2026-07-11.md +220 -0
- package/docs/EXT-DOGFOOD-2026-07-12.md +50 -0
- package/docs/FINAL-VERIFY-SURFACE-AUDIT-2026-07-09.md +44 -0
- package/docs/FRAG-RECON-INVESTIGATION-2026-07-09.md +183 -0
- package/docs/HANDOFF.md +121 -0
- package/docs/KNOWN-ISSUES.md +96 -0
- package/docs/LEGW-WINDOW-TAX-2026-07-10.md +82 -0
- package/docs/LIVE-PROBE-BATCH-2026-07-11.md +207 -0
- package/docs/M2-CERT-ATTRIBUTION-2026-07-10.md +61 -0
- package/docs/M25-LEG-VARIANCE-ATTRIBUTION-2026-07-10.md +81 -0
- package/docs/MAILMAN-TIMEOUT-ATTRIBUTION-2026-07-10.md +88 -0
- package/docs/MEMORY-BACKEND-DIALECT-NOTES.md +69 -0
- package/docs/MTEB-ESCAPE-HATCH-ATTRIBUTION-2026-07-09.md +57 -0
- package/docs/MTEB-LEADERBOARD-ATTRIBUTION-2026-07-10.md +134 -0
- package/docs/ORACLE-GATE-NEGATIVE-SAMPLE-2026-07-11.md +28 -0
- package/docs/PARITY-CONTEXT-TRANSACTIONS-2026-07-10.md +67 -0
- package/docs/PARITY-PROGRESS-MATRIX-2026-07-10.md +37 -0
- package/docs/PARITY-SPOT-AGENT-TYPES-2026-07-10.md +70 -0
- package/docs/PARITY-SPOT-REMINDERS-2026-07-10.md +144 -0
- package/docs/PARITY-SPOT-TOOL-INVENTORY-2026-07-10.md +61 -0
- package/docs/PARITY-SPOT-USAGE-CONSTANTS-2026-07-10.md +95 -0
- package/docs/PARITY-SPOT-WORKFLOW-2026-07-10.md +93 -0
- package/docs/PASSWORD-RECOVERY-PANEL-VERDICT-2026-07-10.md +62 -0
- package/docs/R8-R9-FINALIZE-COORDINATION-2026-07-09.md +124 -0
- package/docs/REPL-CODE-MODE-EVALUATION-2026-07-10.md +187 -0
- package/docs/REPORT-1249-TARGETED.md +48 -0
- package/docs/RESEARCH-3P-MEMORY-SWAP-2026-07-12.md +273 -0
- package/docs/ROADMAP.md +111 -0
- package/docs/RSI-CLOUD-DEPLOY-2026-07-06.md +289 -0
- package/docs/RSI-PROCESS-AI-COLDSTART-2026-07-11.md +68 -0
- package/docs/S18-THOROUGHNESS-AUDIT-2026-07-09.md +113 -0
- package/docs/SERVICE-INTEGRATION-GUIDE.md +298 -0
- package/docs/SUBAGENT-STREAM-RESILIENCE-PARITY-2026-07-10.md +118 -0
- package/docs/SWEBENCH-PRO-RECON-2026-07-11.md +31 -0
- package/docs/TB-EFFICIENCY-TELEMETRY-2026-07-08.md +114 -0
- package/docs/TB-FAILURE-AUTOPSY-2026-07-05-RERUN.md +67 -0
- package/docs/TB-FAIRNESS-AUDIT-2026-07-08.md +141 -0
- package/docs/TB-FULL-1257-2026-07-08.md +77 -0
- package/docs/TB-LEG-GAP-ATTRIBUTION-1261-1263-2026-07-11.md +154 -0
- package/docs/TB-REGRESSION-DAEMON-KILL-2026-07-08.md +58 -0
- package/docs/TB-RSI-CROSSCHECK-2026-07-06.md +68 -0
- package/docs/TB-RSI-LEDGER.md +30 -0
- package/docs/TB-STABLE-SET-2026-07-08.md +127 -0
- package/docs/TB21-RECON-2026-07-11.md +28 -0
- package/docs/TEST-DESIGN-BATCH-1-2-3.md +97 -0
- package/docs/THIRD-PARTY-INTEGRATION.md +45 -0
- package/docs/TOKEN-ESTIMATE-CALIBRATION-LIVE-2026-07-09.md +102 -0
- package/docs/audit-2026-06-10-/347/254/254/344/272/214/350/275/256-/347/251/272/347/231/275/345/214/272/344/270/216/345/277/230/346/216/245/347/272/277.md +147 -0
- package/docs/audit-2026-06-10-/350/256/241/347/256/227bug/346/211/253/346/217/217.md +163 -0
- package/docs/audit-2026-06-11-/344/277/256/345/244/215/345/244/215/345/256/241/344/270/216/345/233/236/345/275/222/344/270/223/346/211/253.md +95 -0
- package/docs/audit-2026-06-12-design71-P1/346/275/234/344/274/217/351/235/242/350/243/201/345/206/263/344/270/216/345/220/236/351/224/231/345/256/241/350/256/241.md +45 -0
- package/docs/audit-2026-06-12-/345/205/254/345/274/200/346/227/213/351/222/256/346/264/273/346/200/247/344/270/216vendored/346/255/273/350/267/257.md +63 -0
- package/docs/audit-2026-06-15/ADDENDUM-second-pass.md +88 -0
- package/docs/audit-2026-06-15/ARCHITECTURE-AND-ROADMAP.md +187 -0
- package/docs/audit-2026-06-15/DOC-CORRECTIONS.md +105 -0
- package/docs/audit-2026-06-15/INDEX.md +49 -0
- package/docs/audit-2026-06-15/ORCHESTRATION-STATUS.md +98 -0
- package/docs/audit-2026-06-15/PRODUCTION-ISSUES.md +189 -0
- package/docs/audit-2026-06-15/REFERENCES-literature.md +139 -0
- package/docs/audit-2026-06-15/VENDOR-REFACTOR-PLAN.md +96 -0
- package/docs/cc-probe-198/README.md +72 -0
- package/docs/cc-probe-198/STABILITY-AUDIT.md +118 -0
- package/docs/cc-probe-198/live-schema-monitor-worktree-2026-07-09.json +56 -0
- package/docs/cc-probe-198/mount-variants.json +536 -0
- package/docs/cc-probe-198/plan-mode-run.json +1 -0
- package/docs/cc-probe-198/probe-bash-bg.json +224 -0
- package/docs/cc-probe-198/probe-edit-mismatch.json +120 -0
- package/docs/cc-probe-198/probe-read-missing.json +62 -0
- package/docs/cc-probe-198/probe-search-empty.json +127 -0
- package/docs/cc-probe-198/probe-task-family.json +227 -0
- package/docs/cc-probe-198/probes.status +6 -0
- package/docs/cc-probe-198/raw-capture-interactive.json +948 -0
- package/docs/cc-probe-198/raw-capture-print.json +787 -0
- package/docs/cc-probe-198/raw-capture2-interactive.json +948 -0
- package/docs/cc-probe-198/raw-capture2-print.json +787 -0
- package/docs/cc-probe-198/system-prompt.txt +135 -0
- package/docs/cc-probe-198/tools-array.json +962 -0
- package/docs/durability-boundary.md +63 -0
- package/docs/fix-2026-06-10-/350/256/241/347/256/227bug/344/277/256/345/244/215-search/346/211/271.md +75 -0
- package/docs/fix-2026-06-11-/347/254/254/344/272/214/350/275/256-/344/277/256/345/244/215-search/346/211/271.md +62 -0
- package/docs/parity-sweep/REPORT-DYNAMIC.md +97 -0
- package/docs/parity-sweep/REPORT-STATIC-GGB.md +127 -0
- package/docs/parity-sweep/REPORT-STATIC-RWE.md +133 -0
- package/docs/vendor-history.md +385 -0
- package/docs/vendored-upstream-diff-2026-07.md +83 -0
- package/package.json +70 -0
|
@@ -0,0 +1,2828 @@
|
|
|
1
|
+
import type { TSchema } from "typebox";
|
|
2
|
+
import type { AgentTool, ThinkingLevel } from "../internal/harness.js";
|
|
3
|
+
import type { DocumentContent, ImageContent, Model, ResilienceOptions, StreamFn, TextContent } from "../internal/llm.js";
|
|
4
|
+
import type { TaskNotificationPayload } from "./task-notification.js";
|
|
5
|
+
/** A model reference: either a fully-formed Model, or a `"provider/id"` ref resolved via a catalog. */
|
|
6
|
+
export type ModelRef = string | Model;
|
|
7
|
+
/**
|
|
8
|
+
* Logical model roles, so a deployment declares its models once and every subsystem asks for its
|
|
9
|
+
* role instead of repeating a model name. Resolved against `RunnerDeps.roles` / `TaskSpec.roles`
|
|
10
|
+
* with a fallback chain (e.g. `summarize → default`, `synthesize → team → default`).
|
|
11
|
+
* - `default` — the main task model when `TaskSpec.model` is omitted.
|
|
12
|
+
* - `summarize` — between-turn compaction/summarization (aider's "weak model"); a cheap tier.
|
|
13
|
+
* - `subagent` — delegated sub-runs (`createSubagentTool` without an explicit model).
|
|
14
|
+
* - `team` / `synthesize` — team members / the neutral synthesizer.
|
|
15
|
+
* - `advisor` — the strong "teacher" a cheap student escalates to (`runWithTeacher`).
|
|
16
|
+
*/
|
|
17
|
+
export type ModelRole = "default" | "summarize" | "subagent" | "team" | "synthesize" | "advisor" | "verifier";
|
|
18
|
+
/**
|
|
19
|
+
* A role's model: a `ModelRef`, or a config object that pins a `model`, **selects** one by
|
|
20
|
+
* capability/price (`select`, design/11 Layer 2), and/or sets a default `thinking` level.
|
|
21
|
+
*/
|
|
22
|
+
export type RoleSpec = ModelRef | {
|
|
23
|
+
model?: ModelRef;
|
|
24
|
+
select?: import("./select-model.js").ModelCriteria;
|
|
25
|
+
thinking?: ThinkingLevel;
|
|
26
|
+
/**
|
|
27
|
+
* Optional preset system prompt for this role (e.g. {@link CODE_AGENT_PROMPT} for a dev role).
|
|
28
|
+
* Used only when the task does not supply its own `TaskSpec.systemPrompt`. Lets coding roles run
|
|
29
|
+
* a coding prompt while other roles keep the neutral default — without touching the global default.
|
|
30
|
+
*/
|
|
31
|
+
systemPrompt?: string;
|
|
32
|
+
};
|
|
33
|
+
/** Map of role → model. `TaskSpec.roles` overrides `RunnerDeps.roles` per task/scenario. */
|
|
34
|
+
export type ModelRoles = Partial<Record<ModelRole, RoleSpec>>;
|
|
35
|
+
/** The "external brain": a streaming completion function plus a non-streaming one (auto-derived if omitted). */
|
|
36
|
+
export interface Brain {
|
|
37
|
+
/** Streaming completion. Must follow the AssistantMessageEvent stream contract (never throw post-invocation).
|
|
38
|
+
*
|
|
39
|
+
* NOTE: the return type is a union — `Stream | Promise<Stream>`. Third-party direct callers must
|
|
40
|
+
* normalize first (`const s = await brain.stream(...)`) before iterating or reading `.result()`,
|
|
41
|
+
* otherwise TS reports TS2339 on the union. The Runner already handles this internally. */
|
|
42
|
+
stream: StreamFn;
|
|
43
|
+
/**
|
|
44
|
+
* Optional non-streaming completion used by compaction/summarization.
|
|
45
|
+
* If omitted, it is derived from `stream` by consuming the stream to its final result.
|
|
46
|
+
*
|
|
47
|
+
* CONTRACT: a custom implementation must return the AssistantMessage with ALL fields intact —
|
|
48
|
+
* including `errorKind` (the compaction summary path keys its budget-escalation recovery on it)
|
|
49
|
+
* and `errorMessage`. Rebuilding the message with a field whitelist silently disables recovery.
|
|
50
|
+
*/
|
|
51
|
+
complete?: (model: Model, context: {
|
|
52
|
+
systemPrompt?: string;
|
|
53
|
+
messages: unknown[];
|
|
54
|
+
}, options?: unknown) => Promise<unknown>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Side-effect class of a tool. Used by wake/resume reconciliation: when a call was interrupted
|
|
58
|
+
* before its result was recorded, the outcome is unknown, so core must decide whether re-doing it
|
|
59
|
+
* is safe. See {@link reconcileInterruptedSession}.
|
|
60
|
+
* - `read` — no side effects (a query/lookup). Safe to call again.
|
|
61
|
+
* - `idempotent` — has a side effect, but repeating it with the same args is equivalent to doing it
|
|
62
|
+
* once (e.g. `PUT` a known key, set-to-value). Safe to call again.
|
|
63
|
+
* - `write` — a non-idempotent side effect (delete, append, charge, send). **Unsafe to repeat
|
|
64
|
+
* blindly.** This is the conservative default when `effect` is omitted.
|
|
65
|
+
*/
|
|
66
|
+
export type ToolEffect = "read" | "write" | "idempotent";
|
|
67
|
+
/** A native tool the model can call. `parameters` is a typebox schema; `execute` does the work. */
|
|
68
|
+
export interface ToolSpec<TParams extends TSchema = TSchema> {
|
|
69
|
+
/**
|
|
70
|
+
* Model-facing tool name. MUST NOT contain `__` — that separator is reserved for the MCP namespace
|
|
71
|
+
* (`mcp__<server>__<tool>`); a caller tool name with `__` is rejected at prepare-time (`config.tool_name_invalid`)
|
|
72
|
+
* because the durable-resume name shim ({@link canonicalToolName}) would mis-namespace it across an upgrade.
|
|
73
|
+
*/
|
|
74
|
+
name: string;
|
|
75
|
+
/**
|
|
76
|
+
* Backward-compatible model-facing names that should dispatch to this tool. New transcripts and tool rosters
|
|
77
|
+
* should use {@link name}; aliases exist only so old model calls / SDK payloads / resumed sessions don't strand
|
|
78
|
+
* across a canonical rename.
|
|
79
|
+
*/
|
|
80
|
+
aliases?: string[];
|
|
81
|
+
description: string;
|
|
82
|
+
/**
|
|
83
|
+
* Human label for UIs. Defaults to `name`.
|
|
84
|
+
*
|
|
85
|
+
* ⚠️ Currently INERT (design/71 liveness sweep, 2026-06-12): mapped onto the tool object but no
|
|
86
|
+
* runtime path or emitted event reads it — the model and TaskStream consumers only ever see
|
|
87
|
+
* `name`. Kept for API stability; wire it into tool events or drop it before building on it.
|
|
88
|
+
*/
|
|
89
|
+
label?: string;
|
|
90
|
+
/**
|
|
91
|
+
* G1 通告层 (CC `agent_listing_delta` parity): the delegation tool's agent-type roster (name + one-line
|
|
92
|
+
* description), filled by `createSubagentTool` so the Runner's turn-boundary announcer can surface the
|
|
93
|
+
* "Available agent types" reminder without reaching into the tool's closure. Deployment-authored tools
|
|
94
|
+
* normally leave it unset; the announcer only runs when `TaskSpec.attachments.agentListing` opts in.
|
|
95
|
+
*/
|
|
96
|
+
agentListing?: ReadonlyArray<{
|
|
97
|
+
name: string;
|
|
98
|
+
description: string;
|
|
99
|
+
}>;
|
|
100
|
+
/**
|
|
101
|
+
* design/136 §2.1.c — OPTIONAL pre-validation compatibility shim for raw tool-call arguments (mirrors the
|
|
102
|
+
* engine `AgentTool.prepareArguments` seam it is forwarded onto): map a LEGACY argument shape onto the
|
|
103
|
+
* current schema BEFORE schema validation, so a persisted old-shape call (a pre-rename durable checkpoint's
|
|
104
|
+
* pendingAction replayed via {@link canonicalToolName}) doesn't fail the declared-schema check. MUST be
|
|
105
|
+
* idempotent and identity for already-canonical args (the engine path applies it before validation AND the
|
|
106
|
+
* defineTool wrapper applies it again before its own check). Consumer example: the Agent tool maps the
|
|
107
|
+
* retired Fork tool's `{directive}` onto `{prompt, subagent_type:"fork"}`.
|
|
108
|
+
*/
|
|
109
|
+
prepareArguments?: (args: unknown) => unknown;
|
|
110
|
+
/**
|
|
111
|
+
* Side-effect class for wake/resume safety. Defaults to `write` (conservative) when omitted:
|
|
112
|
+
* an interrupted call of unknown effect is treated as possibly-applied and never auto-repeated.
|
|
113
|
+
*/
|
|
114
|
+
effect?: ToolEffect;
|
|
115
|
+
/**
|
|
116
|
+
* design/70: marks a tool whose execution is an EXTERNAL write (egress) — an outward-visible,
|
|
117
|
+
* effectively-irreversible action (open a PR, push a branch, send) as opposed to an internal side
|
|
118
|
+
* effect. **Orthogonal to {@link effect}**: `effect` is the repeat-safety axis (wake/resume
|
|
119
|
+
* reconciliation), `egress` is the blast-radius axis (the design/37 gate); reconcile/wake ignore it.
|
|
120
|
+
* The gate NEVER auto-allows an egress tool: a surviving `allow` (default or policy) is tightened to
|
|
121
|
+
* `ask`, so execution always passes an explicit ask-resolution — synchronous `onAsk`, a durable
|
|
122
|
+
* suspend (design/45), or a deployment-authored approver. Headless stays deny (an external write
|
|
123
|
+
* never happens without explicit confirmation). An egress tool must be repeat-unsafe: declaring
|
|
124
|
+
* `effect: "read"`/`"idempotent"` with `egress: true` is a configuration error (fail-fast at
|
|
125
|
+
* prepare) — omitting `effect` is fine (the default IS `write`).
|
|
126
|
+
*/
|
|
127
|
+
egress?: true;
|
|
128
|
+
/**
|
|
129
|
+
* design/77 §4 (Gate 4 — irreversibility axis): how reversible this tool's effect is. A THIRD axis,
|
|
130
|
+
* orthogonal to {@link effect} (repeat-safety) and {@link egress} (blast-radius). For office/finance
|
|
131
|
+
* primitives (send money, file a return, send an email) where a wrong action cannot be undone, this
|
|
132
|
+
* forces a durable human-approval suspend BEFORE the tool runs:
|
|
133
|
+
* - `"never"` — fully reversible; the gate leaves a surviving `allow` untouched (no ask).
|
|
134
|
+
* - `"maybe"` — reversibility depends on the args; the gate calls {@link reversibilityProbe} (when one is
|
|
135
|
+
* declared) on a surviving `allow` and tightens to `ask` UNLESS the probe reports reversible. A tool
|
|
136
|
+
* that declares a `reversibilityProbe` but omits `irreversibility` defaults to `"maybe"` (so it always
|
|
137
|
+
* enters the activation set and is gated).
|
|
138
|
+
* - `"always"` — irreversible; the gate ALWAYS tightens a surviving `allow` to `ask` (like {@link egress}).
|
|
139
|
+
*
|
|
140
|
+
* The tighten mirrors the egress tighten (it only ever tightens allow→ask; a `deny`/`ask` is untouched),
|
|
141
|
+
* runs immediately AFTER it, and routes through the SAME ask-resolution: synchronous `onAsk`, a durable
|
|
142
|
+
* suspend (a new `{kind:"irreversible_ask"}` checkpoint → `status:"suspended"`), or a deployment approver.
|
|
143
|
+
* Headless with no approver SUSPENDS durably (never a model-facing deny — that would be a reward-hack
|
|
144
|
+
* retry surface), so an irreversible action never runs unattended without explicit confirmation.
|
|
145
|
+
*
|
|
146
|
+
* **Note (deliberate redundancy):** `egress` already means "effectively-irreversible external write"; an
|
|
147
|
+
* `egress:true` + `irreversibility:"always"` tool is DOUBLE-tightened. Harmless (allow→ask is idempotent
|
|
148
|
+
* under the deny>ask fold) — the two axes overlap on purpose, they are NOT strictly disjoint.
|
|
149
|
+
*/
|
|
150
|
+
irreversibility?: "never" | "maybe" | "always";
|
|
151
|
+
/**
|
|
152
|
+
* design/77 §4: optional deployment-injected probe for an `irreversibility:"maybe"` tool. Given the call's
|
|
153
|
+
* (post-hook) args, it reports whether THIS specific call is reversible. The gate calls it ONLY when the
|
|
154
|
+
* surviving decision is `allow` and `irreversibility` resolves to `"maybe"`; it is time-bounded (the
|
|
155
|
+
* approval timeout) and **fail-closed**: a non-`reversible` verdict, a timeout, or a throw all tighten to
|
|
156
|
+
* `ask`. Declaring this probe defaults `irreversibility` to `"maybe"`. It is read from the spec at
|
|
157
|
+
* prepare-time and captured in a closure — NOT a tool argument — so the model cannot monkey-patch it.
|
|
158
|
+
*/
|
|
159
|
+
reversibilityProbe?: (args: unknown) => {
|
|
160
|
+
reversible: boolean;
|
|
161
|
+
} | Promise<{
|
|
162
|
+
reversible: boolean;
|
|
163
|
+
}>;
|
|
164
|
+
/**
|
|
165
|
+
* Batch execution mode (design/64 §1 P1, CC reads-parallel/writes-sequential partition). When omitted,
|
|
166
|
+
* `defineTool` derives it FAIL-CLOSED from `effect` (CC 2.1.206 `TOOL_DEFAULTS.isConcurrencySafe → false`):
|
|
167
|
+
* `read` → `"parallel"`; `write`/`idempotent`/UNDECLARED → `"sequential"` — an unannotated tool never
|
|
168
|
+
* silently rides a parallel batch, and two writes in one batch never race. Set explicitly to override.
|
|
169
|
+
*/
|
|
170
|
+
executionMode?: "sequential" | "parallel";
|
|
171
|
+
/**
|
|
172
|
+
* design/120 P1.5 (CC `isConcurrencySafe(parsedInput)` parity): input-level concurrency
|
|
173
|
+
* refinement for a non-`"parallel"` tool — return `true` to let THIS CALL run in a parallel batch
|
|
174
|
+
* (and, under `streamingToolExecution`, start in-stream). An explicit `executionMode:"parallel"`
|
|
175
|
+
* needs no refinement (always safe); a throw = false (fail-closed). In the batch/stream paths the
|
|
176
|
+
* hook receives schema-VALIDATED (coerced) args — CC 206 `parsed.data` parity; a schema-invalid
|
|
177
|
+
* call is judged unsafe before the hook runs. Still treat defensively (direct callers may pass raw).
|
|
178
|
+
* The one real consumer is Bash's read-only classifier.
|
|
179
|
+
*/
|
|
180
|
+
isConcurrencySafe?: (args: unknown) => boolean;
|
|
181
|
+
/** typebox schema for the tool arguments. */
|
|
182
|
+
parameters: TParams;
|
|
183
|
+
/**
|
|
184
|
+
* Large-result offload (design/30): set `false` to NEVER offload this tool's output (e.g. a file-read
|
|
185
|
+
* tool whose output IS the deliverable — offloading then immediately re-reading would just churn).
|
|
186
|
+
* Default: offload when the result exceeds the resolved threshold.
|
|
187
|
+
*/
|
|
188
|
+
offload?: boolean;
|
|
189
|
+
/** Per-tool offload threshold (chars), overriding the global {@link RunnerDeps.toolResultThresholdChars}. */
|
|
190
|
+
offloadThresholdChars?: number;
|
|
191
|
+
/**
|
|
192
|
+
* Deferred disclosure (design/36): when `true`, this tool is NOT inlined with its full JSON Schema in
|
|
193
|
+
* every request. It appears as a lightweight placeholder (`{name, one-line hint, empty params}`) so
|
|
194
|
+
* the model knows it exists; the model must call the injected `tool_search` to activate it, at which
|
|
195
|
+
* point core materializes its full schema into the next request's `tools[]` (without disturbing the
|
|
196
|
+
* cache prefix). Use for large/MCP tool sets where inlining hundreds of schemas blows up turn-1 tokens
|
|
197
|
+
* and risks prefix-cache breakage. Default: not deferred (full schema inlined). See {@link RunnerDeps.deferMode}.
|
|
198
|
+
*/
|
|
199
|
+
defer?: boolean;
|
|
200
|
+
/**
|
|
201
|
+
* Execute the tool. Return a string (becomes text content) or a structured result.
|
|
202
|
+
* Throw to signal failure (the loop encodes it as an error tool result).
|
|
203
|
+
*/
|
|
204
|
+
execute: (args: unknown, ctx: ToolExecuteContext) => Promise<ToolReturn> | ToolReturn;
|
|
205
|
+
}
|
|
206
|
+
/** What a tool's execute may return. */
|
|
207
|
+
export type ToolReturn = string | {
|
|
208
|
+
content: Array<TextContent | ImageContent | DocumentContent> | string;
|
|
209
|
+
/** Arbitrary structured details for logs/UI (not shown to the model unless put in content).
|
|
210
|
+
* Producer side of the tool-result 双面契约: `content` is the MODEL face (may carry model-directed
|
|
211
|
+
* framing/trailers), `details` is the HOST face (per-tool structured Output). Hosts render from the
|
|
212
|
+
* structured face and never re-parse the model face — see the `tool_end.structured` JSDoc
|
|
213
|
+
* (CC 2.1.207 @765495, CC207-CORE-SWEEP P2-3) for the full contract. */
|
|
214
|
+
details?: unknown;
|
|
215
|
+
/** Hint the agent to stop after this tool batch. */
|
|
216
|
+
terminate?: boolean;
|
|
217
|
+
};
|
|
218
|
+
export interface ToolExecuteContext {
|
|
219
|
+
toolCallId: string;
|
|
220
|
+
signal?: AbortSignal;
|
|
221
|
+
/**
|
|
222
|
+
* The RUNNING task's effective working root (worktree-aware), Runner-filled — read-only context a
|
|
223
|
+
* delegation tool threads into its child's trusted internals so the child's env can inherit the
|
|
224
|
+
* parent's cwd (CC parity: a Task sub-agent works in the main session's directory). Undefined when
|
|
225
|
+
* the tool runs outside a Runner task.
|
|
226
|
+
*/
|
|
227
|
+
parentCwd?: string;
|
|
228
|
+
/**
|
|
229
|
+
* Report usage spent in a nested run this tool spawned (e.g. a sub-agent). The Runner accumulates
|
|
230
|
+
* it into the parent task's `TaskResult.stats.nested`, so delegated cost — the multi-agent "~15×"
|
|
231
|
+
* — is visible at the top level. `createSubagentTool` calls this automatically.
|
|
232
|
+
*/
|
|
233
|
+
reportUsage?: (usage: {
|
|
234
|
+
tokens: number;
|
|
235
|
+
turns: number;
|
|
236
|
+
tasks: number;
|
|
237
|
+
costUsd?: number;
|
|
238
|
+
costMicroUsd?: number;
|
|
239
|
+
}) => void;
|
|
240
|
+
/**
|
|
241
|
+
* The model the PARENT task is currently running on, **snapshotted at the moment this tool is called**
|
|
242
|
+
* (design/38 1B). A delegation tool reads it to let a sub-agent `inherit` the caller's model. If the
|
|
243
|
+
* parent later degrades, an already-started child is unaffected (it kept the snapshot). Undefined when
|
|
244
|
+
* the tool runs outside a Runner task.
|
|
245
|
+
*/
|
|
246
|
+
model?: Model;
|
|
247
|
+
/**
|
|
248
|
+
* The PARENT task's current thinking level, snapshotted at call time — the {@link model} companion.
|
|
249
|
+
* A delegation tool threads it into the child so a sub-agent inherits the caller's thinking depth by
|
|
250
|
+
* default (an explicit agent-definition/script `thinking` wins). Undefined outside a Runner task.
|
|
251
|
+
*/
|
|
252
|
+
thinkingLevel?: ThinkingLevel;
|
|
253
|
+
/**
|
|
254
|
+
* The running task's authenticated end-user {@link TaskSpec.principal} (design/62), **read-only** — the
|
|
255
|
+
* Runner fills it; a tool cannot change it. A delegation tool (`createSubagentTool`) propagates it
|
|
256
|
+
* verbatim to its child task so the end-user identity is inherited down the delegation tree (the worker
|
|
257
|
+
* cannot substitute a different principal — it is not a tool argument). Undefined when the task has no
|
|
258
|
+
* principal or the tool runs outside a Runner task.
|
|
259
|
+
*/
|
|
260
|
+
principal?: string;
|
|
261
|
+
/**
|
|
262
|
+
* design/112 C1/C5 — read-only SNAPSHOT of the parent task's client-supplied USER facts (timeZone/userEmail),
|
|
263
|
+
* inherited verbatim down the delegation tree like `principal`, so a subagent/fork child's
|
|
264
|
+
* `# Environment` block localizes "today" to the SAME user zone (not the container's UTC) and names the same
|
|
265
|
+
* user. Runner-filled (NOT a tool argument). Undefined when the task carries no clientContext.
|
|
266
|
+
*/
|
|
267
|
+
clientContext?: TaskSpec["clientContext"];
|
|
268
|
+
/**
|
|
269
|
+
* 🔴 design/77 §3 / §7 — read-only SNAPSHOT of the parent task's ACTIVE skill-manifest frames (the
|
|
270
|
+
* Gate-3 deny-narrowing scope, see {@link SkillManifest}), filled by the Runner. A delegation tool
|
|
271
|
+
* (`createSubagentTool`) reads it AT SPAWN TIME and propagates it into the child task so the child
|
|
272
|
+
* inherits the parent skill's tool/path restrictions (a child of a manifested skill is at most as
|
|
273
|
+
* capable as the manifest). Returns an opaque, frozen array of frames; an empty array = no manifest is
|
|
274
|
+
* active (the common case). The model/worker can neither read nor set it (it is not a tool argument).
|
|
275
|
+
* Undefined when the tool runs outside a Runner task. The returned frame objects are intentionally
|
|
276
|
+
* opaque to callers other than the Runner internals that re-seed them.
|
|
277
|
+
*/
|
|
278
|
+
activeSkillScope?: () => readonly unknown[];
|
|
279
|
+
/**
|
|
280
|
+
* design/99 (nested-subagent live observability): the host run's stable taskId (`spec.taskId ?? sessionId`),
|
|
281
|
+
* filled by the Runner. A delegation tool (`createSubagentTool`) reads it AT SPAWN TIME and threads it into the
|
|
282
|
+
* child as the child's `parentTaskId`, so a UI can build the live nested-agent tree (child.parentTaskId === this
|
|
283
|
+
* taskId). Undefined when the tool runs outside a Runner task.
|
|
284
|
+
*/
|
|
285
|
+
taskId?: string;
|
|
286
|
+
/** design/129: the host run's SESSION id (Runner-filled, read-only) — a session-scoped background child
|
|
287
|
+
* registers under it so later turns (fresh taskId) still reach the entry. */
|
|
288
|
+
sessionId?: string;
|
|
289
|
+
/** design/129: the host spec's `backgroundScope`, threaded read-only so delegation tools apply the
|
|
290
|
+
* deployment's background-lifetime policy (never a model argument). */
|
|
291
|
+
backgroundScope?: "task" | "session";
|
|
292
|
+
/** design/129-B: the process-level background-child observer ({@link RunnerDeps.onBackgroundChildEvent}),
|
|
293
|
+
* threaded read-only so the Agent tool's background lane reports spawn/tick/terminal for the child's
|
|
294
|
+
* whole lifetime (a per-leg sink goes stale when the leg settles; this one never does). */
|
|
295
|
+
onBackgroundChildEvent?: (event: BackgroundChildEvent) => void;
|
|
296
|
+
/**
|
|
297
|
+
* design/115 P3 — the run-local task-notification sink (the SAME lane runtask wires for workflow/bash
|
|
298
|
+
* completions). Injected by prepare-task's spec.tools wrapper so a caller-mounted delegation tool can
|
|
299
|
+
* fire background-agent completion notifications into the SOURCE task's next turn. TRUSTED, run-scoped.
|
|
300
|
+
*/
|
|
301
|
+
onTaskNotification?: (n: import("./task-notification.js").TaskNotificationPayload, opts?: {
|
|
302
|
+
priority?: import("./task-notification.js").SystemInjectionPriority;
|
|
303
|
+
}) => void;
|
|
304
|
+
/**
|
|
305
|
+
* design/99 (nested-subagent live observability): the host run's OPT-IN display sink — a deployment sets it (via
|
|
306
|
+
* `RunInternals.onForwardEvent`) to receive a SUBAGENT's live `task_progress` ticks that otherwise stay in the
|
|
307
|
+
* child's ISOLATED stream. A delegation tool threads it to the child so nested progress bubbles to one sink. This
|
|
308
|
+
* is a DISPLAY channel ONLY — the child stream is NEVER merged into the parent's MODEL context, and nothing
|
|
309
|
+
* security-relevant consumes a forwarded event. Present ONLY when the deployment opted in; the Runner filters it
|
|
310
|
+
* to `task_progress` (a tool cannot push other event types). ⚠️ Forwarded ticks are UNTRUSTED display hints — any
|
|
311
|
+
* tool holding this ctx could forge one, so a consumer validates `parentTaskId` against its known runs.
|
|
312
|
+
*/
|
|
313
|
+
forwardEvent?: (event: TaskEvent) => void;
|
|
314
|
+
/**
|
|
315
|
+
* Blackboard 2026-07-03 (subagent steer verb): the host run's opt-in SUBAGENT-STEER-HANDLE sink
|
|
316
|
+
* (threaded from `RunInternals.onSubagentSpawn`). When present, `createSubagentTool` runs each sync
|
|
317
|
+
* child via `runTaskStream` and emits a steer handle here; the deployment routes a human steer into
|
|
318
|
+
* the running child. The handle never reaches the model. Absent ⇒ children run non-steerable.
|
|
319
|
+
*/
|
|
320
|
+
onSubagentSpawn?: (handle: import("../agents/subagent.js").SubagentSteerHandle) => void;
|
|
321
|
+
/**
|
|
322
|
+
* design/122 D1 — the parent run's subagent-retain LEDGER, present ONLY when the parent's
|
|
323
|
+
* {@link TaskSpec.retainSubagentSessions} is enabled. TRUSTED run-scoped state the Runner fills (never a
|
|
324
|
+
* tool argument): `createSubagentTool` registers each retained child here (pre-minted sessionId + a
|
|
325
|
+
* FROZEN plain spec snapshot — never the live ctx/spec-builder closures, r1-m5) and the Runner disposes
|
|
326
|
+
* the whole ledger (abort in-flight resumes + unpin + release every retained session) when the parent
|
|
327
|
+
* run ends (D4).
|
|
328
|
+
*/
|
|
329
|
+
subagentRetain?: import("../agents/subagent.js").SubagentRetainLedger;
|
|
330
|
+
/**
|
|
331
|
+
* design/135 §0 — the TRUSTED per-call worktree-isolation lane for the Agent tool (CC
|
|
332
|
+
* `isolation: "worktree"`). The Runner fills it (prepare-task builds it over the run's ExecutionEnv +
|
|
333
|
+
* task root via `createSubagentWorktreeHelper`) for write-capable runs; a tool cannot forge it and the
|
|
334
|
+
* model only REQUESTS isolation via the Agent tool's `isolation` parameter — the capability itself is
|
|
335
|
+
* never a model argument. Absent ⇒ the deployment cannot mint worktrees (read-only run / outside a
|
|
336
|
+
* Runner) and the Agent tool reports isolation as honestly unavailable.
|
|
337
|
+
*/
|
|
338
|
+
worktreeIsolation?: import("../agents/subagent.js").SubagentWorktreeIsolation;
|
|
339
|
+
/**
|
|
340
|
+
* design/135 §0 — TRUE when THIS run is itself a forked child ({@link RunInternals.insideFork}),
|
|
341
|
+
* threaded read-only so the Agent tool's built-in `subagent_type:"fork"` route can refuse nested forks
|
|
342
|
+
* (CC: "fork is not available inside a forked worker") even for a deployment-mounted Agent tool that
|
|
343
|
+
* flowed into the forked child via its tool list. Runner-filled; never a model argument.
|
|
344
|
+
*/
|
|
345
|
+
insideFork?: boolean;
|
|
346
|
+
/**
|
|
347
|
+
* OBS-2 (CC 2.1.206 observer parity) — present iff this run's principal resolved
|
|
348
|
+
* {@link RuntimeCaps.allowObservers}` === true` (EXPLICIT opt-in, default OFF — see the polarity
|
|
349
|
+
* note there). The delegation tool honors {@link AgentDefinition.observer} declarations only under
|
|
350
|
+
* this flag; absent ⇒ declarations resolve to unobserved with NO warn (the gate, not a mistake).
|
|
351
|
+
* Runner-filled at call time (same closure posture as `forkAccess`); never a model argument.
|
|
352
|
+
*/
|
|
353
|
+
observersAllowed?: true;
|
|
354
|
+
/**
|
|
355
|
+
* design/136 §6 盲点① — the Runner-computed fork-GOVERNANCE verdict for THIS run (from
|
|
356
|
+
* `forkGovernanceDenial(spec.enableFork, runtimeCaps.allowFork)`), threaded read-only so the Agent
|
|
357
|
+
* tool's built-in `subagent_type:"fork"` route enforces the SAME per-task/per-principal authorization
|
|
358
|
+
* as the standalone Fork tool's mount gate (pre-1.256, `allowFork:false` only prevented mounting Fork
|
|
359
|
+
* while Agent-fork ran ungoverned). Present ONLY when governance DENIES (`denied:"task"` =
|
|
360
|
+
* `enableFork:false`; `denied:"principal"` = `runtimeCaps.allowFork:false`) — absent means governance
|
|
361
|
+
* does not object (or the tool runs outside a Runner ⇒ capability checks only). Runner-filled; never a
|
|
362
|
+
* model argument.
|
|
363
|
+
*/
|
|
364
|
+
forkAccess?: {
|
|
365
|
+
denied: "task" | "principal";
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* design/80 D-B — the general "a tool yields to a HUMAN review gate" primitive. A tool calls this to request
|
|
369
|
+
* that, at the next SAFE turn boundary, the engine pause with a durable `plan_review` checkpoint
|
|
370
|
+
* (`status:"needs_review"`) so a human approves/edits/rejects before the run continues. The tool still returns
|
|
371
|
+
* its `content` normally first (the plan/diff lives there → reaches the reviewer via the transcript). HONORED
|
|
372
|
+
* only when the deployment can actually pause (a `checkpointStore` is wired); otherwise the request is a silent
|
|
373
|
+
* no-op (read-only/headless degrade). The first-party `present_plan` tool (CC `ExitPlanMode` parity) is a thin
|
|
374
|
+
* caller of this; any tool may use it to gate a high-blast step on human review. Idempotent within a batch (the
|
|
375
|
+
* first request wins; the suspend fires once at the boundary). The Runner fills it; not a tool arg.
|
|
376
|
+
*/
|
|
377
|
+
requestReview?: (opts?: {
|
|
378
|
+
reason?: string;
|
|
379
|
+
}) => void;
|
|
380
|
+
/**
|
|
381
|
+
* design/105 — request a CLEAN stop of THIS run after the current turn (NOT an abort: the loop finishes the
|
|
382
|
+
* turn, then exits gracefully — no orphan-[INTERRUPTED] reconcile). A thin binding to the harness's existing
|
|
383
|
+
* one-way `requestStopAfterTurn` flag (the same the human-suspend saga uses). Typical use: a tool that
|
|
384
|
+
* persisted a delayed self-wake intent (e.g. CronCreate with kind:"delay") ends the run cleanly so the
|
|
385
|
+
* daemon owns the re-wake ("end now, re-wake" — NOT "suspend-continue", see design/105 §3.4). Idempotent
|
|
386
|
+
* one-way flag; a no-op for tools that don't call it. The Runner fills it; not a tool arg. Absent outside a Runner.
|
|
387
|
+
*/
|
|
388
|
+
requestStopAfterTurn?: () => void;
|
|
389
|
+
/**
|
|
390
|
+
* design/108 — enter mid-run READ-ONLY plan mode: the rest of THIS run rejects write-effect tool calls
|
|
391
|
+
* (`effect !== "read"`), while read/research tools and `present_plan` still run. A run-local one-way flag
|
|
392
|
+
* (NOT durable — a later approve-resume re-prepares with it clear, so the approved plan can write). The
|
|
393
|
+
* first-party `enter_plan_mode` tool (CC `EnterPlanMode` parity) is the only caller; the engine enforces the
|
|
394
|
+
* read-only restriction in a dedicated plan-mode tool-call check (separate from the safety gate — plan mode
|
|
395
|
+
* is a FIDELITY mode, not a security boundary; the real safety gates apply independently). Idempotent; a
|
|
396
|
+
* no-op for tools that don't call it. The Runner fills it; not a tool arg. Absent outside a Runner.
|
|
397
|
+
*/
|
|
398
|
+
enterPlanMode?: () => void;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* design/138 S2-C — the hands band's write-time CONTENT hook (single source; `src/tools/fs` re-exports
|
|
402
|
+
* these so its import surface is unchanged — moved here by design/141 件2 because `RunnerDeps.hands`
|
|
403
|
+
* carries the deployment-composable half of the hook). Called before EVERY `env.writeFile` in
|
|
404
|
+
* Write/Edit/NotebookEdit with the resolved containment key and the exact final text; `{ ok:false }`
|
|
405
|
+
* fails the tool with a structured error and NOTHING is written. A THROWING hook fails CLOSED.
|
|
406
|
+
*/
|
|
407
|
+
export interface BeforeWriteRequest {
|
|
408
|
+
tool: "Write" | "Edit" | "NotebookEdit";
|
|
409
|
+
/** The model-supplied path argument (for the error-message coordinate the model knows). */
|
|
410
|
+
path: string;
|
|
411
|
+
/** The resolved canonical containment key — what the hook should judge. */
|
|
412
|
+
key: string;
|
|
413
|
+
/** The FINAL full text about to be written (Edit/NotebookEdit: after application). */
|
|
414
|
+
content: string;
|
|
415
|
+
}
|
|
416
|
+
export type BeforeWriteResult = {
|
|
417
|
+
ok: true;
|
|
418
|
+
} | {
|
|
419
|
+
ok: false;
|
|
420
|
+
code: string;
|
|
421
|
+
reason: string;
|
|
422
|
+
};
|
|
423
|
+
export type BeforeWriteHook = (req: BeforeWriteRequest) => BeforeWriteResult | undefined | Promise<BeforeWriteResult | undefined>;
|
|
424
|
+
/**
|
|
425
|
+
* design/141 件2 — the SAFE deployment-configurable subset of the hands toolkit ({@link RunnerDeps.hands}).
|
|
426
|
+
* Only fields whose injection is purely additive for a deployment are here; Runner-internal orchestration
|
|
427
|
+
* state (taskRegistry/detachHub/execClamp/cwdRef/mount coordination) is deliberately NOT configurable.
|
|
428
|
+
*/
|
|
429
|
+
export interface HandsBandOptions {
|
|
430
|
+
/** Override the `bash_readonly` command allowlist (read-only band). Default: the built-in read-only set. */
|
|
431
|
+
bashReadonlyAllow?: readonly string[];
|
|
432
|
+
/** Co-Authored-By trailer for the bash git protocol; `false` disables it. Default: the built-in trailer. */
|
|
433
|
+
commitCoAuthor?: string | false;
|
|
434
|
+
/** Read-tool image downsampler: inject your own, or `false` to force-disable (deterministic no-sharp).
|
|
435
|
+
* Omitted ⇒ auto-detect sharp. Same contract as the MCP-side {@link import("./mcp.js").ImageDownsampler}. */
|
|
436
|
+
readImageDownsampler?: ((input: Buffer, mimeType: string) => Promise<import("./mcp.js").DownsampledImage | undefined>) | false;
|
|
437
|
+
/** Deployment write gate — COMPOSED with (never replacing) the engine's MemoryEngine write-scan gate:
|
|
438
|
+
* this hook judges first (a rejection short-circuits), the engine gate then still runs in full. */
|
|
439
|
+
beforeWrite?: BeforeWriteHook;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* A declarative, reusable named sub-agent (design/38 1B). Hand a set to {@link createSubagentTool} and the
|
|
443
|
+
* model picks one (by `whenToUse`) to delegate to; the chosen definition's config builds the child task.
|
|
444
|
+
*
|
|
445
|
+
* **Deployment-side config, NOT user input** — `systemPrompt`/`allowTools` shape what the sub-agent can do
|
|
446
|
+
* and see, so they must be set by the deployment, never taken from an end-user message.
|
|
447
|
+
*/
|
|
448
|
+
export interface AgentDefinition {
|
|
449
|
+
/** Stable identifier + the value the delegation tool's `agent` parameter selects. Must be unique. */
|
|
450
|
+
name: string;
|
|
451
|
+
/** Guidance shown to the model for WHEN to pick this agent (listed in the delegation tool's description). */
|
|
452
|
+
whenToUse?: string;
|
|
453
|
+
/**
|
|
454
|
+
* F4 (CC 2.1.198 parity, `whenToUseLean` — 锚 pretty.js:409174 `rbm` + selection `tIl` :453029
|
|
455
|
+
* `(lean && e.whenToUseLean) || e.whenToUse`): a SHORT variant of {@link whenToUse} preferred on
|
|
456
|
+
* lean-prompt surfaces. sema posture: the engine runs the CC lean-prompt arm wholesale (web.ts
|
|
457
|
+
* lean-card precedent), so roster listings/descriptions prefer this text whenever present;
|
|
458
|
+
* {@link whenToUse} remains the fallback. Optional — a single-text agent behaves exactly as before.
|
|
459
|
+
*/
|
|
460
|
+
whenToUseLean?: string;
|
|
461
|
+
/** Tool allowlist over the delegation pool (`["*"]` = all). Replaces (does not merge with) the tool's
|
|
462
|
+
* own `allowTools`/`denyTools` when this agent is selected. F1 (CC parity): unlike the TOOL-level
|
|
463
|
+
* allow/deny (which never filters the nested delegation tool — that stays `maxDepth`-governed), a
|
|
464
|
+
* PER-AGENT allow/deny ALSO governs the nested delegation tool: an agent whose allow/deny excludes
|
|
465
|
+
* the delegation tool's name cannot re-delegate (CC Explore/Plan `disallowedTools` include Agent,
|
|
466
|
+
* pretty.js:409189/486948). */
|
|
467
|
+
allowTools?: string[];
|
|
468
|
+
/** Tool denylist (a deny always wins). See {@link allowTools} for the per-agent delegation-tool note. */
|
|
469
|
+
denyTools?: string[];
|
|
470
|
+
/**
|
|
471
|
+
* F7 (CC 2.1.198 parity, per-agent `skills` — 锚 pretty.js:422126 `e.skills ?? []`, GA/ungated in 198:
|
|
472
|
+
* CC preloads each named skill's prompt content into the child's opening messages, warning on misses).
|
|
473
|
+
* sema shape: full {@link SkillSpec} objects (sema has no ambient skill registry to resolve bare names
|
|
474
|
+
* against) threaded into the chosen child's `TaskSpec.skills` — disclosed in its `<skills>` block +
|
|
475
|
+
* invocable via the `skill` tool. Deployment-trusted, same trust tier as `systemPrompt`.
|
|
476
|
+
*/
|
|
477
|
+
skills?: SkillSpec[];
|
|
478
|
+
/**
|
|
479
|
+
* F7 (CC 2.1.198 parity, per-agent `background` — 锚 pretty.js:453611 `H.background===!0` OR-ed into
|
|
480
|
+
* the background predicate, GA/ungated): `true` = this agent ALWAYS launches on the background lane
|
|
481
|
+
* (an omitted `run_in_background` no longer means sync, and the per-call parameter cannot force sync —
|
|
482
|
+
* CC-same OR semantics). Requires the delegation tool's `background` surface; without one the child
|
|
483
|
+
* runs synchronously (CC-same quiet fallback — CC's env kill-switch arm, :453611 `&& !sJt`).
|
|
484
|
+
*/
|
|
485
|
+
background?: boolean;
|
|
486
|
+
/**
|
|
487
|
+
* F7 (CC 2.1.198 parity, per-agent `isolation` — 锚 pretty.js:453599 `z = a ?? H.isolation`, GA):
|
|
488
|
+
* default isolation for this agent; an explicit per-call `isolation` argument wins. sema supports
|
|
489
|
+
* `"worktree"` (CC's `"remote"` arm is a claude.ai-session concern, not ported).
|
|
490
|
+
*/
|
|
491
|
+
isolation?: "worktree";
|
|
492
|
+
/** Model for this agent. **Omit to INHERIT the caller's current model** (design/38 1B finding 7) — the
|
|
493
|
+
* recommended default; a concrete `ModelRef` pins it instead. */
|
|
494
|
+
model?: ModelRef;
|
|
495
|
+
/** Thinking level for this agent. **Omit to INHERIT the caller's current thinking level** (the model
|
|
496
|
+
* companion above — a mid-run degrade/boost on the parent carries into new children); a concrete
|
|
497
|
+
* level pins it instead. */
|
|
498
|
+
thinking?: ThinkingLevel;
|
|
499
|
+
/** System prompt / persona for this agent. Falls back to the delegation tool's `systemPrompt`. */
|
|
500
|
+
systemPrompt?: string;
|
|
501
|
+
/** Per-agent turn cap. Falls back to the delegation tool's `limits.maxTurns`. */
|
|
502
|
+
maxTurns?: number;
|
|
503
|
+
/** Long-term memory scope for this agent (same shape as {@link TaskSpec.memory}). */
|
|
504
|
+
memory?: TaskSpec["memory"];
|
|
505
|
+
/**
|
|
506
|
+
* Observer agents (CC 2.1.206 parity — 逐字锚 docs/CC206-OBSERVER-ANCHORS-2026-07-11.md, schema
|
|
507
|
+
* 面 C @28385708): "Agent type auto-spawned as a background observer whenever this agent runs.
|
|
508
|
+
* The observer receives read-only activity digests and reports via the ObserverReport tool; it
|
|
509
|
+
* never participates in the task." Resolution is warn-and-unobserved on an unknown type and
|
|
510
|
+
* refuses chaining (an observer's own `observer` declaration is ignored). Gated by
|
|
511
|
+
* {@link RuntimeCaps.allowObservers} — EXPLICIT opt-in, default OFF (the sema seat of CC's
|
|
512
|
+
* default-unset env `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS` + default-true statsig pair).
|
|
513
|
+
*/
|
|
514
|
+
observer?: string;
|
|
515
|
+
/**
|
|
516
|
+
* CC 面 C: "Supplemental postamble appended (after the harness-owned default) to each activity
|
|
517
|
+
* digest sent to the observer. Blank values are ignored."
|
|
518
|
+
*/
|
|
519
|
+
observerMessage?: string;
|
|
520
|
+
}
|
|
521
|
+
/** Definition of an MCP server to connect to for the duration of one task, then discard. */
|
|
522
|
+
export interface McpServerSpec {
|
|
523
|
+
/** Stable name; tool names are namespaced as `<name>__<tool>` to avoid collisions. */
|
|
524
|
+
name: string;
|
|
525
|
+
transport: {
|
|
526
|
+
kind: "stdio";
|
|
527
|
+
command: string;
|
|
528
|
+
args?: string[];
|
|
529
|
+
env?: Record<string, string>;
|
|
530
|
+
} | {
|
|
531
|
+
kind: "http";
|
|
532
|
+
url: string;
|
|
533
|
+
/** Static headers sent on every request (e.g. an auth bearer for the MCP server itself). */
|
|
534
|
+
headers?: Record<string, string>;
|
|
535
|
+
/**
|
|
536
|
+
* Per-task **end-user principal** header (design/62). When set, the Runner injects the running task's
|
|
537
|
+
* authenticated {@link TaskSpec.principal} as this header (e.g. `"X-Agent-Principal"`) on every call to
|
|
538
|
+
* this server's tools, so the MCP server can enforce per-user RBAC. Absent {@link TaskSpec.principal}
|
|
539
|
+
* ⇒ the header is **not** sent (the MCP server must default to deny/public, never admin). Overrides any
|
|
540
|
+
* same-named static `headers` entry. The principal is Runner-held and the model/worker can neither read
|
|
541
|
+
* nor set it (it is not a tool argument) — see {@link TaskSpec.principal}.
|
|
542
|
+
*/
|
|
543
|
+
principalHeader?: string;
|
|
544
|
+
};
|
|
545
|
+
/** Optional allowlist of tool names to expose (others are dropped). */
|
|
546
|
+
allowTools?: string[];
|
|
547
|
+
/**
|
|
548
|
+
* design/99 §E23 — opt in to INBOUND elicitation for THIS server: when `true` AND a {@link RunnerDeps.onElicit}
|
|
549
|
+
* seam is wired, core advertises the `elicitation` capability to this server and registers a handler, so the
|
|
550
|
+
* server may send an `elicitation/create` request to ask the END USER for input mid-tool-call. **Default OFF
|
|
551
|
+
* (fail-closed)**: never advertise unless explicitly wired, so a hostile/over-eager server cannot pull a human
|
|
552
|
+
* into the loop. v1 is LIVE-ONLY — `onElicit` answers synchronously on the open connection (no durable
|
|
553
|
+
* suspend; a durable/cross-replica elicitation needs the deferred E22 longer-lived connection).
|
|
554
|
+
*/
|
|
555
|
+
elicitation?: boolean;
|
|
556
|
+
/**
|
|
557
|
+
* Caller-side per-tool safety-axis overrides, keyed by the server's REMOTE (un-namespaced) tool name. The
|
|
558
|
+
* CALLER is the trust root: unlike a server's self-declared annotations (which may only TIGHTEN), a caller
|
|
559
|
+
* override is AUTHORITATIVE and may LOWER an effect (vouch a tool is `read`/`idempotent`) as well as raise it
|
|
560
|
+
* (`egress` / irreversible). This is the ONLY trusted way to drop an MCP tool below the fail-closed `write`
|
|
561
|
+
* default (design F). Folds over the server hints in prepare-task (caller > server hint > fail-closed write).
|
|
562
|
+
*/
|
|
563
|
+
toolAxes?: Record<string, {
|
|
564
|
+
effect?: ToolEffect;
|
|
565
|
+
egress?: boolean;
|
|
566
|
+
irreversibility?: "always" | "never";
|
|
567
|
+
}>;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* design/99 §E23 — an INBOUND MCP elicitation request (a connected server asking the END USER for input
|
|
571
|
+
* mid-tool-call). Handed to the deployment's {@link RunnerDeps.onElicit} seam. **UNTRUSTED**: `message` /
|
|
572
|
+
* `requestedSchema` / `url` are SERVER-controlled — core never interprets `requestedSchema`; a consumer that
|
|
573
|
+
* shows `message` to a human MUST fence it (`delimitUntrusted`).
|
|
574
|
+
*/
|
|
575
|
+
export interface McpElicitRequest {
|
|
576
|
+
/** The {@link McpServerSpec.name} of the server that issued the request. */
|
|
577
|
+
server: string;
|
|
578
|
+
/** The server's human-facing prompt (UNTRUSTED — fence before display). */
|
|
579
|
+
message: string;
|
|
580
|
+
/** Form mode: the server's requested input schema (a flat object of scalars). OPAQUE to core. */
|
|
581
|
+
requestedSchema?: unknown;
|
|
582
|
+
/**
|
|
583
|
+
* URL mode: a server-controlled URL the user is asked to visit (UNTRUSTED — a phishing/social-engineering
|
|
584
|
+
* surface; a consumer MUST scrutinize/fence it before showing it). **Inactive in v1**: core advertises
|
|
585
|
+
* FORM mode only, so the SDK rejects url-mode requests before this seam — this field is reserved for a
|
|
586
|
+
* future url-mode opt-in and is never populated today.
|
|
587
|
+
*/
|
|
588
|
+
url?: string;
|
|
589
|
+
/** The running task's authenticated end-user (design/62), if any — for routing the prompt to the right human. */
|
|
590
|
+
principal?: string;
|
|
591
|
+
}
|
|
592
|
+
/** design/99 §E23 — the deployment's answer to an {@link McpElicitRequest} (returned to the MCP server). */
|
|
593
|
+
export interface McpElicitResponse {
|
|
594
|
+
action: "accept" | "decline" | "cancel";
|
|
595
|
+
/** Submitted values (accept only); core passes them through opaquely, never validated against the schema. */
|
|
596
|
+
content?: Record<string, string | number | boolean | string[]>;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* design/99 §E23 — the LIVE-ONLY inbound-elicitation seam. A deployment provides it (e.g. the sema shell
|
|
600
|
+
* prompts the user at the terminal) and returns the answer SYNCHRONOUSLY; core replies to the server on the
|
|
601
|
+
* still-open connection. Absent ⇒ no server is advertised the elicitation capability (fail-closed). Not a
|
|
602
|
+
* durable suspend — a crash/replica-change loses an in-flight elicitation (acceptable for an interactive shell).
|
|
603
|
+
*
|
|
604
|
+
* 🔴 THROTTLING IS THE DEPLOYMENT'S JOB: once a server is opted in, it may issue elicitations at any frequency
|
|
605
|
+
* (one per tool call, or many) — core imposes NO rate/count limit (an elicitation is not a tool call and does
|
|
606
|
+
* not ride the policy gate). `onElicit` is the choke point: throttle, aggregate, or `decline`/`cancel` an
|
|
607
|
+
* over-eager or hostile server here (the request's `AbortSignal` is forwarded so a deadline can cancel it).
|
|
608
|
+
*/
|
|
609
|
+
export type OnElicit = (req: McpElicitRequest, signal?: AbortSignal) => Promise<McpElicitResponse>;
|
|
610
|
+
/**
|
|
611
|
+
* A per-skill runtime capability manifest (design/77 §3 Gate-3). When present, loading the skill
|
|
612
|
+
* SCOPES the rest of the invocation to ONLY these tools/paths via runtime deny-narrowing: a tool call
|
|
613
|
+
* not in `allowTools` (intersected across nested skill frames) is DENIED, and a write whose canonical
|
|
614
|
+
* target falls outside `allowPaths` is DENIED — regardless of how permissive the task policy is.
|
|
615
|
+
*
|
|
616
|
+
* 🔴 **Safe-by-construction:** a manifest can only SUBTRACT capability. The narrowing composes via the
|
|
617
|
+
* `deny > ask > allow` fold (`combinePolicies`) where `deny` short-circuits, so a manifest can never
|
|
618
|
+
* *grant* a tool the task policy withheld — an attacker who sets a manifest can only restrict further.
|
|
619
|
+
* Worst case (the model never pops the frame) = no narrowing, never widening — still ⊆ task policy.
|
|
620
|
+
*
|
|
621
|
+
* The manifest is CALLER-provided here (same trust level as the rest of `SkillSpec`); deriving it
|
|
622
|
+
* automatically (the auto-promote pipeline) is a separate, deferred concern (design/77 §5).
|
|
623
|
+
*/
|
|
624
|
+
export interface SkillManifest {
|
|
625
|
+
/** The ONLY tool names the invocation may call while this skill's frame is active. */
|
|
626
|
+
allowTools: string[];
|
|
627
|
+
/**
|
|
628
|
+
* Optional path allowlist for WRITE tools (`write_file`/`edit_file`): a write whose canonicalized
|
|
629
|
+
* target is not inside one of these (path-segment-aware) prefixes is DENIED. Omit = no path narrowing
|
|
630
|
+
* (only `allowTools` applies). Reads are never path-narrowed (this gate restricts capability, not visibility).
|
|
631
|
+
*
|
|
632
|
+
* 🔴 **Fail-closed (MAJOR-2):** `allowPaths` can only confine tools whose write target is a parseable `path`
|
|
633
|
+
* argument (`write_file`/`edit_file`). While an `allowPaths` constraint is active, any OTHER mutating
|
|
634
|
+
* (effect:write/idempotent) allowlisted tool — notably `bash`, whose command can write anywhere — is DENIED
|
|
635
|
+
* outright, because its target cannot be path-confined. So a manifest that lists `bash` together with
|
|
636
|
+
* `allowPaths` does NOT let bash write/egress anywhere: bash is denied while the path constraint is active.
|
|
637
|
+
* Confine writes to specific paths via `write_file`/`edit_file` only.
|
|
638
|
+
*/
|
|
639
|
+
allowPaths?: string[];
|
|
640
|
+
/** Reserved (design/77 §3): whether egress is permitted under this manifest. Carried through; v1 does
|
|
641
|
+
* not act on it beyond the allowTools intersection (egress tools must also be in `allowTools`). */
|
|
642
|
+
egress?: boolean;
|
|
643
|
+
/** Stable lineage id of the artifact this manifest came from — used in deny reasons + as the scope key. */
|
|
644
|
+
lineageId: string;
|
|
645
|
+
}
|
|
646
|
+
/** A skill made available to this task (passed as an object; not loaded from disk). */
|
|
647
|
+
export interface SkillSpec {
|
|
648
|
+
name: string;
|
|
649
|
+
description: string;
|
|
650
|
+
content: string;
|
|
651
|
+
/** Optional Gate-3 runtime capability manifest (design/77 §3) — see {@link SkillManifest}. */
|
|
652
|
+
manifest?: SkillManifest;
|
|
653
|
+
}
|
|
654
|
+
/** An image attached to the task's user message: either inline base64 or a URL to fetch. */
|
|
655
|
+
export type ImageInput = {
|
|
656
|
+
/** Base64-encoded image bytes (no data: prefix). */
|
|
657
|
+
data: string;
|
|
658
|
+
/** MIME type, e.g. "image/png" / "image/jpeg". */
|
|
659
|
+
mimeType: string;
|
|
660
|
+
} | {
|
|
661
|
+
/** URL the runner will fetch and inline as base64 before sending to the model. */
|
|
662
|
+
url: string;
|
|
663
|
+
};
|
|
664
|
+
/** A single self-contained task with its full configuration. */
|
|
665
|
+
export interface TaskSpec {
|
|
666
|
+
taskId?: string;
|
|
667
|
+
/** The instruction / latest user message for this turn. */
|
|
668
|
+
objective: string;
|
|
669
|
+
/**
|
|
670
|
+
* Authenticated **end-user principal** this task runs on behalf of (design/62) — an opaque identity string
|
|
671
|
+
* (user id, email, tenant-scoped subject) the **trusted caller** sets at task creation. The Runner holds it
|
|
672
|
+
* for the whole run and injects it into MCP requests for any server with a `principalHeader`
|
|
673
|
+
* ({@link McpServerSpec}), enabling per-user RBAC in the MCP server. Delegated child tasks (sub-agent / team /
|
|
674
|
+
* fan-out) inherit it.
|
|
675
|
+
*
|
|
676
|
+
* 🔴 **Trust contract (design/53 — authority stays in the control plane):** this is a control-plane value,
|
|
677
|
+
* **NOT model/worker input.** Set it only from the authenticated task-submission context; it is not exposed
|
|
678
|
+
* as a tool argument and the model cannot read or change it (a worker filling its own principal = a privilege
|
|
679
|
+
* bypass). Treat it as write-once for the run. The MCP server MUST trust this header only on the Runner's
|
|
680
|
+
* authenticated/TLS channel and default to deny/public when it is absent — never default-admin.
|
|
681
|
+
*
|
|
682
|
+
* 🔴🔴 **This is the GOVERNANCE key.** Per-principal entitlements are resolved off this value:
|
|
683
|
+
* {@link RunnerDeps.runtimeCapsResolver}`(spec.principal)` decides `allowWorkflows` (and thus whether
|
|
684
|
+
* self-orchestration / `RunWorkflow` is permitted). So a caller MUST set `spec.principal` to a
|
|
685
|
+
* **cryptographically VERIFIED** identity — **never a raw, spoofable request header**. A deployment that holds
|
|
686
|
+
* both an unverified header value AND a verified one (e.g. a "direct-door" path) MUST pass the VERIFIED one
|
|
687
|
+
* here: keying a gate on a spoofable principal is a multi-tenant governance BYPASS (a forged header would
|
|
688
|
+
* inherit another tenant's entitlements). Core cannot verify identity itself (no crypto context) — it trusts
|
|
689
|
+
* this value by contract; getting it wrong is a privilege-escalation hole, not a core bug.
|
|
690
|
+
*/
|
|
691
|
+
principal?: string;
|
|
692
|
+
/** Optional images attached to this turn's user message (model must support vision). */
|
|
693
|
+
images?: ImageInput[];
|
|
694
|
+
/** Reuse an existing in-memory session for chat continuity; omit to start fresh. */
|
|
695
|
+
sessionId?: string;
|
|
696
|
+
/**
|
|
697
|
+
* design/114 Phase3 — with `sessionId` set, REQUIRE that session to already exist: if it is gone (e.g. a
|
|
698
|
+
* non-durable store lost it across a restart, or a typo'd id), the run FAILS LOUD (`resume.session_not_found`)
|
|
699
|
+
* instead of silently creating a fresh empty session and running with NO warm context. Use this for a
|
|
700
|
+
* reuse-style warm-resume (`runTask({sessionId, requireExistingSession: true})`) so "looks warm, actually
|
|
701
|
+
* fresh" can never happen. (The `fork`-first path via `warmResume` is already fail-loud without this flag.)
|
|
702
|
+
* Ignored when `sessionId` is absent. Default `false` = today's create-on-miss behavior.
|
|
703
|
+
*/
|
|
704
|
+
requireExistingSession?: boolean;
|
|
705
|
+
/**
|
|
706
|
+
* design/112 C1/C5 — CLIENT-supplied USER facts (distinct from execution-env/container facts). In TOB the
|
|
707
|
+
* worker container runs UTC and has no idea who the user is or where they are; the client/REPL/gateway knows.
|
|
708
|
+
* It threads these so the `# Environment` block localizes "today" to the user's zone (else it annotates UTC)
|
|
709
|
+
* and names who the agent acts for. All optional; absent ⇒ current behavior (UTC date, no user line). This is
|
|
710
|
+
* the USER half of the env block — the WORKSPACE half (cwd/git/platform/shell) is probed THROUGH the
|
|
711
|
+
* ExecutionEnv (the container), never from here.
|
|
712
|
+
*/
|
|
713
|
+
clientContext?: {
|
|
714
|
+
/** IANA time zone of the user (e.g. `Asia/Tokyo`) — localizes the env block's date. Invalid zones fall back
|
|
715
|
+
* to UTC (date AND annotation) rather than mislabeling — see `isValidTimeZone`. */
|
|
716
|
+
timeZone?: string;
|
|
717
|
+
/** The user's identity (e.g. email) — surfaced in the env block so the agent knows who it acts for. */
|
|
718
|
+
userEmail?: string;
|
|
719
|
+
};
|
|
720
|
+
/**
|
|
721
|
+
* design/99 §E18 (resume-at) — BRANCH the session at this prior entry BEFORE the turn: replay root→here,
|
|
722
|
+
* then run the new `objective` as the next turn (the shell's "rewind to this message, ask differently").
|
|
723
|
+
* Requires `sessionId`. **The id is a core `SessionTreeEntry.id`** — a persisted session-entry id — **NOT a
|
|
724
|
+
* live {@link TaskEventIdentity.eventId}** (eventIds are never persisted; a deployment that holds eventIds
|
|
725
|
+
* owns the eventId→entryId map). Must reference a `message`/`custom_message` entry, and NOT an assistant
|
|
726
|
+
* message that ends mid-tool-call (a SETTLED turn boundary — else the replay would orphan-close a done call).
|
|
727
|
+
* Non-destructive: recorded as a branch `leaf` entry, so prior leaves stay in the tree (re-resume any time).
|
|
728
|
+
* Mutually exclusive with a durable `runner.resume(...)` (the Runner rejects both at once).
|
|
729
|
+
*/
|
|
730
|
+
resumeAt?: string;
|
|
731
|
+
/**
|
|
732
|
+
* Which model to run on. If omitted, resolved from the `modelRole` (default `"default"`) against
|
|
733
|
+
* `roles` / `RunnerDeps.roles`. Either `model` or a resolvable role must be available.
|
|
734
|
+
*/
|
|
735
|
+
model?: ModelRef;
|
|
736
|
+
/** Which role to resolve when `model` is omitted. Default `"default"`. */
|
|
737
|
+
modelRole?: ModelRole;
|
|
738
|
+
/** Per-task/scenario role→model overrides (merged over `RunnerDeps.roles`, task wins). */
|
|
739
|
+
roles?: ModelRoles;
|
|
740
|
+
/** Optional cheaper model for compaction/summarization. Falls back to the `summarize` role if set. */
|
|
741
|
+
compactionModel?: ModelRef;
|
|
742
|
+
/** Thinking level. If omitted, a default from the resolved role's `RoleSpec.thinking` applies. */
|
|
743
|
+
thinking?: ThinkingLevel;
|
|
744
|
+
/** Preset system prompt for this task. */
|
|
745
|
+
systemPrompt?: string;
|
|
746
|
+
/**
|
|
747
|
+
* APPEND a caller block to the assembled system prompt, keeping the engine's base + harness/safety blocks
|
|
748
|
+
* (unlike `systemPrompt`, which REPLACES the base, and `promptProvider`, which rewrites the whole assembly).
|
|
749
|
+
* The lightweight user/scenario-extension seam (≈ CC `--append-system-prompt`): add task-specific rules,
|
|
750
|
+
* domain context, or a persona tweak without losing the neutral base, cyber/url safety, harness context, or
|
|
751
|
+
* memory discipline. CALLER-TRUSTED (same trust level as `systemPrompt`/`skills` — NOT user input). Composed
|
|
752
|
+
* as a STABLE block (prepare-time) at the END of the stable prefix, before the volatile `<user_memory>` tail,
|
|
753
|
+
* so it never breaks prefix-cache friendliness. Composes WITH `systemPrompt` (appended after it).
|
|
754
|
+
*/
|
|
755
|
+
appendSystemPrompt?: string;
|
|
756
|
+
/**
|
|
757
|
+
* Per-task ROLE-LAYER prompt provider (overrides `RunnerDeps.promptProvider`). Lets one Runner serve
|
|
758
|
+
* different scenarios with different role prompts. 提示词主权批: `stableSystem` supplies the role base
|
|
759
|
+
* only — core appends the constitution (harness/safety/mode/memory blocks) structurally, so a provider
|
|
760
|
+
* cannot drop it by accident; `replaceAll: true` is the explicit full-replacement escape hatch.
|
|
761
|
+
* TRUST BOUNDARY: a provider is function-valued and therefore CODE — it can only be set by in-process
|
|
762
|
+
* deployment code, never by a wire-level (JSON) task submission; untrusted self-orchestration specs
|
|
763
|
+
* additionally have this field stripped by workflow governance. The `prompt.assembled` trace records
|
|
764
|
+
* which mode ran, so a `replaceAll` is always observable.
|
|
765
|
+
*/
|
|
766
|
+
promptProvider?: import("../prompts/default.js").PromptProvider;
|
|
767
|
+
/**
|
|
768
|
+
* Enable long-term memory for this task. **design/138 S4 (BREAKING): requires `RunnerDeps.memoryBackend`**
|
|
769
|
+
* (the injection-first memory engine — materialize → file ops → harvest). With a backend configured the
|
|
770
|
+
* task gets the CC-verbatim `# Memory` instruction + fenced derived index and works memory through its
|
|
771
|
+
* ordinary file tools. WITHOUT a backend this field is INERT: the legacy `RunnerDeps.memoryStore` fallback
|
|
772
|
+
* (remember/recall tools + legacy `<user_memory>` injection) was retired — the task runs memory-less and
|
|
773
|
+
* one deprecation warning is emitted via `onError` (phase `"config"`).
|
|
774
|
+
*
|
|
775
|
+
* **design/84 Seam A** — single opaque scope → an **ordered, opaque scope list + a single writeScope**.
|
|
776
|
+
* The engine only does read-side **layered injection** (one `<user_memory>` block, a `<scope …>` subsection
|
|
777
|
+
* per scope, ordered by priority — the LAST scope is highest-priority and lands at the prompt TAIL) and
|
|
778
|
+
* write-side **single-point routing** (remember/consolidation only ever write `writeScope`; the model never
|
|
779
|
+
* picks a layer). Scope strings stay OPAQUE — the client/profile derives them (TOC: managed/user/project/
|
|
780
|
+
* agent/local; TOB: tenant hierarchy). All three fields are normalized to one canonical shape
|
|
781
|
+
* ({@link import("./memory.js").normalizeMemorySpec}) — `scope` → `[scope]`, `writeScope` defaults to the
|
|
782
|
+
* LAST scope — so the consumer side reads one array with zero narrowing.
|
|
783
|
+
*
|
|
784
|
+
* Cache discipline (§5, implemented in prepare-task): the scopes are injected in list order, so the
|
|
785
|
+
* caller places STABLE layers (managed/user/org — rarely change) FIRST (cacheable prefix) and VOLATILE
|
|
786
|
+
* layers (project/agent/local) LAST (only the tail re-computes). The stable prefix is byte-stable.
|
|
787
|
+
*
|
|
788
|
+
* Backward compatible: a plain `{ scope: "user:42" }` is unchanged (normalizes to `scopes:["user:42"]`,
|
|
789
|
+
* `writeScope:"user:42"`).
|
|
790
|
+
*
|
|
791
|
+
* The accepted shape is {@link import("./memory.js").MemorySpecInput} (the SAME type
|
|
792
|
+
* {@link import("./memory.js").normalizeMemorySpec} consumes) — DESIGN-2 (council): typed by import rather
|
|
793
|
+
* than re-declared inline so the input contract and its normalizer can never silently diverge. Per-field
|
|
794
|
+
* semantics: `scope` = single opaque LEGACY scope (`scopes` wins when both present); `scopes` = ordered
|
|
795
|
+
* opaque layering (STABLE first / VOLATILE last; last = highest priority); `writeScope` = the single layer
|
|
796
|
+
* all writes land in (default = last scope; explicit `null` = read-only — no `remember` tool, consolidation
|
|
797
|
+
* off); `enabled` = master switch (default true).
|
|
798
|
+
*/
|
|
799
|
+
memory?: import("./memory.js").MemorySpecInput;
|
|
800
|
+
/**
|
|
801
|
+
* @deprecated design/138 S4 — legacy memory consolidation (design/41) rode the retired memoryStore
|
|
802
|
+
* path and no longer runs; this field is ignored. (The engine plane's consolidation re-mount is a
|
|
803
|
+
* separate design — see design/138 §7.) Type kept one major; removal is the next major.
|
|
804
|
+
*/
|
|
805
|
+
memoryConsolidation?: MemoryConsolidationConfig;
|
|
806
|
+
/**
|
|
807
|
+
* design/100 §E12 — after the task COMPLETES, run ONE extra opt-in LLM pass to propose "next prompts" the
|
|
808
|
+
* user might send (the shell's follow-up suggestions). OFF/omitted = zero extra LLM calls, behavior unchanged.
|
|
809
|
+
* Fire-and-forget (never blocks the result); the suggestions are surfaced via {@link TaskStream.suggestions}
|
|
810
|
+
* and the (budget-excluded) cost via {@link TaskStats.suggestions}. `count` default 3, `role` default
|
|
811
|
+
* `"summarize"` (a cheap tier → falls back to the task model). The output is UNTRUSTED model text for the
|
|
812
|
+
* shell UI ONLY — never re-feed it to a model.
|
|
813
|
+
*/
|
|
814
|
+
suggestNextPrompts?: boolean | {
|
|
815
|
+
count?: number;
|
|
816
|
+
role?: ModelRole;
|
|
817
|
+
};
|
|
818
|
+
/**
|
|
819
|
+
* design/101 §E19 — opt-in working-tree **rewind**: when this task uses {@link resumeAt} to branch at a prior
|
|
820
|
+
* message AND a snapshot was captured for that message, RESTORE the files to how they were at that message
|
|
821
|
+
* (pairs with E18: branch the session + restore the tree). Also makes every COMPLETED turn capture a
|
|
822
|
+
* snapshot keyed by its leaf `SessionTreeEntry.id`. Requires `RunnerDeps.fileSnapshotStore`. **v1 is
|
|
823
|
+
* LOCAL-only** — a remote ({@link RunnerDeps.executionEnvFactory}) env defers rewind to its own VM-snapshot
|
|
824
|
+
* backend behind the same seam. OFF/omitted = zero snapshot/restore work.
|
|
825
|
+
*/
|
|
826
|
+
rewindFiles?: boolean;
|
|
827
|
+
/**
|
|
828
|
+
* design/101 §E19 + R8 (CC Rewind `code`-only mode) — restore the working tree to the snapshot captured at
|
|
829
|
+
* this prior message entryId WITHOUT forking the conversation (no {@link resumeAt} leaf-branch). This is CC's
|
|
830
|
+
* "Restore code" mode (vs "Restore code and conversation" = {@link resumeAt}+{@link rewindFiles}, and "Restore
|
|
831
|
+
* conversation" = {@link resumeAt} alone). Honored ONLY when {@link resumeAt} is ABSENT (with `resumeAt` set,
|
|
832
|
+
* that branch's own `rewindFiles` governs — they are different operations); a no-snapshot target is an
|
|
833
|
+
* expected no-op (same as `rewindFiles`). Requires `RunnerDeps.fileSnapshotStore`. The session leaf is
|
|
834
|
+
* untouched — the next turn continues the CURRENT conversation, only the files moved.
|
|
835
|
+
*/
|
|
836
|
+
rewindFilesTo?: string;
|
|
837
|
+
/** Native tools available to this task. */
|
|
838
|
+
tools?: ToolSpec[];
|
|
839
|
+
/** Gate tool calls before they run (allow/deny/approval). Overrides `RunnerDeps.toolPolicy`. */
|
|
840
|
+
toolPolicy?: import("./tool-policy.js").ToolPolicy;
|
|
841
|
+
/** How `ask` decisions resolve for this task (headless auto-deny by default). Overrides `RunnerDeps.onAsk`. */
|
|
842
|
+
onAsk?: import("./tool-policy.js").OnAsk;
|
|
843
|
+
/** Content-ask seam (design/64 §5): routes an AskUserQuestion tool call to a real human/UI. When set, the
|
|
844
|
+
* AskUserQuestion tool is mounted. Overrides `RunnerDeps.onQuestion`. Distinct from `onAsk` (permission). */
|
|
845
|
+
onQuestion?: import("./ask-question.js").OnQuestion;
|
|
846
|
+
/** LSP code-intelligence seam (design/64 §13.1): when set, the `lsp` tool is mounted and routed to this
|
|
847
|
+
* manager. Overrides `RunnerDeps.lspManager`. Unset ⇒ no `lsp` tool (the model uses grep/read_file). */
|
|
848
|
+
lspManager?: import("./lsp.js").LspServerManager;
|
|
849
|
+
/**
|
|
850
|
+
* design/121 (CC 198 parity): after the agent edits a file, NEW language-server diagnostics are
|
|
851
|
+
* injected into the model (`<new-diagnostics>` context message, 10/file · 30 total · 4000-char cap)
|
|
852
|
+
* and emitted as a structured `diagnostics` event for the shell. **Default ON** whenever the
|
|
853
|
+
* preconditions hold — an LSP manager with a diagnostics registry is wired AND the roster has
|
|
854
|
+
* write-capable fs tools (CC's same gate); zero cost/behavior change otherwise. `false` opts out.
|
|
855
|
+
*/
|
|
856
|
+
lspDiagnostics?: boolean;
|
|
857
|
+
/** In-process hooks (PreToolUse/PostToolUse/UserPromptSubmit) for this task. Overrides `RunnerDeps.hooks`. */
|
|
858
|
+
hooks?: import("./hooks.js").Hooks;
|
|
859
|
+
/**
|
|
860
|
+
* design/45 **durable suspend-on-approval** (F4). When set AND a `CheckpointStore` is wired
|
|
861
|
+
* (`checkpointStore` here or on `RunnerDeps`), a tool-policy `ask` is **persisted as a checkpoint** and
|
|
862
|
+
* the task ends `status:"suspended"` + `checkpointToken` instead of resolving synchronously through
|
|
863
|
+
* `onAsk` — resume later with `runner.resume(token, outcome)`. This is the cross-process / long /
|
|
864
|
+
* headless version of the `onAsk` gate. **opt-in, default-off**: unset → the 1.63 synchronous `onAsk`
|
|
865
|
+
* path (unchanged). Only safe at the top-level `runTask` (orchestrators fail-fast, §11 Q6).
|
|
866
|
+
*/
|
|
867
|
+
durableApproval?: {
|
|
868
|
+
/** Multi-tenant isolation key, forced into the checkpoint + `resolve`/`reap` WHERE. Required. */
|
|
869
|
+
scope: string;
|
|
870
|
+
/** Optional awaiting-human TTL (ms). Past it a reaper CAS-expires the checkpoint (≈ deny). */
|
|
871
|
+
ttlMs?: number;
|
|
872
|
+
};
|
|
873
|
+
/**
|
|
874
|
+
* design/74: opt into resource-slice suspend. When a resource limit (maxTurns / budget / walltime) is hit
|
|
875
|
+
* AND the task is eligible (a `checkpointStore` + a remote, suspendable `executionEnvFactory` env), suspend
|
|
876
|
+
* as a resumable `resource_limit` checkpoint instead of failing (clay's "失败≠没做完" third state) — resume
|
|
877
|
+
* continues the run with the next slice's allowance. `scope` is the multi-tenant isolation key (like
|
|
878
|
+
* `durableApproval.scope`). Absent ⇒ a limit hit still FAILS (backward compatible). Independent of
|
|
879
|
+
* `durableApproval` (a run can have one, both, or neither).
|
|
880
|
+
*/
|
|
881
|
+
resourceSuspend?: {
|
|
882
|
+
/** Multi-tenant isolation key, forced into the checkpoint + `resolve`/`reap` WHERE. Required. */
|
|
883
|
+
scope: string;
|
|
884
|
+
/**
|
|
885
|
+
* design/74 Slice 4: the task's TOTAL $ budget (USD) across the whole resume→re-suspend chain — the
|
|
886
|
+
* human's allocation, distinct from `maxCostUsd` (the per-SLICE window). Each slice may spend
|
|
887
|
+
* `min(maxCostUsd, total − alreadySpent)`; the ledger (carried on the checkpoint) accumulates spend so a
|
|
888
|
+
* resume can't refresh the budget. `undefined` ⇒ no $ ceiling on the whole task (each slice is bounded
|
|
889
|
+
* only by its own `maxCostUsd` / walltime). Set ONLY on the FIRST slice; later slices read the frozen
|
|
890
|
+
* total from the ledger. (Walltime has a sibling `totalWalltimeSec` on the ledger; not yet enforced.)
|
|
891
|
+
*/
|
|
892
|
+
totalBudgetUsd?: number;
|
|
893
|
+
/**
|
|
894
|
+
* design/74 (search [136] HIGH-1): max resource SLICES (resume legs) before the run fails with
|
|
895
|
+
* `"suspend.loop"`. The resource-slice analogue of `maxSuspends`, but counted on the ledger's
|
|
896
|
+
* `sliceCount` and INDEPENDENT of the restart-loop `maxSuspends`: a legitimate long resource run must
|
|
897
|
+
* not be capped by the (low) restart-loop safety, and restart-loop suspends must not consume the slice
|
|
898
|
+
* allowance (the bug: both shared one `suspendCount` + `maxSuspends`). The cross-slice $ budget
|
|
899
|
+
* (`totalBudgetUsd`) is the PRIMARY bound; this is a backstop against a $0-progress slice loop. Default
|
|
900
|
+
* `DEFAULT_MAX_SLICES` (100, the design/74 spec's worker-suspend ceiling). The leader sizes it to budget/slice.
|
|
901
|
+
*/
|
|
902
|
+
maxSlices?: number;
|
|
903
|
+
/**
|
|
904
|
+
* design/74 (search [136] HIGH-2): retention TTL (ms) stamped onto the resource checkpoint's `deadline`
|
|
905
|
+
* so the durable reaper can GC an orphaned (never-resumed) resource suspend. WITHOUT it the checkpoint
|
|
906
|
+
* has no `deadline`, both reapers filter on `deadline`, and the `pending` row (+ in-memory pin) leaks
|
|
907
|
+
* forever. Default `DEFAULT_RESOURCE_TTL_MS` (30 days, the spec `RESOURCE_SUSPEND_TTL_SEC`). A legitimate
|
|
908
|
+
* resume happens long before this; the deadline only reaps abandonment.
|
|
909
|
+
*/
|
|
910
|
+
ttlMs?: number;
|
|
911
|
+
};
|
|
912
|
+
/**
|
|
913
|
+
* design/80 Seam #2 (external preempt/yield): the SCHEDULER raises this `AbortSignal` to PREEMPT this task —
|
|
914
|
+
* a graceful, RESUMABLE durable yield (free resources for a higher-priority task), NOT an abort (abort kills
|
|
915
|
+
* the run and loses its state). When raised, the task durably suspends at the next CLEAN turn boundary as a
|
|
916
|
+
* `resource_limit` checkpoint with reason `"preempt"` (the SAME mechanism as a budget/turns/walltime resource
|
|
917
|
+
* suspend — only the trigger differs), and is resumed later via `runner.resume(token, {gate:"resource_limit",
|
|
918
|
+
* decision:"continue"}, …)` exactly like any resource-limit resume (continue the work, no decision).
|
|
919
|
+
*
|
|
920
|
+
* **Eligibility (v1 reuses the resource-suspend opt-in):** preempt only fires when the task is eligible for
|
|
921
|
+
* durable suspend — i.e. it opted into {@link resourceSuspend} AND a durable `checkpointStore` is wired AND
|
|
922
|
+
* tool-results are durable AND the per-task env is a remote (suspendable) `RemoteExecutionEnv`. This is
|
|
923
|
+
* correct: a non-durable task cannot be preempted-AND-resumed anyway. If `preemptSignal` is raised on a task
|
|
924
|
+
* that is NOT resource-suspend-eligible, preempt is a SILENT NO-OP (the run continues normally to its natural
|
|
925
|
+
* end) — decoupling preempt's own opt-in from `resourceSuspend` is a future enhancement, not built here.
|
|
926
|
+
*
|
|
927
|
+
* **Re-supply on resume:** like `resourceSuspend`/`durableApproval`, this is part of the resume task config —
|
|
928
|
+
* a long task that is resumed may need re-preemption, so supply a FRESH `preemptSignal` (a new
|
|
929
|
+
* `AbortController.signal`) in the resume `taskConfig` to make the resumed leg preempt-able again.
|
|
930
|
+
*/
|
|
931
|
+
preemptSignal?: AbortSignal;
|
|
932
|
+
/**
|
|
933
|
+
* design/131 (service [404] 拍) — per-task resilience overrides, INTENT-ONLY (no decorator
|
|
934
|
+
* topology on the spec; the deployment's brain stack stays the single owner). For bench/eval or
|
|
935
|
+
* critical tasks that need the provider's TRUE failure shape instead of a silent fallback:
|
|
936
|
+
* - `allowDegrade:false` — reactive model degrade is off for this task (failure passes through).
|
|
937
|
+
* - `allowFailover:false` — cross-gateway failover is off (only the primary brain is tried).
|
|
938
|
+
* - `bypassBreaker:true` — an open circuit breaker's fast-fail is waived for THIS task; outcomes
|
|
939
|
+
* are still recorded (shared observation undiminished). Operator-facing — deployments SHOULD
|
|
940
|
+
* NOT expose this to wire users directly (it defeats provider protection).
|
|
941
|
+
* All absent ⇒ exactly today's behavior. Threaded per-call as `StreamOptions.resilience`; the
|
|
942
|
+
* first-party degrading/failover/breaker decorators honor it, custom brains may ignore it.
|
|
943
|
+
*/
|
|
944
|
+
resilience?: ResilienceOptions;
|
|
945
|
+
/**
|
|
946
|
+
* design/132 — final-verification gate (OPT-IN: `true` enables). When a task is about to end
|
|
947
|
+
* NATURALLY (inside budget) and this run made at least one non-`read` tool call, the engine
|
|
948
|
+
* injects a reminder to re-verify the final deliverable through its REAL entry point
|
|
949
|
+
* (execute it directly; don't trust earlier self-tests or shell redirections) before finishing.
|
|
950
|
+
* Oracle-grounding upgrade (docs/DESIGN-ORACLE-GROUNDING-GATE-2026-07-10.md §3.A): if the run's
|
|
951
|
+
* tool-call record carried a deterministic verifiable-structure signal (raw-byte read /
|
|
952
|
+
* structural parse / digest-reconciliation word-faces in shell commands — never a semantic scan
|
|
953
|
+
* of closing text) and the model ends AGAIN without headroom concerns, ONE grounding re-entry
|
|
954
|
+
* reminder is injected; total injections are hard-capped at 2, then the run always ends. A
|
|
955
|
+
* submitted structured output and the maxTurns-1 boundary always pass through un-gated.
|
|
956
|
+
* Evidence: TB full-run autopsy — the biggest shell-gap bucket (7-8 tasks) finished convinced by
|
|
957
|
+
* their own fake self-check; prompt discipline alone (1.242) had a low landing rate. Opt-in
|
|
958
|
+
* because the evidence is from AUTONOMOUS legs — turn it on for autonomous/benchmark scenarios
|
|
959
|
+
* (sema-tb defaults it ON); interactive deployments choose per scenario. Read-only / Q&A runs
|
|
960
|
+
* never trigger it. Telemetry: `stats.mechanisms.finalVerifyInjected`.
|
|
961
|
+
*/
|
|
962
|
+
finalVerification?: boolean;
|
|
963
|
+
/**
|
|
964
|
+
* design/72 §2.2 (B): max times this task may durably suspend before the run fails with
|
|
965
|
+
* `"suspend.loop"` instead of minting another checkpoint. Caps a resume/restart loop (a model that
|
|
966
|
+
* re-issues the gated/egress call every resume, re-suspending forever). Counted across resume chains.
|
|
967
|
+
* Default 5 (loose — a real human-approval flow re-suspends rarely, so 5 separates a normal resume from a
|
|
968
|
+
* pathological loop; a deployment that genuinely needs more sets this). Overrides `RunnerDeps.maxSuspends`.
|
|
969
|
+
*/
|
|
970
|
+
maxSuspends?: number;
|
|
971
|
+
/** Per-task {@link import("./checkpoint-store.js").CheckpointStore} for durable suspend/resume
|
|
972
|
+
* (design/45). Overrides `RunnerDeps.checkpointStore`. Needed (with `durableApproval`) to suspend. */
|
|
973
|
+
checkpointStore?: import("./checkpoint-store.js").CheckpointStore;
|
|
974
|
+
/**
|
|
975
|
+
* Restrict the injected "hand" band (design/44) to its effect:read tools for this task — read_file /
|
|
976
|
+
* grep / glob (+ `bash_readonly` when a shell is available); edit_file / write_file / `bash` are not
|
|
977
|
+
* mounted. This is the verifier read-only boundary (§6): an adversarial verifier inspects but must not
|
|
978
|
+
* modify the project. No effect unless an `executionEnv` is injected. Default false.
|
|
979
|
+
*/
|
|
980
|
+
handsReadOnly?: boolean;
|
|
981
|
+
/**
|
|
982
|
+
* design/119 (CC --add-dir parity): extra directories the FILE tools may access in addition to the
|
|
983
|
+
* containment root — each is canonicalized into the containment allowlist and listed in the
|
|
984
|
+
* `# Environment` block so the model knows they're available. Same defense-in-depth caveat as the
|
|
985
|
+
* root: this bounds the file tools, not `bash` (OS-level containment is the env's job).
|
|
986
|
+
*/
|
|
987
|
+
additionalDirectories?: string[];
|
|
988
|
+
/**
|
|
989
|
+
* design/80 D-B — opt in to PLAN MODE: mount the first-party `present_plan` tool (CC `ExitPlanMode` parity).
|
|
990
|
+
* The model calls it to present a plan; the engine then pauses with a durable `plan_review` checkpoint
|
|
991
|
+
* (`status:"needs_review"`) so a human approves/edits/rejects before any action. Typically paired with
|
|
992
|
+
* `handsReadOnly:true` (research read-only until the plan is approved, then the resume drops it). Default
|
|
993
|
+
* false — when unset the tool is NOT mounted, NOT disclosed, and a `ToolReturn.requestReview` is ignored, so
|
|
994
|
+
* a non-plan-mode task is byte-identical. Needs a `checkpointStore` wired to actually pause (else a
|
|
995
|
+
* `requestReview` is a no-op). The tool is a thin composition over the general `requestReview` primitive.
|
|
996
|
+
*/
|
|
997
|
+
enablePlanMode?: boolean;
|
|
998
|
+
/**
|
|
999
|
+
* design/110 / design/136 §2.1.a (⚠️ BREAKING semantics change) — the per-task FORK governance gate for
|
|
1000
|
+
* `Agent(subagent_type:"fork")` (the standalone `Fork` tool was retired; the capability lives in the Agent
|
|
1001
|
+
* tool's `subagent_type` value domain — CC-exact shape). The fork spawns a child that INHERITS this
|
|
1002
|
+
* conversation's full context (vs the clean-context delegation) and shares the prompt-cache prefix.
|
|
1003
|
+
*
|
|
1004
|
+
* OPT-OUT default (flipped from the pre-136 opt-IN): `undefined`/`true` = fork is AVAILABLE, bounded by the
|
|
1005
|
+
* session capability (`hasSessionFork` durable store + a session id + not inside a fork — honest refusal
|
|
1006
|
+
* otherwise); an EXPLICIT `false` = fork is DENIED for this task with the honest `fork.disabled` result
|
|
1007
|
+
* (never a silent downgrade). Multi-tenant deployments that previously relied on `undefined` being OFF must
|
|
1008
|
+
* now send `enableFork: false` explicitly (or deny per-principal via `RuntimeCaps.allowFork`).
|
|
1009
|
+
*/
|
|
1010
|
+
enableFork?: boolean;
|
|
1011
|
+
/**
|
|
1012
|
+
* design/80 D-2 (part-1): gate the injected `bash` hand tool, since a full shell can run egress (`curl`,
|
|
1013
|
+
* `git push`) and irreversible (`rm`) commands that the per-tool egress/irreversibility marks otherwise miss.
|
|
1014
|
+
* The §4-OQ4 doctrine: shell-in-presence ⇒ always-gate UNLESS a real parsed classifier is wired.
|
|
1015
|
+
* - `"off"` (default): `bash` is unmarked — the current behavior (subject only to the deployment's policy).
|
|
1016
|
+
* - `"always"`: every `bash` command tightens to an `irreversible_ask` durable suspend (fail-closed; the
|
|
1017
|
+
* correct default for an unattended/supervisor deployment with no classifier).
|
|
1018
|
+
* - `"classify"`: mark `bash` `irreversibility:"maybe"` with {@link import("../tools/fs/index.js").bashReversibilityProbe}
|
|
1019
|
+
* — a provably-benign single allowlisted read-only command (no operators) auto-allows; everything else
|
|
1020
|
+
* (writes, egress, pipes, unknown commands) tightens to ask. An egress command (e.g. `curl`) suspends under
|
|
1021
|
+
* the IRREVERSIBLE axis (the shell mark is irreversibility, not egress) — the kind is non-budgetable either
|
|
1022
|
+
* way, so the budget resolver still never auto-approves it; the axis label is informational.
|
|
1023
|
+
* No effect under `handsReadOnly` (that mounts `bash_readonly`, already allowlisted) or with no execution env.
|
|
1024
|
+
* **Re-supply on resume:** like `toolPolicy`/`tools`/`durableApproval`, `shellGate` is part of the resume
|
|
1025
|
+
* task config — a resume that omits it leaves the resumed run's SUBSEQUENT `bash` calls ungated (the approved
|
|
1026
|
+
* pending call itself runs once, having been adjudicated). Re-pass the same value the original task used.
|
|
1027
|
+
*/
|
|
1028
|
+
shellGate?: "off" | "always" | "classify";
|
|
1029
|
+
/** Task-scoped MCP servers, materialized into tools then disposed. */
|
|
1030
|
+
mcp?: McpServerSpec[];
|
|
1031
|
+
/**
|
|
1032
|
+
* Task-scoped skills (object form). Two first-party halves (design/71 黑盒#5 fix): a stable
|
|
1033
|
+
* `<skills>` system-prompt block disclosing name+description (deterministic order, capped), and an
|
|
1034
|
+
* injected `skill` tool (effect:read) that returns the skill's full content as a tool result
|
|
1035
|
+
* (per-skill body cap with an honest truncation marker). Duplicate names: first wins. The name
|
|
1036
|
+
* `skill` becomes reserved when this field is non-empty (`config.reserved_tool_name`).
|
|
1037
|
+
*
|
|
1038
|
+
* Skill content is CALLER-trusted — same trust level as `systemPrompt`. Callers forwarding
|
|
1039
|
+
* end-user-authored skills are responsible for vetting them: a skill IS instructions by design.
|
|
1040
|
+
*/
|
|
1041
|
+
skills?: SkillSpec[];
|
|
1042
|
+
/**
|
|
1043
|
+
* design/129 — lifetime scope for BACKGROUND children (Agent/Fork `run_in_background`). Default `"task"`:
|
|
1044
|
+
* the parent runTask's terminal reaps them (design/115 — no orphans burning tokens; [431] turn-end killed
|
|
1045
|
+
* frame). `"session"`: children OUTLIVE the turn (CC Backgrounded semantics) — registered under the
|
|
1046
|
+
* SESSION owner (cross-turn TaskOutput poll works), skipped by the parent-teardown reap, force-capped by
|
|
1047
|
+
* a default child timeout when none is given, and finally reapable via
|
|
1048
|
+
* `TaskRegistry.reapSessionBackground(sessionId, scope)` (call it from your session release/sweep).
|
|
1049
|
+
* CALLER-trusted (systemPrompt tier): never a model-facing parameter, never on the governed workflow
|
|
1050
|
+
* whitelist — a child's lifetime crossing the turn boundary is an isolation-contract surface.
|
|
1051
|
+
*/
|
|
1052
|
+
backgroundScope?: "task" | "session";
|
|
1053
|
+
/**
|
|
1054
|
+
* 黑板 [435]/[442] A1 — structured SANDBOX facts for the `# Environment` block, so the agent knows what
|
|
1055
|
+
* toolchains the environment already carries (no blind reinstall), which package source installs go
|
|
1056
|
+
* through, and whether the network is reachable at all (egress=none ⇒ don't burn budget on downloads).
|
|
1057
|
+
* DEPLOYMENT-trusted (systemPrompt tier — the deployment knows its own sandbox binding): rendered
|
|
1058
|
+
* sanitized+bounded by prepare-task; never a model-facing parameter, never on the governed workflow
|
|
1059
|
+
* whitelist. All fields optional; absent ⇒ block unchanged.
|
|
1060
|
+
*/
|
|
1061
|
+
envFacts?: {
|
|
1062
|
+
/** The bound sandbox image profile (e.g. `dev-mobile`). */
|
|
1063
|
+
profile?: string;
|
|
1064
|
+
/** Toolchains/capabilities the image carries (e.g. `android-sdk`, `gradle`). Rendered bounded. */
|
|
1065
|
+
capabilities?: readonly string[];
|
|
1066
|
+
/** Which package-source lane installs go through (e.g. `cn` | `global` | `custom`). */
|
|
1067
|
+
pkgSource?: string;
|
|
1068
|
+
/** Outbound-network posture. `none` renders an explicit "downloads will fail" caveat. */
|
|
1069
|
+
egress?: "none" | "allowlist" | "full";
|
|
1070
|
+
/** Session-specific scratch directory for temporary files (CC Scratchpad parity, 1.257.3): when set,
|
|
1071
|
+
* the environment block instructs the model to use this dir instead of `/tmp` — prevents parallel
|
|
1072
|
+
* tasks trampling each other's temp files and project-dir pollution. Unset ⇒ no section rendered. */
|
|
1073
|
+
scratchpadDir?: string;
|
|
1074
|
+
};
|
|
1075
|
+
limits?: {
|
|
1076
|
+
maxTurns?: number;
|
|
1077
|
+
timeoutSec?: number;
|
|
1078
|
+
/**
|
|
1079
|
+
* design/119 #2: per-REQUEST output-token cap (the provider `max_tokens` / `max_completion_tokens`
|
|
1080
|
+
* field). Distinct from `maxTokens` (the cumulative BUDGET cap): this bounds each model reply.
|
|
1081
|
+
* Unset ⇒ prior behavior (Anthropic: model.maxTokens; OpenAI family: provider default). A reply
|
|
1082
|
+
* that hits it stops with `length` and the loop's truncated-output auto-continue takes over.
|
|
1083
|
+
* HARD bound on Anthropic budget-thinking models too: a cap too small to host a legal thinking
|
|
1084
|
+
* budget (< 2048) skips thinking for the request rather than silently raising the cap.
|
|
1085
|
+
*/
|
|
1086
|
+
maxOutputTokens?: number;
|
|
1087
|
+
/**
|
|
1088
|
+
* design/128 T1-2 — deadline awareness for `timeoutSec` (default ON). At each turn boundary the run
|
|
1089
|
+
* loop checks elapsed wall-clock against the budget and injects at most TWO one-shot
|
|
1090
|
+
* `<system-reminder>` nudges (at ~80%: "start converging"; at ~95% or budget−2min, whichever is
|
|
1091
|
+
* earlier: "deliver NOW") so the model converges BEFORE the hard abort instead of losing unfinished
|
|
1092
|
+
* work to it. `false` disables; `{at:[a,b]}` overrides the two ratios (0<a<b<1). No effect without
|
|
1093
|
+
* `timeoutSec`. Resource-suspend-eligible tasks never nudge (their timeoutSec is a SLICE boundary —
|
|
1094
|
+
* the clean suspend already is the convergence). Cost: at most two tail transcript reminders; the
|
|
1095
|
+
* stable system prefix (and thus the prompt cache) is untouched. Known limit: the check runs only at
|
|
1096
|
+
* turn boundaries — a single very long turn can sail past a threshold and see the nudge one boundary
|
|
1097
|
+
* late.
|
|
1098
|
+
*/
|
|
1099
|
+
deadlineNudge?: false | {
|
|
1100
|
+
at?: [number, number];
|
|
1101
|
+
};
|
|
1102
|
+
/**
|
|
1103
|
+
* design/130 P1 — wall-clock-aware per-CALL output cap (default ON when `timeoutSec` is set).
|
|
1104
|
+
* Before each model call the runner shrinks the request's `max_tokens` to what the remaining
|
|
1105
|
+
* wall-clock can actually absorb (`remainingSec × measured-throughput × 0.5 safety`, EWMA from
|
|
1106
|
+
* this run's completed calls; a conservative prior before the first sample), clamped to
|
|
1107
|
+
* [1024, `maxOutputTokens` ?? model default]. SHRINK-ONLY: never raises the static ceiling.
|
|
1108
|
+
* Thinking contract (codex ①): a cap that lands in [1024, 2047] is raised to 2048 iff the
|
|
1109
|
+
* remaining budget can absorb it WITHOUT the safety margin; otherwise the cap stands and an
|
|
1110
|
+
* Anthropic budget-thinking call skips thinking for that request (design/119 semantics) — the
|
|
1111
|
+
* `brain.call` trace carries `callCap`/`capThinkingSkipped` either way. `false` disables.
|
|
1112
|
+
* Resource-suspend-eligible tasks never shrink (their timeoutSec is a SLICE boundary; a
|
|
1113
|
+
* per-slice opt-in is deferred). No effect without `timeoutSec`.
|
|
1114
|
+
*/
|
|
1115
|
+
callCapByDeadline?: false;
|
|
1116
|
+
/**
|
|
1117
|
+
* design/130 P2 — graceful-finalize turn (default ON when `timeoutSec` is set). At a turn
|
|
1118
|
+
* boundary where the remaining wall-clock no longer fits one more full model-call + tool cycle
|
|
1119
|
+
* (EWMA of this run's call latencies + tool durations, ×1.25 headroom), the runner injects a
|
|
1120
|
+
* ONE-SHOT finalize instruction — "write your best current answer to the deliverable path NOW,
|
|
1121
|
+
* open no new work" — and suppresses any still-pending deadline nudges (one deadline-class
|
|
1122
|
+
* message per boundary, finalize wins — codex ②). The turn after finalize still runs under the
|
|
1123
|
+
* P1 cap with its floor raised to 2048 so the write-out isn't starved. `false` disables.
|
|
1124
|
+
* Resource-suspend-eligible tasks never finalize (clean slice suspend outranks it — codex ⑤).
|
|
1125
|
+
* v1 is instruction-only: the finalize turn's tool face is NOT narrowed (deferred; needs a
|
|
1126
|
+
* mid-run setTools surgery whose cache cost outweighs v1 value).
|
|
1127
|
+
*
|
|
1128
|
+
* design/130 P2b — deadline EXECUTION hardening (rides this same switch; the family is one
|
|
1129
|
+
* discipline). With finalize on, the runner additionally reserves a fixed write-out CUSHION
|
|
1130
|
+
* (15% of the budget, clamped to [10s, 75s]) and enforces a soft execution deadline
|
|
1131
|
+
* (`deadline − cushion`; the finalize turn itself gets `deadline − 5s`):
|
|
1132
|
+
* - the finalize boundary condition becomes `remaining < est + cushion` (the last work cycle
|
|
1133
|
+
* can no longer eat the write-out window), with a TAIL-AWARE est (decayed peak ∨ EWMA);
|
|
1134
|
+
* - first-party brains CUT a model call whose stream crosses the soft deadline (prefix
|
|
1135
|
+
* salvaged, one bounded write-out turn follows; exhausted ⇒ `timeout` + salvagedOutput);
|
|
1136
|
+
* - foreground shell timeouts are CLAMPED to the soft deadline (a long command times out
|
|
1137
|
+
* cleanly instead of riding into the hard abort).
|
|
1138
|
+
* `stats.mechanisms.callCutoffs`/`toolClamps` count the engagements. `false` disables all of it.
|
|
1139
|
+
*/
|
|
1140
|
+
gracefulFinalize?: false;
|
|
1141
|
+
};
|
|
1142
|
+
/**
|
|
1143
|
+
* Blackboard 2026-07-03 (subagent viewing pane, clay dogfood): widen the opt-in display sink
|
|
1144
|
+
* (`RunInternals.onForwardEvent`) from `task_progress`-only to a SUBAGENT's live CONTENT events
|
|
1145
|
+
* (`text_delta` / `reasoning_delta` / `tool_start` / `tool_end`), so a UI can render a delegated
|
|
1146
|
+
* child's transcript live. Default OFF (progress-only, prior behavior). The child stream is still
|
|
1147
|
+
* NEVER merged into the parent's model context — this is purely a render channel; forwarded events
|
|
1148
|
+
* carry `parentToolCallId` (attribution) and the same UNTRUSTED-RAW contract as the main stream's
|
|
1149
|
+
* `tool_start.args`/`tool_end.output` (consumer MUST redact — design/99 §E1). Single-level: each
|
|
1150
|
+
* delegation level opts in for ITS direct children.
|
|
1151
|
+
*/
|
|
1152
|
+
forwardSubagentEvents?: boolean;
|
|
1153
|
+
/**
|
|
1154
|
+
* design/122 D1 — RETAIN sync sub-agent sessions after they settle so an operator can RESUME (revive) a
|
|
1155
|
+
* finished child with a new prompt via {@link import("../agents/subagent.js").SubagentSteerHandle}'s
|
|
1156
|
+
* `resume` verb (CC `dfe` resumeAgentBackground parity). Default OFF = prior behavior byte-for-byte:
|
|
1157
|
+
* child sessions are throwaway (released eagerly after the delegation returns).
|
|
1158
|
+
*
|
|
1159
|
+
* ON (`true` or a config object): each SYNC delegation spawned while the deployment's
|
|
1160
|
+
* `RunInternals.onSubagentSpawn` sink is wired (the handle-emitting path — without a handle there is no
|
|
1161
|
+
* resume capability, so retaining would be a pure leak) pre-mints the child's sessionId, PINS it against
|
|
1162
|
+
* the store's idle sweep, and SKIPS the eager release. The session is retained in a parent-run-scoped
|
|
1163
|
+
* ledger until `ttlMs` after settle (default 30 min), eviction past `max` retained children (default 16),
|
|
1164
|
+
* or the PARENT run reaching a terminal state — whichever comes first; then it is unpinned + explicitly
|
|
1165
|
+
* released (throwaway semantics restored — a retained session never dangles to the store's 7-day TTL).
|
|
1166
|
+
* `run_in_background` children are OUT OF SCOPE (no handle, no retain — r1-M3; the bg lane's resume needs
|
|
1167
|
+
* durable support and is a separate item). Resume is reachable only while the parent run lives (the
|
|
1168
|
+
* ledger is run-scoped, not a durable registry — codex-B3).
|
|
1169
|
+
*/
|
|
1170
|
+
retainSubagentSessions?: boolean | {
|
|
1171
|
+
ttlMs?: number;
|
|
1172
|
+
max?: number;
|
|
1173
|
+
};
|
|
1174
|
+
/**
|
|
1175
|
+
* design/120 P2: opt in to in-stream tool execution — safe tool calls start while the model is
|
|
1176
|
+
* still streaming its response instead of waiting for the full reply. Default OFF. Forwarded to
|
|
1177
|
+
* the harness, which additionally withholds it whenever a `tool_call` gate handler is registered
|
|
1178
|
+
* (policy / approval / egress runs — a gate could durably suspend, which is impossible
|
|
1179
|
+
* mid-stream), so setting this on a gated task is safe and simply has no effect. A run whose only
|
|
1180
|
+
* gate concern is resource-suspend does NOT register that handler (it stops at clean turn
|
|
1181
|
+
* boundaries), so in-stream execution stays available there.
|
|
1182
|
+
*
|
|
1183
|
+
* Known limitation (documented): with this ON, a tool's side effect can complete BEFORE the
|
|
1184
|
+
* assistant message persists; a hard process crash in that window leaves no transcript trace of
|
|
1185
|
+
* the call (wake reconcile cannot see an orphan that was never written). Prefer OFF for
|
|
1186
|
+
* deployments where crash-exactly-once accounting of tool effects matters more than latency.
|
|
1187
|
+
*/
|
|
1188
|
+
streamingToolExecution?: boolean;
|
|
1189
|
+
/**
|
|
1190
|
+
* Hard cost ceiling in USD for this task (requires `model.cost` or `RunnerDeps.pricing`). Checked
|
|
1191
|
+
* pre-call and at each turn boundary; exceeding ends the task `failed` with `errorCode="budget.precall"`
|
|
1192
|
+
* (estimate rejected, nothing spent) or `"budget.exceeded"` (after spend). When set, `budgetStreamCancel`
|
|
1193
|
+
* defaults to `true`.
|
|
1194
|
+
*
|
|
1195
|
+
* NOTE: the pre-call check is **best-effort** — it estimates the first call's input from the objective
|
|
1196
|
+
* length only (it cannot see the assembled system prompt / history / memory), so it may under-estimate
|
|
1197
|
+
* and let an oversized first turn run; the turn-boundary gate then catches it as `budget.exceeded`.
|
|
1198
|
+
* Treat `budget.precall` as a fast-fail optimization, not a hard guarantee that no single call exceeds.
|
|
1199
|
+
*/
|
|
1200
|
+
maxCostUsd?: number;
|
|
1201
|
+
/** Hard cap on cumulative prompt+completion tokens; exceeding ends `failed` + `"budget.exceeded"`. */
|
|
1202
|
+
maxTokens?: number;
|
|
1203
|
+
/** Cancel an in-flight stream the moment cumulative cost crosses `maxCostUsd`. Defaults to `true`
|
|
1204
|
+
* when `maxCostUsd` is set (hard control), `false` otherwise. */
|
|
1205
|
+
budgetStreamCancel?: boolean;
|
|
1206
|
+
/**
|
|
1207
|
+
* **Near-budget degradation** (1.39 v2, design/21 §5C). When cumulative cost reaches `atCostFraction`
|
|
1208
|
+
* of `maxCostUsd`, **switch the active model to the cheaper `to`** for the rest of the task to stretch
|
|
1209
|
+
* the remaining budget — accepting lower quality instead of stopping at `maxCostUsd`. One-way (never
|
|
1210
|
+
* switches back); sets `TaskResult.degraded = { …, reason: "budget" }`. Requires `maxCostUsd` (the
|
|
1211
|
+
* fraction is of it); ignored otherwise. This is the proactive, Runner-level complement to the
|
|
1212
|
+
* reactive brain-level `createDegradingBrain` (rate_limit / breaker-open).
|
|
1213
|
+
*/
|
|
1214
|
+
degrade?: {
|
|
1215
|
+
to: ModelRef;
|
|
1216
|
+
atCostFraction: number;
|
|
1217
|
+
};
|
|
1218
|
+
/**
|
|
1219
|
+
* **Structured output** (1.41): constrain the task's FINAL result to this JSON schema (a typebox
|
|
1220
|
+
* object schema). Injects a built-in `submit_output` tool whose parameters ARE this schema; the model
|
|
1221
|
+
* calls it to finish, the validated object is surfaced as `TaskResult.structuredOutput`, and the task
|
|
1222
|
+
* ends. Provider-agnostic (it's just a tool). If the model can't produce a valid object within a few
|
|
1223
|
+
* tries the task fails with `errorCode="output.invalid"`. A caller tool named `submit_output` is
|
|
1224
|
+
* rejected (reserved). The model may still answer in prose (then `structuredOutput` is undefined) or
|
|
1225
|
+
* `report_blocked`. Cast the result with `Static<typeof yourSchema>`.
|
|
1226
|
+
*/
|
|
1227
|
+
outputSchema?: TSchema;
|
|
1228
|
+
/**
|
|
1229
|
+
* How many times the model may **retry** a rejected `submit_output` before the task fails with
|
|
1230
|
+
* `errorCode="output.invalid"` (only meaningful when {@link outputSchema} is set). `0` = fail on the
|
|
1231
|
+
* first invalid submit (no in-loop retry); the caller decides whether to re-run. Default `2`
|
|
1232
|
+
* (3 total attempts). Clamped to a non-negative integer. This bounds only the *in-task* retry of a
|
|
1233
|
+
* malformed object — it is not an auto-fixer; pair it with a caller-side retry on `output.invalid`.
|
|
1234
|
+
*/
|
|
1235
|
+
outputRetries?: number;
|
|
1236
|
+
/** Best-effort fire-and-forget trace sink (task/turn/brain/tool). Overrides `RunnerDeps.tracer`. */
|
|
1237
|
+
tracer?: import("./trace.js").TracerHook;
|
|
1238
|
+
/** Per-task override of the large-tool-result offload threshold (chars); see `RunnerDeps.toolResultThresholdChars`. */
|
|
1239
|
+
toolResultThresholdChars?: number;
|
|
1240
|
+
/**
|
|
1241
|
+
* Override auto-compaction thresholds for this task's session. Compaction (LLM summary, persisted
|
|
1242
|
+
* to the session) runs in two places sharing these settings: at every within-task turn boundary
|
|
1243
|
+
* (design/64 §25 (A) — the long-single-task case) and once at task end (the between-task case).
|
|
1244
|
+
* Defaults: enabled, reserveTokens 16384, keepRecentTokens 20000 — repaired automatically when
|
|
1245
|
+
* pathological for the model's window: threshold ≤ 0, keepRecent ≥ threshold, or a threshold above
|
|
1246
|
+
* the clearStale point (0.7×window — the prefix-cache "death band", design/64 §26.4) is clamped
|
|
1247
|
+
* down to it. The clamp applies to explicit values too (the clearStale point is not configurable,
|
|
1248
|
+
* so a threshold above it cannot express consistent intent); explicit values below all three
|
|
1249
|
+
* bounds are never overridden (see `sanitizeCompactionSettings`).
|
|
1250
|
+
* `instructions` is appended to the summarization prompt — use it to guarantee critical
|
|
1251
|
+
* facts survive (e.g. "preserve verbatim any codes, IDs, names, and explicit user instructions").
|
|
1252
|
+
* Scope caveat (design/141 examples 批实测): `instructions` rides the WHOLE-TURN summarization
|
|
1253
|
+
* request only; a split-turn cut point (mid-turn prefix summarization) uses the engine-owned
|
|
1254
|
+
* turn-prefix prompt and does not carry it (same A2 boundary as `RunnerDeps.summaryProvider`).
|
|
1255
|
+
* `withinTask: false` keeps end-of-task compaction but disables the within-task (turn-boundary)
|
|
1256
|
+
* trigger — the escape hatch for the §25 (A) control-flow change; the system prompt then stops
|
|
1257
|
+
* claiming mid-task summarization (§6.3 honesty).
|
|
1258
|
+
* `attachWorkingFiles` (LONGRUN-2; **default ON since 2026-07-03** — CC 198 hard-codes its
|
|
1259
|
+
* post-compact file restore, and LONGRUN-2 measured ≈2.3 extra read round-trips per compaction
|
|
1260
|
+
* without it): after each compaction, re-read the task's most recently READ files (CC
|
|
1261
|
+
* readFileState semantics; falls back to modified-by-recency when read tracking is absent) and
|
|
1262
|
+
* append their current contents to the summary (bounded: `maxFiles` default 3,
|
|
1263
|
+
* `maxCharsPerFile` default 16k chars ≈ 4k tokens, plus a total cap that self-scales to ~15% of
|
|
1264
|
+
* the model window). The `compacted` wire event carries the attached list as `attachedFiles`
|
|
1265
|
+
* (shell renders CC's post-compact Read cards). `false` opts out; an object customizes caps;
|
|
1266
|
+
* no-op when the task has no execution env (no hands, nothing to re-read).
|
|
1267
|
+
*/
|
|
1268
|
+
compaction?: {
|
|
1269
|
+
enabled?: boolean;
|
|
1270
|
+
withinTask?: boolean;
|
|
1271
|
+
reserveTokens?: number;
|
|
1272
|
+
keepRecentTokens?: number;
|
|
1273
|
+
instructions?: string;
|
|
1274
|
+
attachWorkingFiles?: boolean | {
|
|
1275
|
+
maxFiles?: number;
|
|
1276
|
+
maxCharsPerFile?: number;
|
|
1277
|
+
};
|
|
1278
|
+
};
|
|
1279
|
+
/**
|
|
1280
|
+
* design/133 §R3 — turn-boundary attachment producers (CC `getContextAttachments` parity), ALL
|
|
1281
|
+
* OPT-IN. Same default-face judgment as design/132 `finalVerification` (B2/H2): the evidence for
|
|
1282
|
+
* these reminders comes from AUTONOMOUS long-task legs (weak-model drift safety net — CC's own
|
|
1283
|
+
* trigger counts proved unreproducible: the observed CC runs never mounted TodoWrite), so the
|
|
1284
|
+
* autonomy entrypoints (sema-tb) turn them on and interactive deployments stay byte-identical
|
|
1285
|
+
* until a behavior leg proves them neutral. At most ONE coalesced `<system-reminder>` steer per
|
|
1286
|
+
* clean turn boundary, lowest lane: finalize/deadline-nudge/diagnostics at the same boundary — and
|
|
1287
|
+
* the design/130 P2 / design/132 end-game latches — all suppress it.
|
|
1288
|
+
*
|
|
1289
|
+
* - `todoReminder`: CC 10/10 cadence — when TodoWrite (or the task tools; both mounted ⇒ the
|
|
1290
|
+
* task family wins, CC isTodoV2) hasn't been used for 10 assistant turns, re-surface the list
|
|
1291
|
+
* (thin projection; an all-completed list is cleared, never regurgitated). No tools mounted ⇒
|
|
1292
|
+
* permanently silent.
|
|
1293
|
+
* - `changedFiles`: boundary-time stat of ≤20 (or `maxFiles`) most-recently-READ files; a file
|
|
1294
|
+
* whose mtime moved past the recorded read time (+2s epsilon) is listed (path-only v1, "do not
|
|
1295
|
+
* blindly revert — re-read"). OFF ⇒ zero stat calls. Self-edits are immune (write-back
|
|
1296
|
+
* refreshes the read stamp); mtime skew on exotic fs remains a documented false-positive source.
|
|
1297
|
+
* - `planModeReminder`: while `enter_plan_mode` is active, re-surface the read-only constraint
|
|
1298
|
+
* every 5 assistant turns (full copy every 5th, sparse between) so a long plan phase doesn't
|
|
1299
|
+
* drift into write-deny thrash. Exiting plan mode stops it.
|
|
1300
|
+
* - `backgroundTasks` (G1 通告层, 黑板 [482] — CC /compact parity): after a compaction LANDS, the
|
|
1301
|
+
* next boundary announces this run's still pending/running background tasks (task registry
|
|
1302
|
+
* snapshot: id/description/status, CC three-state copy). ONE-SHOT per compaction — never
|
|
1303
|
+
* per-boundary nagging; no compaction ⇒ permanently silent.
|
|
1304
|
+
* - `toolsDelta` (G1 — CC deferred-tools boundary notice): when design/36 `tool_search`
|
|
1305
|
+
* materializes deferred tools mid-task (setTools + fingerprint refresh), the next boundary
|
|
1306
|
+
* announces the NEWLY available names once. Already-active and resume-reseeded tools are never
|
|
1307
|
+
* (re)announced; no deferred tools ⇒ permanently silent.
|
|
1308
|
+
* - `agentListing` (G1 续批 — CC `agent_listing_delta` parity): when a delegation tool built by
|
|
1309
|
+
* `createSubagentTool` is mounted, the FIRST collected boundary announces the full agent-type
|
|
1310
|
+
* roster ("Available agent types for the Agent tool:", CC-verbatim; + the concurrency note when
|
|
1311
|
+
* more than one type). Later boundaries announce only roster drift (adds/removals — static in
|
|
1312
|
+
* practice; the delta lane serves dynamic-registration deployments). A durable resume leg is
|
|
1313
|
+
* seeded as already-announced (the prior leg's listing is in the transcript — never replayed).
|
|
1314
|
+
* - `mcpInstructions` (G1 续批 — CC `mcp_instructions_delta` parity): the INITIAL server
|
|
1315
|
+
* instructions stay in the stable system prompt (`# MCP Server Instructions`, design/64 §17.3 —
|
|
1316
|
+
* deliberate CC deviation: CC injects them as reminders, sema's stable-prompt carrier is
|
|
1317
|
+
* prefix-cache-correct). This member announces only DELTAS: a mid-task disconnect of an
|
|
1318
|
+
* instruction-bearing server ("The following MCP servers have disconnected…", CC-verbatim), and
|
|
1319
|
+
* the add lane for a future dynamic-connect face. Added instruction text is UNTRUSTED server
|
|
1320
|
+
* text → fenced with `delimitUntrusted` (deliberate CC deviation: CC injects it raw).
|
|
1321
|
+
*
|
|
1322
|
+
* Telemetry: `steering_injected` (source `todo_reminder`/`task_reminder`/`changed_files`/
|
|
1323
|
+
* `plan_mode`/`background_tasks`/`tools_delta`/`agent_listing`/`mcp_instructions`) +
|
|
1324
|
+
* `stats.mechanisms.attachmentsInjected`.
|
|
1325
|
+
*/
|
|
1326
|
+
attachments?: {
|
|
1327
|
+
todoReminder?: true;
|
|
1328
|
+
/**
|
|
1329
|
+
* task #51 口径③ — CC `r2o()` kill-switch parity (CC 198 pretty.js:479167-479171; both reminder
|
|
1330
|
+
* producers consume it as `if (r2o() === "off") return []`, :480232/:480268). `"off"` silences the
|
|
1331
|
+
* todo/task reminder lane even when `todoReminder` is wired on (the other attachment producers are
|
|
1332
|
+
* untouched — CC's nudge gate is lane-scoped); any other value (or absence) = CC `"baseline"`.
|
|
1333
|
+
* CC resolves this from env `CLAUDE_CODE_TODO_REMINDER_MODE` / the `tengu_soft_slate_nudge` gate;
|
|
1334
|
+
* sema keeps env resolution at the deployment shell (sema-tb: `TB_TODOREMIND=off`) — core reads no env.
|
|
1335
|
+
*/
|
|
1336
|
+
todoReminderMode?: "baseline" | "off";
|
|
1337
|
+
changedFiles?: true | {
|
|
1338
|
+
maxFiles?: number;
|
|
1339
|
+
};
|
|
1340
|
+
planModeReminder?: true;
|
|
1341
|
+
/**
|
|
1342
|
+
* SR-3 (CC 198 `budget_usd` lane, producer QFm pretty.js:480424-480428 + renderer :600225): the
|
|
1343
|
+
* progressive $-budget readout `USD budget: $used/$total; $remaining remaining` (CC-verbatim
|
|
1344
|
+
* template). CC-exact activation: live ONLY while the task carries an effective cost ceiling
|
|
1345
|
+
* (`maxCostUsd`, or a resource-slice ledger remaining — CC `options.maxBudgetUsd`); no ceiling ⇒
|
|
1346
|
+
* permanently silent even when opted in. CC-exact cadence: NO threshold ladder and NO throttle —
|
|
1347
|
+
* CC mounts it on every main-agent attachment cycle (:479243-479245, gated `d = !t.agentId`), so
|
|
1348
|
+
* sema emits one line at every collected clean turn boundary; the "progression" is the numbers
|
|
1349
|
+
* advancing with spend. Recorded deviation (continuation gate): CC attaches at request assembly
|
|
1350
|
+
* and can never EXTEND a run, while a sema boundary steer revives an idle harness — so this lane
|
|
1351
|
+
* only rides boundaries whose turn resolved ≥1 tool call (a next request is already guaranteed);
|
|
1352
|
+
* a text-only final turn is never dragged past its natural end. Numbers ride the enforcement
|
|
1353
|
+
* coordinate (`stats.costMicroUsd` vs the effective ceiling, ÷1e6 → USD) so the readout never
|
|
1354
|
+
* disagrees with `budget.exceeded`.
|
|
1355
|
+
* NOTE: this deliberately relaxes the design/74 "no budget language reaches the model" default —
|
|
1356
|
+
* that judgment shaped the DEFAULT-OFF posture; an opted-in deployment chooses CC parity.
|
|
1357
|
+
*/
|
|
1358
|
+
budgetUsd?: true;
|
|
1359
|
+
backgroundTasks?: true;
|
|
1360
|
+
toolsDelta?: true;
|
|
1361
|
+
agentListing?: true;
|
|
1362
|
+
mcpInstructions?: true;
|
|
1363
|
+
};
|
|
1364
|
+
/**
|
|
1365
|
+
* Inject a built-in `report_blocked` tool the agent can call when it cannot finish
|
|
1366
|
+
* (missing info, permission, ambiguity). When called, the task ends with status "blocked".
|
|
1367
|
+
* Default: true.
|
|
1368
|
+
*/
|
|
1369
|
+
enableBlockedReport?: boolean;
|
|
1370
|
+
/**
|
|
1371
|
+
* **LLM self-orchestration** (design/98, S8). Allow THIS task's model to AUTHOR + RUN its own workflow
|
|
1372
|
+
* (a deterministic JS orchestration script) via the `run_workflow` tool. Default `false`.
|
|
1373
|
+
*
|
|
1374
|
+
* 🔴 REQUIRES a deployment-provided HARD sandbox AND a governance baseline:
|
|
1375
|
+
* `RunnerDeps.workflowScriptRunner.safeForUntrustedScripts === true` (an isolated-vm / separate-process
|
|
1376
|
+
* runner — the Node `vm` dev runner is NOT a security boundary) AND `RunnerDeps.workflowGovernanceBaseline`
|
|
1377
|
+
* (the deployment-trusted governance every spawned sub-agent inherits, tighten-only). With EITHER missing
|
|
1378
|
+
* the tool is NOT mounted and the orchestration prompt is NOT injected (FAIL-CLOSED) — core never runs an
|
|
1379
|
+
* LLM-authored script in the dev `vm`, and never lets a script-spawned agent run with no governed baseline.
|
|
1380
|
+
*
|
|
1381
|
+
* Recommended ONLY for strong models; weak models default-off (force-enableable, but the hard-sandbox +
|
|
1382
|
+
* baseline bar still applies — the gate is the deployment's sandbox/governance, NOT the model id). NOT
|
|
1383
|
+
* enforced by model id.
|
|
1384
|
+
*/
|
|
1385
|
+
selfOrchestration?: boolean;
|
|
1386
|
+
/** Per-model auth. Returns the api key (and optional headers) for a given provider/model. */
|
|
1387
|
+
getApiKeyAndHeaders?: (model: Model) => Promise<{
|
|
1388
|
+
apiKey: string;
|
|
1389
|
+
headers?: Record<string, string>;
|
|
1390
|
+
} | undefined>;
|
|
1391
|
+
/**
|
|
1392
|
+
* External cancellation. When it aborts, the task aborts (the brain request is cancelled and any
|
|
1393
|
+
* pending tool-policy gate releases). Pass a parent tool's `ToolExecuteContext.signal` here so a
|
|
1394
|
+
* nested `runTask` stops the instant the parent does instead of running to its own `timeoutSec`.
|
|
1395
|
+
*/
|
|
1396
|
+
signal?: AbortSignal;
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* `"suspended"` (design/45) is a **non-terminal** outcome: the task hit a durable tool-policy gate
|
|
1400
|
+
* (`ask` with a `CheckpointStore` wired) and persisted a checkpoint instead of finishing — resume it
|
|
1401
|
+
* with `runner.resume(checkpointToken, outcome)`. v1 contract: it is only safe at the **top-level
|
|
1402
|
+
* `runTask` boundary**; the orchestrators (cascade/teacher/verify/team) map an unexpected `suspended`
|
|
1403
|
+
* to `failed` + `errorCode:"unexpected.suspended"` and pass the token up (§11 Q6, hard boundary).
|
|
1404
|
+
*
|
|
1405
|
+
* `"needs_review"` (design/76 §2.5, dry-run / shadow; design/80 D-B, plan-gate) is also a **non-terminal,
|
|
1406
|
+
* resumable** outcome, but a DISTINCT one: it is the REVIEW-PAUSE terminal a human/judge must clear. Two
|
|
1407
|
+
* disjoint gate kinds share it (carrying a `reviewRef`, errorCode `"review.pending"`): a `{kind:"needs_review"}`
|
|
1408
|
+
* checkpoint — a profile's dry-run interception produced a predicted state-diff to REVIEW before it is applied,
|
|
1409
|
+
* resumed with a `dry_run_review` outcome — and a `{kind:"plan_review"}` checkpoint (design/80 D-B) — a
|
|
1410
|
+
* profile's plan-gate produced a proposed PLAN a human must approve/edit/reject BEFORE any step runs, resumed
|
|
1411
|
+
* with a `plan_review` outcome. Both are DISJOINT from `"suspended"`: that is a PRE-ACTION approval of a TOOL
|
|
1412
|
+
* CALL (resumed with `policy_ask`); these are human REVIEWS (the distinct gate.kind picks the resume outcome).
|
|
1413
|
+
* Orchestrators that map an unexpected `suspended` should map an unexpected `needs_review` the same
|
|
1414
|
+
* hard-boundary way (it is, like `suspended`, only safe at the top-level `runTask` boundary).
|
|
1415
|
+
*/
|
|
1416
|
+
export type TaskStatus = "completed" | "blocked" | "failed" | "timeout" | "suspended" | "needs_review";
|
|
1417
|
+
/** Result returned when a task finishes or gets stuck. Designed to be machine-readable for an external AI. */
|
|
1418
|
+
export interface TaskResult {
|
|
1419
|
+
taskId: string;
|
|
1420
|
+
/** Use this to continue the same conversation on the next call. */
|
|
1421
|
+
sessionId: string;
|
|
1422
|
+
status: TaskStatus;
|
|
1423
|
+
/** design/99 MF-25: the EFFECTIVE model id that served this task — the RESOLVED `Model.id`, not the requested
|
|
1424
|
+
* `TaskSpec.model` ref (which may be a role / name / `@mention`). Lets a UI echo "served by X" instead of the
|
|
1425
|
+
* requested ref. A mid-run degradation is observed separately (see the degraded-model fields). */
|
|
1426
|
+
model?: string;
|
|
1427
|
+
/** Final assistant text. */
|
|
1428
|
+
result: string;
|
|
1429
|
+
/**
|
|
1430
|
+
* Best-effort salvaged assistant text from a terminal FAILURE (design/39). Lets a caller recover work
|
|
1431
|
+
* a task produced before it failed at the very end, instead of discarding a `failed` result wholesale:
|
|
1432
|
+
* `const out = r.status === "completed" ? r.result : r.salvagedOutput;`. Its interpretation depends on
|
|
1433
|
+
* `errorCode` — for `"output.degenerate"` it is the model's text up to (and currently including) the
|
|
1434
|
+
* looped tail. **v1 fills it only on degenerate repetition**; a follow-up generalizes it to
|
|
1435
|
+
* timeout/max_turns and trims the degenerate tail. Undefined when there was nothing to salvage.
|
|
1436
|
+
*/
|
|
1437
|
+
salvagedOutput?: string;
|
|
1438
|
+
/** Set when status is "blocked": why the agent could not finish. */
|
|
1439
|
+
blockedReason?: string;
|
|
1440
|
+
/**
|
|
1441
|
+
* Set when `status === "suspended"` (design/45) OR `status === "needs_review"` (design/76 §2.5 dry-run /
|
|
1442
|
+
* design/80 D-B plan-gate): the durable-checkpoint token to resume this task with via
|
|
1443
|
+
* `runner.resume(checkpointToken, outcome)` (a `policy_ask` outcome for `suspended`; for `needs_review`, a
|
|
1444
|
+
* `dry_run_review` outcome on a `needs_review` gate or a `plan_review` outcome on a `plan_review` gate —
|
|
1445
|
+
* read `checkpointGate.kind` to pick). Also passed up by an
|
|
1446
|
+
* orchestrator that mapped an unexpected `suspended` to `failed` (errorCode `"unexpected.suspended"`) so the
|
|
1447
|
+
* top-level caller can still resume. Branded `CheckpointToken`; **never log it or put it in a URL** (it is
|
|
1448
|
+
* the resume capability, §6). Undefined for every other status.
|
|
1449
|
+
*/
|
|
1450
|
+
checkpointToken?: import("./checkpoint-store.js").CheckpointToken;
|
|
1451
|
+
/** Set with `checkpointToken`: who/what must resume (e.g. `{kind:"human", reason, toolName}`), so the
|
|
1452
|
+
* caller knows what decision the suspension is awaiting. */
|
|
1453
|
+
checkpointGate?: import("./checkpoint-store.js").CheckpointGate;
|
|
1454
|
+
/** Set when status is "failed"/"timeout". Human-readable. */
|
|
1455
|
+
errorMessage?: string;
|
|
1456
|
+
/**
|
|
1457
|
+
* Machine-readable failure code when the failure carried one — e.g. a `SessionError.code` such as
|
|
1458
|
+
* `"conflict"` (a cross-instance write lost the optimistic lock), or a Node error code. Lets a
|
|
1459
|
+
* caller branch programmatically (e.g. evict a stale cache + retry on `"conflict"`) instead of
|
|
1460
|
+
* matching `errorMessage` strings. Undefined when no code is available.
|
|
1461
|
+
*
|
|
1462
|
+
* 1.37+ terminal codes use a **dotted namespace** so a caller can prefix-match a whole class:
|
|
1463
|
+
* `"budget.precall"` / `"budget.exceeded"` / `"limit.max_turns"` / `"limit.timeout"`
|
|
1464
|
+
* (e.g. `errorCode.startsWith("budget.")`). 1.36 brain codes (`auth`/`network`/`rate_limit`/…)
|
|
1465
|
+
* and `"conflict"` remain flat (unchanged, to avoid breaking existing consumers).
|
|
1466
|
+
*/
|
|
1467
|
+
errorCode?: string;
|
|
1468
|
+
/**
|
|
1469
|
+
* Present when the task was served — at least once — by a **degraded** (cheaper/different) model
|
|
1470
|
+
* because the primary was rate-limited, its circuit breaker was open, or — design/126 chain form —
|
|
1471
|
+
* it failed with a `server_error`/`last_resort` class error (1.39 + design/126, opt-in via
|
|
1472
|
+
* `createDegradingBrain`). Lets a caller know the result was produced at reduced quality and alert/
|
|
1473
|
+
* track it. Records the **first** degradation only (degradation is one-way within a task). Set even
|
|
1474
|
+
* when the fallback also failed — so `status:"failed"` + `degraded` means "primary down, fallback
|
|
1475
|
+
* down too". `reason="budget"` is reserved for the v2 near-budget trigger.
|
|
1476
|
+
*/
|
|
1477
|
+
degraded?: {
|
|
1478
|
+
from: string;
|
|
1479
|
+
to: string;
|
|
1480
|
+
/** design/126 widens the union: `server_error` (5xx/529 escaped the retry budget) and `last_resort`
|
|
1481
|
+
* (404/other non-retryable statuses) — the CC 批 β fallback-chain triggers. Additive on this
|
|
1482
|
+
* OUTPUT field; consumers switching exhaustively should add the two arms. */
|
|
1483
|
+
reason: "breaker_open" | "rate_limit" | "budget" | "server_error" | "last_resort";
|
|
1484
|
+
/** design/126 — the fallback-chain model ids attempted after the primary, in order (absent on the
|
|
1485
|
+
* single-hop legacy path's pre-126 markers and on the budget path). */
|
|
1486
|
+
chain?: string[];
|
|
1487
|
+
/** 1-based turn during which degradation was triggered. Reactive (rate_limit/breaker): the turn the
|
|
1488
|
+
* cheaper model first served. Budget: the turn whose cumulative cost crossed the threshold (the
|
|
1489
|
+
* switch takes effect from the next turn). */
|
|
1490
|
+
atTurn: number;
|
|
1491
|
+
};
|
|
1492
|
+
/** The validated object the model submitted via `submit_output` when `TaskSpec.outputSchema` was set
|
|
1493
|
+
* (1.41). Undefined if the model answered in prose instead, or the task didn't finish via the output
|
|
1494
|
+
* tool. Cast it with `Static<typeof yourSchema>`. (Exhausting the output-retry cap → `failed` +
|
|
1495
|
+
* `errorCode="output.invalid"`, and this stays undefined.) */
|
|
1496
|
+
structuredOutput?: unknown;
|
|
1497
|
+
/**
|
|
1498
|
+
* `turns`/`tokens`/`costUsd` are this task's OWN model usage. `nested` is the summed usage of any
|
|
1499
|
+
* delegated sub-runs (sub-agents) it spawned — present only when it delegated. The true total
|
|
1500
|
+
* cost is `tokens + (nested?.tokens ?? 0)`; a large `nested` is the multi-agent "~15×" made visible.
|
|
1501
|
+
*/
|
|
1502
|
+
stats: {
|
|
1503
|
+
turns: number;
|
|
1504
|
+
tokens: number;
|
|
1505
|
+
/** design/97 CORE-8 (②): total TOOL CALLS executed (one per `tool_start`) — distinct from `turns` (model
|
|
1506
|
+
* rounds; a turn may issue several parallel tool calls). For a CC-style "N tool calls" per-agent row.
|
|
1507
|
+
* **v1 fidelity (audit MINOR)**: counted in THIS run leg via the harness dispatch path, so on a DURABLE
|
|
1508
|
+
* RESUME it under-reports — the resumed gated call (executed by the resume engine, not the harness) and any
|
|
1509
|
+
* cross-slice resource-suspend legs are not folded (turns/tokens/cost ARE folded; toolCalls is per-leg, like
|
|
1510
|
+
* the compaction subtotal). OBSERVE-ONLY (never gates budget). The workflow display is unaffected (its agents
|
|
1511
|
+
* fail-on-suspend, never durably resume). A `spentToolCalls` ledger fold is a follow-on. */
|
|
1512
|
+
toolCalls?: number;
|
|
1513
|
+
/** Total prompt (input) tokens presented across the task's turns, normalized across providers
|
|
1514
|
+
* (Anthropic reports input excluding cache; OpenAI/vLLM include it). The denominator for
|
|
1515
|
+
* `cacheHitRate`. */
|
|
1516
|
+
promptTokens?: number;
|
|
1517
|
+
/** Prompt tokens served from the model's prefix cache (a cache HIT), summed over the task's
|
|
1518
|
+
* turns — when the gateway reports it (vLLM/OpenAI `prompt_tokens_details.cached_tokens`,
|
|
1519
|
+
* DeepSeek `prompt_cache_hit_tokens`, Anthropic `cache_read_input_tokens`). */
|
|
1520
|
+
cachedTokens?: number;
|
|
1521
|
+
/** Prompt tokens written to the cache (Anthropic `cache_creation_input_tokens`); 0 elsewhere. */
|
|
1522
|
+
cacheWriteTokens?: number;
|
|
1523
|
+
/** `cachedTokens / promptTokens` ∈ [0,1] — the prefix-cache hit rate for this task. Cost-critical;
|
|
1524
|
+
* a low value on a multi-turn task means the cacheable prefix is unstable (see `design/09`).
|
|
1525
|
+
* Track it per task and trend it per session. Undefined when the gateway reports no usage. */
|
|
1526
|
+
cacheHitRate?: number;
|
|
1527
|
+
/** Alias of `promptTokens` (the normalized total input incl. cache), named to match OTel
|
|
1528
|
+
* `gen_ai.usage.input_tokens`. Cost is computed from this. (Not a bug fix — `promptTokens` was
|
|
1529
|
+
* already the normalized total; this is the OTel-aligned name. See design/17 §11.5.) */
|
|
1530
|
+
totalInputTokens?: number;
|
|
1531
|
+
/** Completion (output) tokens summed over the task's turns. */
|
|
1532
|
+
outputTokens?: number;
|
|
1533
|
+
/** Cache-write tokens at the 1-hour TTL (Anthropic); 0 unless 1h caching is in use. */
|
|
1534
|
+
cacheWriteTokensLong?: number;
|
|
1535
|
+
/** Authoritative cost in **integer micro-USD** (1e-6 USD), computed in core from injected pricing
|
|
1536
|
+
* — integer to avoid float-accumulation error in billing. Prefer this over the float `costUsd`. */
|
|
1537
|
+
costMicroUsd?: number;
|
|
1538
|
+
/** @deprecated Float USD — accumulation error, and pre-1.37 overstated cache cost. Use
|
|
1539
|
+
* `costMicroUsd`. Kept for back-compat; removed in a later minor. */
|
|
1540
|
+
costUsd?: number;
|
|
1541
|
+
nested?: {
|
|
1542
|
+
tokens: number;
|
|
1543
|
+
turns: number;
|
|
1544
|
+
tasks: number;
|
|
1545
|
+
costUsd?: number;
|
|
1546
|
+
costMicroUsd?: number;
|
|
1547
|
+
};
|
|
1548
|
+
/**
|
|
1549
|
+
* Post-task memory-consolidation usage (design/41), when consolidation ran. Its own line item —
|
|
1550
|
+
* **kept out of `tokens`/`costMicroUsd` and excluded from the budget gate** — so a completed task is
|
|
1551
|
+
* never retroactively flipped to `budget.exceeded` by reconcile cost. `tokens` is 0 when every note
|
|
1552
|
+
* took a cheap (no-LLM) path; `applied` counts store mutations the pass made (cheap-path
|
|
1553
|
+
* UPDATE/DELETE + applied LLM decisions) so callers can observe reconcile efficacy without re-reading
|
|
1554
|
+
* the store. Absent when consolidation was disabled / no-op / produced no notes. Populated
|
|
1555
|
+
* asynchronously (consolidation is fire-and-forget) — see {@link TaskStream.consolidation}.
|
|
1556
|
+
*/
|
|
1557
|
+
memory?: {
|
|
1558
|
+
tokens: number;
|
|
1559
|
+
costMicroUsd: number;
|
|
1560
|
+
applied: number;
|
|
1561
|
+
};
|
|
1562
|
+
/**
|
|
1563
|
+
* design/100 §E12 — the prompt-suggestion pass's usage, when it ran. Same budget-excluded side-observable
|
|
1564
|
+
* treatment as {@link memory}: **kept out of `tokens`/`costMicroUsd` and excluded from the budget gate**, so
|
|
1565
|
+
* the (fire-and-forget, post-completion) suggestion pass can never retroactively flip a done task to
|
|
1566
|
+
* `budget.exceeded`. Absent when `suggestNextPrompts` was off / produced nothing. Populated asynchronously —
|
|
1567
|
+
* see {@link TaskStream.suggestions}.
|
|
1568
|
+
*/
|
|
1569
|
+
suggestions?: {
|
|
1570
|
+
tokens: number;
|
|
1571
|
+
costMicroUsd: number;
|
|
1572
|
+
};
|
|
1573
|
+
/**
|
|
1574
|
+
* TB telemetry B2 (service [397]): counters for the engine's wall-clock/deadline mechanisms, so a
|
|
1575
|
+
* bench/monitoring consumer can judge from the RESULT whether they actually engaged (refute-130
|
|
1576
|
+
* lesson: "did P1/P2 fire" was unanswerable from artifacts). Present only when at least one
|
|
1577
|
+
* mechanism engaged this leg; absent = none did (byte-compatible).
|
|
1578
|
+
*/
|
|
1579
|
+
mechanisms?: {
|
|
1580
|
+
/** design/130 P2: the graceful-finalize instruction was injected this run. */
|
|
1581
|
+
finalizeInjected?: true;
|
|
1582
|
+
/** design/128 T1-2: number of deadline nudges dispatched at turn boundaries. */
|
|
1583
|
+
nudgesSent?: number;
|
|
1584
|
+
/** design/130 P1: number of model calls whose max_tokens was SHRUNK by the wall-clock cap. */
|
|
1585
|
+
capShrinks?: number;
|
|
1586
|
+
/** design/130 P2b: number of model calls the brain CUT at the soft wall-clock deadline
|
|
1587
|
+
* (deliberate stream cancel + prefix salvage — the pre-P2b shape was a mid-call hard kill). */
|
|
1588
|
+
callCutoffs?: number;
|
|
1589
|
+
/** design/130 P2b: number of foreground shell timeouts CLAMPED to the soft tool deadline
|
|
1590
|
+
* (a long command times out cleanly before the write-out window instead of riding past it). */
|
|
1591
|
+
toolClamps?: number;
|
|
1592
|
+
/** design/132: the natural-end final-verification reminder was injected this run. */
|
|
1593
|
+
finalVerifyInjected?: true;
|
|
1594
|
+
/** oracle-grounding gate (opus LOW 复审, additive): HOW MANY final-verification injections
|
|
1595
|
+
* fired this run — 1 = the R9 one-shot only, 2 = R9 + the grounding re-entry (hard cap).
|
|
1596
|
+
* Present iff `finalVerifyInjected` is (the boolean stays for compatibility). */
|
|
1597
|
+
finalVerifyInjections?: number;
|
|
1598
|
+
/** design/133: number of turn-boundary attachments injected this run (todo/task reminders,
|
|
1599
|
+
* changed-files notes, plan-mode re-reminders — each bundled block counts once). */
|
|
1600
|
+
attachmentsInjected?: number;
|
|
1601
|
+
/** Repetition telemetry (clay 2026-07-10, 2e1c161 observability): brain-side degenerate-repetition
|
|
1602
|
+
* stream CUTS this run (each pairs with an `output.degenerate`-classified turn). */
|
|
1603
|
+
repetitionCuts?: number;
|
|
1604
|
+
/** Repetitions that landed in a detection window but were SPARED by a 2e1c161 structural
|
|
1605
|
+
* allowance (code-line shape / divider run) — the raw material for judging the allowance. */
|
|
1606
|
+
repetitionSpared?: number;
|
|
1607
|
+
/** Per-event details (turn + rule + period/reps + a ≤120-char segment sample), capped at 20
|
|
1608
|
+
* entries — `repetitionCuts`/`repetitionSpared` keep the true totals past the cap. */
|
|
1609
|
+
repetitionEvents?: Array<{
|
|
1610
|
+
turn: number;
|
|
1611
|
+
action: "cut" | "spared";
|
|
1612
|
+
rule: "char-run" | "unit-loop";
|
|
1613
|
+
period: number;
|
|
1614
|
+
reps: number;
|
|
1615
|
+
segment: string;
|
|
1616
|
+
}>;
|
|
1617
|
+
};
|
|
1618
|
+
/**
|
|
1619
|
+
* design/91 — **human-review burden** (design/89 §2.4 C2 axis). The wall-clock time a task spent waiting
|
|
1620
|
+
* on a human at an approval gate, plus the count, bucketed by `gate.kind`. Both human-review paths are
|
|
1621
|
+
* captured: the **synchronous** `onAsk`/`resolveAsk` await (`t_return − t_call`) and the **durable**
|
|
1622
|
+
* suspend→resume wait (`resumedAt − checkpoint.suspendedAt`, including the human's offline time); a
|
|
1623
|
+
* multi-leg suspend/resume chain **accumulates across legs**. All timestamps come from {@link RunnerDeps.now}.
|
|
1624
|
+
*
|
|
1625
|
+
* **NOT an LLM cost (load-bearing, design/91 §1):** human-review time is wall-clock latency, not token
|
|
1626
|
+
* spend — it is **NEVER folded into `costMicroUsd`, `costBreakdown`, or the budget gate** (the same
|
|
1627
|
+
* budget-excluded side-observable treatment as {@link memory}). Adding human seconds to token µUSD is the
|
|
1628
|
+
* design/89 §2.1 "apples + oranges" trap; the supervisor Pareto frontier keeps `(token cost, human seconds,
|
|
1629
|
+
* correctness)` as three SEPARATE axes. Absent (`undefined`) when the task hit no approval gate OR no clock
|
|
1630
|
+
* is injectable to measure — byte-compatible with a task that never paused for a human.
|
|
1631
|
+
*/
|
|
1632
|
+
humanReview?: {
|
|
1633
|
+
/** Number of human decisions awaited (each synchronous `resolveAsk` return + each durable resume of an
|
|
1634
|
+
* approval suspend). Equals `gates.length`. */
|
|
1635
|
+
count: number;
|
|
1636
|
+
/** Cumulative wall-clock the approval gates were alive (ms), summed across all legs. Equals `Σ gates[].waitMs`. */
|
|
1637
|
+
totalWaitMs: number;
|
|
1638
|
+
/** One entry per human decision, in order. `kind` = the gate's discriminant (`human` /
|
|
1639
|
+
* `irreversible_ask` for durable; `human` for a synchronous ask). `decision` = the adjudication when
|
|
1640
|
+
* known (`allow`/`deny`). design/99 MF-24 (Service AI [297]): `toolName` = the gated tool; `toolArg` = a
|
|
1641
|
+
* SHORT, SECRET-SCRUBBED one-line summary of its input (the same `primaryActivityArg` boundary as the MF-W
|
|
1642
|
+
* activity arg) — the permission-denial ledger's "denied: Bash(rm …)" display. `toolArg` is set on the
|
|
1643
|
+
* SYNCHRONOUS-ask path (the input is in scope); a durable-resume gate carries `toolName` only (its input is
|
|
1644
|
+
* not threaded onto the persisted gate — a documented follow-on). */
|
|
1645
|
+
gates: Array<{
|
|
1646
|
+
kind: string;
|
|
1647
|
+
waitMs: number;
|
|
1648
|
+
decision?: string;
|
|
1649
|
+
toolName?: string;
|
|
1650
|
+
toolArg?: string;
|
|
1651
|
+
}>;
|
|
1652
|
+
};
|
|
1653
|
+
/**
|
|
1654
|
+
* design/80 D-E-core: a thin FINANCE TAXONOMY of the LLM-derived costs the engine actually prices,
|
|
1655
|
+
* decomposing the task's spend into report categories (derived from existing cost sources — no new
|
|
1656
|
+
* persisted structure). **CORE = LLM-token-derived ONLY** — the deployment SERVICE adds the infra axes it
|
|
1657
|
+
* owns (tool-call / sandbox-walltime / egress; it has the k8s cost data) and composes them with this for
|
|
1658
|
+
* the supervisor surface. Each category is ≥ 0 and the LLM parts reconcile to the independently-summed
|
|
1659
|
+
* LLM total: `llmRootMicroUsd + nestedSubagentMicroUsd + compactionMicroUsd === costMicroUsd`
|
|
1660
|
+
* (`memoryConsolidationMicroUsd` is a separate, budget-excluded line — see `memory` — filled
|
|
1661
|
+
* asynchronously after consolidation, so it is NOT part of that identity). Present whenever stats are
|
|
1662
|
+
* assembled.
|
|
1663
|
+
*/
|
|
1664
|
+
costBreakdown?: {
|
|
1665
|
+
/** Root-agent LLM cost (micro-USD) = `costMicroUsd − compactionMicroUsd` (the sub-category folded into
|
|
1666
|
+
* it). NOT minus nested — nested cost is never folded into `costMicroUsd` (it lands in `nested`).
|
|
1667
|
+
* ⚠️ APPROXIMATE on a multi-slice `resource_limit` RESUME (design/80 D-E-core, codex review #3): the
|
|
1668
|
+
* durable resource ledger persists only the AGGREGATE prior spend, not its compaction subtotal, so
|
|
1669
|
+
* prior slices' compaction folds in HERE rather than into `compactionMicroUsd`. The TOTAL (`costMicroUsd`)
|
|
1670
|
+
* stays exact; only this llmRoot-vs-compaction split is per-leg-approximate across resource slices. */
|
|
1671
|
+
llmRootMicroUsd: number;
|
|
1672
|
+
/** Delegated sub-agent (nested) LLM cost (micro-USD) = `nested?.costMicroUsd ?? 0`. */
|
|
1673
|
+
nestedSubagentMicroUsd: number;
|
|
1674
|
+
/** Post-task memory-consolidation LLM cost (micro-USD) = `memory?.costMicroUsd ?? 0`; filled
|
|
1675
|
+
* asynchronously after the consolidation pass (0 until then). A separate, budget-excluded line. */
|
|
1676
|
+
memoryConsolidationMicroUsd: number;
|
|
1677
|
+
/** design/100 §E12 — prompt-suggestion pass LLM cost (micro-USD) = `suggestions?.costMicroUsd ?? 0`; filled
|
|
1678
|
+
* asynchronously after the (post-completion) pass (0 until then). A separate, budget-excluded line. */
|
|
1679
|
+
suggestionsMicroUsd?: number;
|
|
1680
|
+
/** Within-task compaction LLM cost (micro-USD) — part of `costMicroUsd`, so subtracted from root.
|
|
1681
|
+
* ⚠️ See {@link llmRootMicroUsd}: under-reports prior slices' compaction on a multi-slice resource resume. */
|
|
1682
|
+
compactionMicroUsd: number;
|
|
1683
|
+
};
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
/**
|
|
1687
|
+
* Identity fields carried by every CONTENT event of a task stream (design/99 §E2 — lightweight message
|
|
1688
|
+
* identity, service [241]/[242]). Both are OPTIONAL and ADDITIVE; a consumer that ignores them is unchanged.
|
|
1689
|
+
*
|
|
1690
|
+
* - `eventId` — a core-minted, time-sortable (uuidv7) unique id stamped on each emitted content event. Gives
|
|
1691
|
+
* a live UI a stable handle to correlate/dedup streamed events and to map its own client-side message ids
|
|
1692
|
+
* back to a core anchor. (The durable-anchor mapping for resume-at — which eventIds are restartable
|
|
1693
|
+
* transcript positions — is finalized by the E18 `resumeAt` seam; this field is the stable handle it builds on.)
|
|
1694
|
+
* - `parentToolCallId` — present ONLY when this task runs as a sub-agent spawned under a parent task's tool
|
|
1695
|
+
* call (threaded via the trusted `RunInternals.parentToolCallId`, sourced from the spawning tool's
|
|
1696
|
+
* `ToolExecuteContext.toolCallId`). Lets a consumer attribute streamed content to the delegation subtree it
|
|
1697
|
+
* belongs to WITHOUT core physically merging the child stream into the parent (the child's RESULT still
|
|
1698
|
+
* re-enters the parent MODEL context only through the `delimitUntrusted` fence — observability threading and
|
|
1699
|
+
* model-context isolation are kept separate, so prompt-cache and the injection boundary are untouched).
|
|
1700
|
+
*/
|
|
1701
|
+
export interface TaskEventIdentity {
|
|
1702
|
+
eventId?: string;
|
|
1703
|
+
parentToolCallId?: string;
|
|
1704
|
+
/**
|
|
1705
|
+
* design/122 S2 (codex-M4 name: the `WorkflowRun.sourceTaskId` family, NOT a second `taskId` — that
|
|
1706
|
+
* field already exists on `task_progress` and a duplicate would bite consumers) — the ORIGINATING task's
|
|
1707
|
+
* canonical id (`spec.taskId ?? sessionId`), stamped ONLY on the content events of a task running AS A
|
|
1708
|
+
* SUB-AGENT (same condition as {@link parentToolCallId}). A consumer of the C1 forward channel
|
|
1709
|
+
* (`forwardSubagentEvents`) can key a child's content events by the child task directly, without an
|
|
1710
|
+
* alias table. A TOP-LEVEL task's own events carry NO `sourceTaskId` (absent = the consumer's current
|
|
1711
|
+
* task). Additive; a consumer that ignores it is unchanged.
|
|
1712
|
+
*/
|
|
1713
|
+
sourceTaskId?: string;
|
|
1714
|
+
}
|
|
1715
|
+
/**
|
|
1716
|
+
* design/99 §E3/§E10 (service [241]/[242]) — a BRAIN-LAYER liveness phase, surfaced so a UI can show why a
|
|
1717
|
+
* turn is stalled (the brain otherwise absorbs these silently in its connect/retry loop). Provider-NEUTRAL:
|
|
1718
|
+
* carries only the graduated phase + a neutral hint, NEVER an HTTP status / provider taxonomy / stop_reason.
|
|
1719
|
+
* A CLOSED union (type-safe) covering the core brain layer; a deployment that surfaces its OWN states
|
|
1720
|
+
* (e.g. E25 token-refresh `authenticating`) does so on its own channel, not by widening this.
|
|
1721
|
+
*/
|
|
1722
|
+
export type BrainStatusPhase = "rate_limited" | "retrying" | "reconnecting" | "circuit_open";
|
|
1723
|
+
/** design/99 §E3/§E10 — the payload of a {@link TaskEvent} `status` event (and the brain→runner signal). */
|
|
1724
|
+
export interface BrainStatus {
|
|
1725
|
+
phase: BrainStatusPhase;
|
|
1726
|
+
/** Optional neutral, human-readable hint (NO provider/HTTP detail). */
|
|
1727
|
+
detail?: string;
|
|
1728
|
+
/** Seconds until the brain's next retry attempt (from the honored backoff / `Retry-After`), when known. */
|
|
1729
|
+
retryInSec?: number;
|
|
1730
|
+
}
|
|
1731
|
+
/**
|
|
1732
|
+
* design/97 CORE-8 (③): one lightweight TOOL-ACTIVITY beat surfaced from a running task, for a per-agent live
|
|
1733
|
+
* "last N tool calls" drill-down. A trusted run-scoped sink ({@link RunInternals.onActivity}) receives one at
|
|
1734
|
+
* each tool start + end. Structural (name/phase/ids) + a SHORT redacted primary `arg` for display — NOT the full
|
|
1735
|
+
* ARGS or OUTPUT (those carry untrusted/host data; the workflow layer surfaces redacted prompt/output separately).
|
|
1736
|
+
*/
|
|
1737
|
+
export interface ToolActivity {
|
|
1738
|
+
phase: "start" | "end";
|
|
1739
|
+
toolCallId: string;
|
|
1740
|
+
toolName: string;
|
|
1741
|
+
/** design/99 MF-W: a SHORT primary-arg summary for the monitor's `Read(path)` / `Bash(grep …)` display — the
|
|
1742
|
+
* single most salient input ABBREVIATED (command→name, path→basename, url→origin+path) + SECRET-SCRUBBED +
|
|
1743
|
+
* truncated (~80 code points). Set on `phase: "start"`. NOT the full args object, and NOT `redactHostLeaks`
|
|
1744
|
+
* (that over-redacts the path the monitor needs); the abbreviation + scrub is the leak boundary since the value
|
|
1745
|
+
* is persisted + SSE-forwarded (codex-reviewed). See `primaryActivityArg`. */
|
|
1746
|
+
arg?: string;
|
|
1747
|
+
/** Set on `phase: "end"` — whether the tool call errored. */
|
|
1748
|
+
isError?: boolean;
|
|
1749
|
+
}
|
|
1750
|
+
/** Streaming events surfaced from a running task (for live UIs). */
|
|
1751
|
+
export type TaskEvent = ({
|
|
1752
|
+
type: "text_delta";
|
|
1753
|
+
delta: string;
|
|
1754
|
+
} & TaskEventIdentity) | ({
|
|
1755
|
+
type: "reasoning_delta";
|
|
1756
|
+
delta: string;
|
|
1757
|
+
} & TaskEventIdentity) | ({
|
|
1758
|
+
type: "tool_start";
|
|
1759
|
+
toolCallId: string;
|
|
1760
|
+
toolName: string; /** {@link ToolSpec.label} when distinct from `toolName` (design/71 liveness); omitted otherwise. */
|
|
1761
|
+
label?: string;
|
|
1762
|
+
args: unknown;
|
|
1763
|
+
} & TaskEventIdentity) | ({
|
|
1764
|
+
type: "tool_end";
|
|
1765
|
+
toolCallId: string;
|
|
1766
|
+
toolName: string;
|
|
1767
|
+
/** {@link ToolSpec.label} when distinct from `toolName` (design/71 liveness); omitted otherwise. */
|
|
1768
|
+
label?: string;
|
|
1769
|
+
isError: boolean;
|
|
1770
|
+
/**
|
|
1771
|
+
* design/99 §E1 (service [241]/[242]) — the tool's MODEL-FACING result content, surfaced for a live UI
|
|
1772
|
+
* that renders tool output. It is the harness `AgentToolResult.content` the mapper already produced
|
|
1773
|
+
* (previously dropped here); the internal `details` payload is NOT exposed (e.g. a sub-agent tool's
|
|
1774
|
+
* `details` is the entire child `TaskResult`).
|
|
1775
|
+
*
|
|
1776
|
+
* **Type is `unknown` and intentionally non-uniform** — within size it passes through AS-IS to keep
|
|
1777
|
+
* structure a UI wants (a `string`, or `(TextContent|ImageContent)[]` blocks); when the serialized body
|
|
1778
|
+
* exceeds the core size cap it degrades to a single TRUNCATED STRING (see {@link truncated}). A consumer
|
|
1779
|
+
* must handle both shapes.
|
|
1780
|
+
*
|
|
1781
|
+
* **UNTRUSTED RAW + for OBSERVABILITY ONLY**: it is external tool output (file reads, shell stderr, API
|
|
1782
|
+
* bodies) and may carry secrets/paths/PII — core bounds only its SIZE; a consumer MUST redact and MAY
|
|
1783
|
+
* further bound before it persists or displays it (same contract as `tool_start.args`). It is for a live
|
|
1784
|
+
* UI / trace, NOT for re-feeding to a model: a truncated body would mislead an LLM, and the model already
|
|
1785
|
+
* has the full, untruncated result in its own context — build model prompts from the session, never by
|
|
1786
|
+
* replaying this field. Absent when the tool produced no content body.
|
|
1787
|
+
*/
|
|
1788
|
+
output?: unknown;
|
|
1789
|
+
/**
|
|
1790
|
+
* design/116 [363] channel (b) — the tool's CC-shaped `toolUseResult` facts (`details.type` ∈ the
|
|
1791
|
+
* known card set: edit/create/update/bash/text/grep/glob/notebook-edit/mcp/multiedit), surfaced on
|
|
1792
|
+
* the live wire so a CC-faithful shell renders rich cards (red/green diff, stdout panes, file cards)
|
|
1793
|
+
* without re-parsing the model-facing string. Absent when the tool carries no CC card shape (a
|
|
1794
|
+
* subagent's child TaskResult is deliberately NOT exposed — the allowlist is the leak boundary) or
|
|
1795
|
+
* when the serialized card exceeds the size bound (omitted whole; a consumer falls back to `output`).
|
|
1796
|
+
* UNTRUSTED RAW like {@link output}: a consumer MUST redact before persisting or forwarding.
|
|
1797
|
+
*
|
|
1798
|
+
* **双面契约(CC 2.1.207 @765495 成文,`tool_use_result` describe;CC207-CORE-SWEEP P2-3)** — a tool
|
|
1799
|
+
* result has TWO faces that never substitute for each other:
|
|
1800
|
+
* - **模型面** = {@link output} / the tool_result text: the string the MODEL reads. It may carry
|
|
1801
|
+
* model-directed framing — e.g. a delegation tool's trailer (agentId / usage lines the model uses to
|
|
1802
|
+
* address SendMessage or budget itself). That framing is FOR THE MODEL; it is not a host data format.
|
|
1803
|
+
* - **宿主面** = this field: the tool's structured Output object, per-tool shaped, keyed by the matching
|
|
1804
|
+
* tool call's name. For a delegation/Agent-family tool the completed shape is the subagent's final
|
|
1805
|
+
* report WITHOUT the model-directed trailer, plus run totals (CC names it `AgentToolCompletedOutput`).
|
|
1806
|
+
* A host/shell MUST render from `structured` and MUST NOT parse the model-facing text back into data
|
|
1807
|
+
* (trailer wording is model-audience prose and may change without notice); symmetrically, core never
|
|
1808
|
+
* strips the trailer from the model face just because the structured face exists — the model still needs
|
|
1809
|
+
* it in-context. When `structured` is absent, the honest fallback is to display `output` as opaque text,
|
|
1810
|
+
* not to scrape it.
|
|
1811
|
+
*/
|
|
1812
|
+
structured?: unknown;
|
|
1813
|
+
/**
|
|
1814
|
+
* design/99 §E1 — `true` when {@link output} was SIZE-bounded by core (the full body exceeded the cap and
|
|
1815
|
+
* was degraded to a truncated string). Lets a consumer detect truncation programmatically instead of
|
|
1816
|
+
* parsing the `…[+N chars truncated]` marker out of the string. Absent/false = `output` is the complete
|
|
1817
|
+
* content body. (The full untruncated result still lives in the model's context / `ToolResultStore`.)
|
|
1818
|
+
*/
|
|
1819
|
+
truncated?: boolean;
|
|
1820
|
+
} & TaskEventIdentity) | ({
|
|
1821
|
+
type: "turn_end";
|
|
1822
|
+
/**
|
|
1823
|
+
* Per-turn token usage + cost (the turn that just ended), for live per-turn accounting / a trace UI
|
|
1824
|
+
* (service [41]). Re-priced in core from injected pricing (authoritative, like `TaskResult.stats`).
|
|
1825
|
+
* `inputTokens` is the normalized total input incl. cache (matches `stats.promptTokens` / the tracer's
|
|
1826
|
+
* `brain.call.promptTokens`). Absent only if the turn produced no assistant usage.
|
|
1827
|
+
*/
|
|
1828
|
+
usage?: {
|
|
1829
|
+
inputTokens: number;
|
|
1830
|
+
outputTokens: number;
|
|
1831
|
+
cacheReadTokens: number;
|
|
1832
|
+
cacheWriteTokens: number;
|
|
1833
|
+
costMicroUsd: number;
|
|
1834
|
+
};
|
|
1835
|
+
/** TB 尸检 T1-5: set when the turn ended WITHOUT a provider usage frame (e.g. a degenerate-repetition
|
|
1836
|
+
* cutoff cancelled the stream before usage arrived). Consumers must treat the missing usage as
|
|
1837
|
+
* UNKNOWN — not zero (the provider still served the request; `stats` under-counts it honestly rather
|
|
1838
|
+
* than polluting the single-source accounting with an estimate). */
|
|
1839
|
+
usageMissing?: true;
|
|
1840
|
+
/** TB telemetry B1 (service [397]): the NORMALIZED finish reason of the turn's LAST model call —
|
|
1841
|
+
* the engine's `AssistantMessage.stopReason` (`StopReason`: `"stop"`/`"length"`/`"toolUse"`/
|
|
1842
|
+
* `"error"`/`"aborted"`). This is post-normalization: e.g. Anthropic `end_turn`/`stop_sequence`
|
|
1843
|
+
* both fold to `"stop"`, `max_tokens`→`"length"`; the raw provider reason is NOT preserved here.
|
|
1844
|
+
* The machine signal for "was this turn cut by max_tokens" (`"length"`) — previously stream+trace
|
|
1845
|
+
* double-blind, which made P1 cap-binding unjudgeable from artifacts. Absent when the turn produced
|
|
1846
|
+
* no assistant message. Typed `string` (not the internal `StopReason`) to keep the engine's union
|
|
1847
|
+
* private, but the value set is exactly those five tokens. */
|
|
1848
|
+
stopReason?: string;
|
|
1849
|
+
} & TaskEventIdentity) | {
|
|
1850
|
+
/** design/99 MF-18: a compaction boundary (or, since design/119 #1, mid-turn when the prompt-too-long recovery force-compacts between a failed request and its retry). `trigger` = what caused it: `"auto"` (the context-threshold
|
|
1851
|
+
* auto-compaction) or `"manual"` (the `TaskStream.compact` / `/compact` path). `tokensBefore` = the
|
|
1852
|
+
* pre-compaction context size. CC parity = `SDKCompactBoundary{trigger, pre_tokens, preserved_segment}`. */
|
|
1853
|
+
type: "compacted";
|
|
1854
|
+
trigger: "auto" | "manual";
|
|
1855
|
+
tokensBefore: number;
|
|
1856
|
+
/** TB telemetry B4 (service [397]): post-compaction context size in the TRIGGER-GATE coordinate
|
|
1857
|
+
* (`postTriggerTokens` = estimate + anchor-less overhead). Pairs with {@link triggerTokensBefore}
|
|
1858
|
+
* — NOT with `tokensBefore` (which is the CC `pre_tokens` value in prepareCompaction's coordinate,
|
|
1859
|
+
* lacking the overhead term; subtracting across the two coordinates would mis-state the delta,
|
|
1860
|
+
* the audit-B-1 / P-13 class). Absent when the post measurement failed (best-effort, never fails a
|
|
1861
|
+
* successful compaction). */
|
|
1862
|
+
tokensAfter?: number;
|
|
1863
|
+
/** TB telemetry B4: pre-compaction size in the SAME trigger-gate coordinate as {@link tokensAfter}
|
|
1864
|
+
* (`triggerTokens` — the exact quantity the compaction gate compared). `triggerTokensBefore −
|
|
1865
|
+
* tokensAfter` is the self-consistent freed delta. Absent on the legacy emitter. */
|
|
1866
|
+
triggerTokensBefore?: number;
|
|
1867
|
+
/** TB telemetry B4: wall time of the whole compaction pass (summary call included) — what the
|
|
1868
|
+
* boundary pause actually cost. Absent on legacy emitters. */
|
|
1869
|
+
durationMs?: number;
|
|
1870
|
+
/** CC `SDKCompactBoundary.preserved_segment` parity: `firstKeptEntryId` is the session-tree entry id where
|
|
1871
|
+
* the surviving KEPT TAIL begins after this compaction. A consumer maps it to a wire message via the
|
|
1872
|
+
* `entryId` carried on `message_committed` (message-identity Phase 1) — render the compaction divider just
|
|
1873
|
+
* before that message + relink the preserved tail. (The eventId↔entryId side map service keeps for resumeAt
|
|
1874
|
+
* also resolves it, but is no longer required.) Absent on a compaction that reported no kept-tail floor. */
|
|
1875
|
+
preserved_segment?: {
|
|
1876
|
+
firstKeptEntryId: string;
|
|
1877
|
+
};
|
|
1878
|
+
/** Blackboard 2026-07-03 (CC post-compact file-restore parity): the working files the engine
|
|
1879
|
+
* re-read into the summary (attachWorkingFiles), attachment order. A shell renders CC's
|
|
1880
|
+
* `Read {path} (…)` cards under the compaction divider from this. Absent when the feature is
|
|
1881
|
+
* off or nothing was attached. `truncated` = the content was clipped at the per-file cap. */
|
|
1882
|
+
attachedFiles?: Array<{
|
|
1883
|
+
path: string;
|
|
1884
|
+
chars: number;
|
|
1885
|
+
truncated: boolean;
|
|
1886
|
+
}>;
|
|
1887
|
+
} | ({
|
|
1888
|
+
/**
|
|
1889
|
+
* TB telemetry B3 (service [397]): the engine injected a SYSTEM steering message (a deadline nudge
|
|
1890
|
+
* or the design/130 P2 graceful-finalize instruction) into the model's next turn. Previously these
|
|
1891
|
+
* went through `harness.steer()` with no stream echo — a consumer literally could not tell whether
|
|
1892
|
+
* the finalize fired (the refute-130 attribution blind spot). Echo only; the model-facing message
|
|
1893
|
+
* is unchanged. `preview` is the injected text clipped to a display bound.
|
|
1894
|
+
*
|
|
1895
|
+
* design/133 (LOW-11/F11): the turn-boundary attachment producers ride the same echo — sources
|
|
1896
|
+
* `todo_reminder` / `task_reminder` / `changed_files` / `plan_mode` and the G1 [482]/续批 members
|
|
1897
|
+
* `background_tasks` / `tools_delta` / `agent_listing` / `mcp_instructions` (one event per
|
|
1898
|
+
* attachment; a multi-attachment boundary still coalesces into ONE steer message on the model lane).
|
|
1899
|
+
*/
|
|
1900
|
+
type: "steering_injected";
|
|
1901
|
+
source: "deadline_nudge" | "finalize" | "todo_reminder" | "task_reminder" | "changed_files" | "plan_mode" | "budget_usd" | "background_tasks" | "tools_delta" | "agent_listing" | "mcp_instructions";
|
|
1902
|
+
preview: string;
|
|
1903
|
+
} & TaskEventIdentity) | ({
|
|
1904
|
+
/**
|
|
1905
|
+
* design/121 (CC 198 `<new-diagnostics>` parity): NEW LSP diagnostics that appeared after the
|
|
1906
|
+
* agent's edits, drained at a turn boundary. The SAME data was injected into the model as a
|
|
1907
|
+
* `<new-diagnostics>` context message; this frame is the shell's render source (CC's collapsed
|
|
1908
|
+
* `Found N new diagnostic issues in M files (ctrl+o to expand)` row). UNTRUSTED RAW (language-
|
|
1909
|
+
* server output over workspace files) — a consumer redacts/bounds before persisting (§E1).
|
|
1910
|
+
*/
|
|
1911
|
+
type: "diagnostics";
|
|
1912
|
+
files: Array<{
|
|
1913
|
+
uri: string;
|
|
1914
|
+
diagnostics: Array<{
|
|
1915
|
+
message: string;
|
|
1916
|
+
/** LSP severity: 1=Error 2=Warning 3=Information 4=Hint. */
|
|
1917
|
+
severity?: number;
|
|
1918
|
+
range?: {
|
|
1919
|
+
start: {
|
|
1920
|
+
line: number;
|
|
1921
|
+
character: number;
|
|
1922
|
+
};
|
|
1923
|
+
end?: {
|
|
1924
|
+
line: number;
|
|
1925
|
+
character: number;
|
|
1926
|
+
};
|
|
1927
|
+
};
|
|
1928
|
+
code?: string | number;
|
|
1929
|
+
source?: string;
|
|
1930
|
+
}>;
|
|
1931
|
+
}>;
|
|
1932
|
+
isNew: true;
|
|
1933
|
+
} & TaskEventIdentity) | ({
|
|
1934
|
+
/**
|
|
1935
|
+
* message-identity Phase 1 (the CC `SDKCompactBoundary` parity enabler): a persisted session-tree entry was
|
|
1936
|
+
* just COMMITTED for a RENDERABLE message the consumer has already streamed. `entryId` = `SessionTreeEntry.id`
|
|
1937
|
+
* (uuidv7, persisted, replica-stable) — the SAME id space as `compacted.preserved_segment.firstKeptEntryId`,
|
|
1938
|
+
* E18 `resumeAt`, and E19 `rewindFiles`. `role` + (for a tool result) `toolCallId` let a consumer bind it to
|
|
1939
|
+
* the message it rendered: a tool result by its `toolCallId`; an assistant/user message by stream order (this
|
|
1940
|
+
* is the terminal boundary for the content just streamed, after its deltas and before its tool results). A
|
|
1941
|
+
* consumer builds its own `entryId → message` map from these to resolve `preserved_segment` WITHOUT the
|
|
1942
|
+
* eventId↔entryId side map. Terminal per-message boundary; additive + ignorable. ABSENT for a message that did
|
|
1943
|
+
* not persist (an empty-failure assistant) and for non-message entries (a compaction summary / model_change —
|
|
1944
|
+
* never a `message_committed`). The engine still holds no eventId→entryId map (the deployment owns it); this
|
|
1945
|
+
* only pushes the persisted id onto the wire, the constitution's primitive/profile split (cf. §E2 `eventId`).
|
|
1946
|
+
*/
|
|
1947
|
+
type: "message_committed";
|
|
1948
|
+
entryId: string;
|
|
1949
|
+
role: "user" | "assistant" | "toolResult";
|
|
1950
|
+
/** Present iff `role === "toolResult"`: the exact join key to the `tool_start`/`tool_end` already rendered. */
|
|
1951
|
+
toolCallId?: string;
|
|
1952
|
+
} & TaskEventIdentity) | ({
|
|
1953
|
+
/**
|
|
1954
|
+
* design/99 §E3/§E10 (service [241]/[242]) — a live BRAIN-LAYER status the brain would otherwise absorb
|
|
1955
|
+
* silently (a 429 rate-limit / a 5xx or network retry / a reconnect / an open circuit breaker). Emitted
|
|
1956
|
+
* the moment the brain decides to wait/retry, carrying the graduated {@link BrainStatusPhase} + an
|
|
1957
|
+
* optional `retryInSec` so a UI can show "rate limited, retrying in Ns". EPHEMERAL — a pure liveness
|
|
1958
|
+
* signal, never persisted or replayed on resume. Provider-neutral (no HTTP status / stop_reason).
|
|
1959
|
+
* SCOPE: reflects THIS task's own (top-level) brain calls. A delegated sub-agent's brain liveness routes
|
|
1960
|
+
* to the SUB-AGENT's own stream (isolated, like every child event — §E2); a background internal brain
|
|
1961
|
+
* call (memory recall/consolidation) is intentionally not surfaced.
|
|
1962
|
+
*/
|
|
1963
|
+
type: "status";
|
|
1964
|
+
} & BrainStatus & TaskEventIdentity) | ({
|
|
1965
|
+
/**
|
|
1966
|
+
* design/115 P2 core slice — SDK-side projection of a background task terminal notification. The model-facing
|
|
1967
|
+
* projection is the sibling `<task-notification>` XML injected through the runner's system-injection lane when
|
|
1968
|
+
* the originating harness is still running; durable idle wake/resume is a deployment transport concern.
|
|
1969
|
+
*/
|
|
1970
|
+
type: "task_notification";
|
|
1971
|
+
notification: TaskNotificationPayload;
|
|
1972
|
+
} & TaskEventIdentity) | ({
|
|
1973
|
+
/**
|
|
1974
|
+
* design/99 MF-10 (Service AI [297]) — a SUBAGENT PROGRESS TICK: the delegated sub-run's usage ACCRUING
|
|
1975
|
+
* over time, emitted at each turn boundary WHILE it runs, so a parent UI animates the Task card's rollup
|
|
1976
|
+
* (tokens/tool-uses climbing). Emitted ONLY for a subagent (a task with `parentToolCallId`); a top-level
|
|
1977
|
+
* run's own usage is the consumer's own. `status:"running"` mid-run; the terminal usage is the `done` result.
|
|
1978
|
+
* Live/ephemeral — NOT persisted (a resumable trace re-derives usage from the result), like `status`.
|
|
1979
|
+
* Maps to CC `SDKTaskProgress` (camelCase here → snake_case `task_id`/`total_tokens`/`tool_uses`/`duration_ms`
|
|
1980
|
+
* at the SDK/service projection, the same convention as `toolCallId`→`tool_use_id`).
|
|
1981
|
+
*/
|
|
1982
|
+
type: "task_progress";
|
|
1983
|
+
taskId: string;
|
|
1984
|
+
/** design/99 (nested-subagent live tree): the spawning run's taskId — present on a DEEPER-than-1 subagent tick
|
|
1985
|
+
* (a subagent spawned by another subagent), forwarded via `RunInternals.onForwardEvent` so a UI nests the
|
|
1986
|
+
* node directly (this.taskId under parentTaskId) without mapping `parentToolCallId` → owner. The top-level
|
|
1987
|
+
* run is known to the consumer; its direct children carry the top's taskId here. Absent on a top-level tick. */
|
|
1988
|
+
parentTaskId?: string;
|
|
1989
|
+
/** design/99 BC-2 (Service AI [§I]): a short, single-line HUMAN display name for the subagent — its explicit
|
|
1990
|
+
* `taskName` or the selected agent-type. So a Fleet child row shows a readable label instead of the raw
|
|
1991
|
+
* `taskId` (the stable row identity stays the taskId). ABSENT when the subagent carries neither a taskName
|
|
1992
|
+
* nor an agent-type — the child then keeps its taskId (NOT the raw objective, which could leak a delegated
|
|
1993
|
+
* secret to a progress-scoped consumer — dual-review Q2). Sanitized (control-char-stripped, length-capped). */
|
|
1994
|
+
name?: string;
|
|
1995
|
+
/** 黑板 [583] (#64 接线实证): the child's most recent tool intent as one human line ("Bash npm test",
|
|
1996
|
+
* "Edit src/x.ts") — the SAME source/value as the registry sink tick's `currentAction` (黑板 [558] B),
|
|
1997
|
+
* attached to the FORWARDED frame because every client wire projects this TaskEvent, not the sink
|
|
1998
|
+
* (service's three projection legs saw a permanently-absent field before this). UNTRUSTED display
|
|
1999
|
+
* hint — redact at the projection boundary (service [579]②). Absent until the child runs a tool. */
|
|
2000
|
+
currentAction?: string;
|
|
2001
|
+
usage: {
|
|
2002
|
+
totalTokens: number;
|
|
2003
|
+
toolUses: number;
|
|
2004
|
+
durationMs: number;
|
|
2005
|
+
};
|
|
2006
|
+
status: "running";
|
|
2007
|
+
} & TaskEventIdentity) | ({
|
|
2008
|
+
/**
|
|
2009
|
+
* design/99 §E13 (service [241]/[242]) — the task's tracked working directory CHANGED mid-run (a `bash`
|
|
2010
|
+
* `cd` moved it). Emitted live after the tool that moved it, carrying the new logical cwd, so a shell UI
|
|
2011
|
+
* can update its prompt/path display. The tracked cwd is the RAW logical path (a `cd` through a symlink
|
|
2012
|
+
* reports the raw path navigated, not the resolved target). Only fires when a real shell is mounted
|
|
2013
|
+
* (absent under `handsReadOnly` / no-exec). The initial cwd is NOT announced (it is the known root); only
|
|
2014
|
+
* subsequent changes are. A live observability signal — not persisted, and the tracked cwd RESETS to the
|
|
2015
|
+
* root across a suspend/resume (the per-leg execution cwd is not durable today — a pre-existing limitation
|
|
2016
|
+
* tracked with the E18/E19 execution-state durability work); within a leg, every `cd` move is reported.
|
|
2017
|
+
*/
|
|
2018
|
+
type: "workspace_changed";
|
|
2019
|
+
cwd: string;
|
|
2020
|
+
} & TaskEventIdentity) | {
|
|
2021
|
+
type: "done";
|
|
2022
|
+
result: TaskResult;
|
|
2023
|
+
};
|
|
2024
|
+
/**
|
|
2025
|
+
* Outcome of a manual {@link TaskStream.compact} request (blackboard [496]③ — the enum names align with
|
|
2026
|
+
* the diagnosis decision tree's drain exits, so a consumer can tell "202 processed" states apart):
|
|
2027
|
+
* - `"compacted"` — a compaction landed at the boundary (the `compacted{trigger:"manual"}` event fired).
|
|
2028
|
+
* - `"failed"` — the attempt ran and threw (summarizer failure / empty summary / oversized summary;
|
|
2029
|
+
* `compaction.failed` trace frame + `Runner.onError(phase:"compaction")`), or the §17.4 breaker was
|
|
2030
|
+
* already open so the request was drained without an attempt (`compaction.failed` frame, no attempt).
|
|
2031
|
+
* - `"mooted"` — the request was processed but the run could no longer compact (dying loop: abort /
|
|
2032
|
+
* durable suspend / plan review in flight), or the task settled before any boundary arrived.
|
|
2033
|
+
* - `"noop"` — the attempt ran but there was nothing to compact (no valid cut point / empty history).
|
|
2034
|
+
* - `"blocked"` — a `preCompact` hook deliberately blocked this compaction (not a failure).
|
|
2035
|
+
* - `"disabled"` — compaction is disabled by the task spec (`compaction.enabled: false`).
|
|
2036
|
+
*/
|
|
2037
|
+
export type CompactOutcome = "compacted" | "failed" | "mooted" | "noop" | "blocked" | "disabled";
|
|
2038
|
+
/** A running task you can iterate for live events and await for the final result. */
|
|
2039
|
+
export interface TaskStream extends AsyncIterable<TaskEvent> {
|
|
2040
|
+
result(): Promise<TaskResult>;
|
|
2041
|
+
/**
|
|
2042
|
+
* Resolves when the post-task memory-consolidation pass (design/41) settles — or immediately when none
|
|
2043
|
+
* ran. Consolidation is **fire-and-forget**: `result()`/`runTask()` never wait for it (result-first).
|
|
2044
|
+
* Await this ONLY when you need `stats.memory` populated (tests/metrics) or to know the background
|
|
2045
|
+
* reconcile finished. Best-effort: it never rejects (failures route to `onError(phase:"memory")`).
|
|
2046
|
+
*/
|
|
2047
|
+
consolidation(): Promise<void>;
|
|
2048
|
+
/**
|
|
2049
|
+
* design/100 §E12 — resolves to the post-completion prompt **suggestions** (the shell's follow-up prompts),
|
|
2050
|
+
* or `[]` when `suggestNextPrompts` was off / the task did not complete / the pass produced nothing / it
|
|
2051
|
+
* failed. Like {@link consolidation}, the pass is **fire-and-forget**: `result()` never waits for it, so a
|
|
2052
|
+
* shell does `await stream.result()` THEN `await stream.suggestions()`. **Never rejects.** The strings are
|
|
2053
|
+
* UNTRUSTED model output for display ONLY — never re-feed them to a model.
|
|
2054
|
+
*/
|
|
2055
|
+
suggestions(): Promise<string[]>;
|
|
2056
|
+
/**
|
|
2057
|
+
* Inject a mid-task **steering** message (design/47) that the running task sees at the start of its
|
|
2058
|
+
* next turn (delivered via the harness steering queue). Resolves once queued; **throws** (code
|
|
2059
|
+
* `steering.not_running`) if the task hasn't started yet or has already finished — never silently
|
|
2060
|
+
* dropped. By default the text enters as a normal **user** message (in an orchestration the caller IS
|
|
2061
|
+
* the task's user). Pass `trusted: true` ONLY for operator/system-level guidance: it is wrapped as a
|
|
2062
|
+
* `<system-reminder>` (elevated authority) — do NOT use it for caller/third-party content that could
|
|
2063
|
+
* carry a prompt injection. The seam gives the channel; the caller owns the judgement (design/43 §6).
|
|
2064
|
+
*/
|
|
2065
|
+
steer(text: string, options?: {
|
|
2066
|
+
trusted?: boolean;
|
|
2067
|
+
}): Promise<void>;
|
|
2068
|
+
/**
|
|
2069
|
+
* Request a manual context **compaction** (design/99 MF-18 — the shell `/compact` button). Forces a
|
|
2070
|
+
* compaction at the NEXT safe turn boundary regardless of the auto-threshold (the only safe point — never
|
|
2071
|
+
* mid-turn, which would rewrite the session under an in-flight request); a `compacted` event with
|
|
2072
|
+
* `trigger:"manual"` is emitted when it actually compacts. Resolves once the request has been PROCESSED at
|
|
2073
|
+
* a boundary, or when the task ends first (whichever comes first — it never hangs). **Throws**
|
|
2074
|
+
* (`steering.not_running`) if the task hasn't started or has already finished. Idempotent-ish: concurrent
|
|
2075
|
+
* calls coalesce onto the next boundary (all waiters get the same outcome).
|
|
2076
|
+
*
|
|
2077
|
+
* ⚠️ BREAKING (blackboard [496]③, MF-18 processed-无-compacted): resolves with a {@link CompactOutcome}
|
|
2078
|
+
* instead of `void` — "processed" alone told a consumer nothing when the attempt failed or was mooted
|
|
2079
|
+
* (the 202-then-silence fingerprint). Every outcome also has a stream/trace counterpart:
|
|
2080
|
+
* `"compacted"` → the `compacted` event; `"failed"` → `compaction.failed` trace (+ `onError(phase:
|
|
2081
|
+
* "compaction")` when an attempt was burned); `"blocked"` → `compaction.blocked` trace; `"noop"` →
|
|
2082
|
+
* `compaction.noop` trace; `"disabled"` → `compaction.disabled` trace; `"mooted"` →
|
|
2083
|
+
* `compaction.mooted` trace — or the task simply settled before any boundary processed the request
|
|
2084
|
+
* (the run-end backstop resolves "mooted" without a frame; the task's terminal events are the signal).
|
|
2085
|
+
*/
|
|
2086
|
+
compact(): Promise<CompactOutcome>;
|
|
2087
|
+
/**
|
|
2088
|
+
* design/116 detach(飞轮 [C],CC mid-flight ctrl+b)— move a RUNNING tool call to the background.
|
|
2089
|
+
* Today only a detach-capable Bash honors it (the env adopts the child as a background shell; the tool
|
|
2090
|
+
* settles early with "moved to background; task_id=b*", and the G2b completion notification takes over).
|
|
2091
|
+
* Fire-and-forget and race-safe: a request landing before the tool reads its signal still detaches; one
|
|
2092
|
+
* landing after the tool finished is a no-op. Unknown toolCallIds are a no-op (nothing to detach).
|
|
2093
|
+
*/
|
|
2094
|
+
detach(toolCallId: string): void;
|
|
2095
|
+
/**
|
|
2096
|
+
* Hard-**interrupt** the running task — a real abort (not a best-effort hint), equivalent to firing the
|
|
2097
|
+
* task's `signal` (design/47). No-op if the task already finished. For a SOFT redirect that lets the
|
|
2098
|
+
* task keep running and adjust, use {@link steer} instead.
|
|
2099
|
+
*/
|
|
2100
|
+
interrupt(): Promise<void>;
|
|
2101
|
+
/**
|
|
2102
|
+
* Reap this task's resources — **callable after it finished**, idempotent, never throws (design/50 §3,
|
|
2103
|
+
* design/51). The fan-out (v2) cancel primitive: an orchestrator's `cancelAll` is the shared
|
|
2104
|
+
* `AbortController.abort()` then `Promise.all(streams.map((s) => s.destroy()))`.
|
|
2105
|
+
*
|
|
2106
|
+
* - **still running** → hard-interrupts it; the run's own `finish()` tears down its execution env.
|
|
2107
|
+
* - **suspended** (`status:"suspended"`) → `finish()` SKIPPED env teardown (the remote env was
|
|
2108
|
+
* `suspendVM`-paused for a durable resume) and the checkpoint is committed → `destroy()` reaps BOTH:
|
|
2109
|
+
* it CAS-**expires** the checkpoint (`CheckpointStore.expire`, fencing any concurrent resume) and —
|
|
2110
|
+
* **only if it won that CAS** — destroys the paused env. So a cancelled fan-out worker never leaks a
|
|
2111
|
+
* paused container + orphan checkpoint, and is never resumed onto an env `destroy()` already tore down
|
|
2112
|
+
* (the expire/resolve CAS on the one `pending` row is mutually exclusive: exactly one of reap/resume
|
|
2113
|
+
* wins). If `expire` itself fails, the env is left intact (checkpoint + paused env stay a consistent,
|
|
2114
|
+
* still-resumable pair; the failure surfaces via `RunnerDeps.onError`, not a throw).
|
|
2115
|
+
* - **already completed / failed / already destroyed** → no-op.
|
|
2116
|
+
*
|
|
2117
|
+
* Idempotent at the promise level (repeat/concurrent calls await the same settled work).
|
|
2118
|
+
*/
|
|
2119
|
+
destroy(): Promise<void>;
|
|
2120
|
+
}
|
|
2121
|
+
/**
|
|
2122
|
+
* Memory write-side consolidation (design/41 B-full): after a task ends, optionally make **one** LLM
|
|
2123
|
+
* call to reconcile the notes the model wrote this task against existing memory — Mem0-style
|
|
2124
|
+
* ADD/UPDATE/DELETE/NONE — so memory stays "few and accurate". **Opt-in, off by default**: the object's
|
|
2125
|
+
* mere presence does NOT enable it; `enabled` must be set `true` explicitly (so a config object can sit
|
|
2126
|
+
* in place pre-wired and be flipped on). Requires `RunnerDeps.memoryStore` to implement the
|
|
2127
|
+
* id-addressable trio (`searchScored`/`update`/`delete`); otherwise consolidation is a safe no-op.
|
|
2128
|
+
*
|
|
2129
|
+
* Cost lands in `TaskResult.stats.memory` (NOT in the task's own `tokens`/`cost`, and excluded from the
|
|
2130
|
+
* budget gate). Failures are best-effort: the notes the model already saved are kept, and the failure is
|
|
2131
|
+
* reported via `onError(phase:"memory")`.
|
|
2132
|
+
*
|
|
2133
|
+
* @deprecated design/138 S4 — the runner-integrated consolidation pass rode the retired legacy memoryStore
|
|
2134
|
+
* path and no longer runs (the config is ignored by the Runner). The standalone helpers
|
|
2135
|
+
* (`runMemoryConsolidation`/`consolidateScope`) still accept it for direct store-level use.
|
|
2136
|
+
*/
|
|
2137
|
+
export interface MemoryConsolidationConfig {
|
|
2138
|
+
/** Master switch. `false`/omitted = no consolidation (zero extra LLM calls), unchanged behavior. */
|
|
2139
|
+
enabled: boolean;
|
|
2140
|
+
/** Model role for the reconcile LLM call. Default `"summarize"` (a cheap tier; falls back to `default`). */
|
|
2141
|
+
role?: ModelRole;
|
|
2142
|
+
/**
|
|
2143
|
+
* Vector-distance reconcile band over `searchScored` candidates (see {@link ScoredMemory} — cosine
|
|
2144
|
+
* distance ∈ [0, 2], 0 = identical). A new note's NEAREST existing candidate decides its path:
|
|
2145
|
+
* `< lo` = near-duplicate → cheap UPDATE, no LLM; `[lo, hi]` = possibly refines/contradicts → batched
|
|
2146
|
+
* into the LLM call; `> hi` = genuinely new → kept as-is, no LLM. Default `{ lo: 0.05, hi: 0.30 }`.
|
|
2147
|
+
*
|
|
2148
|
+
* These defaults are effectively the **5th / 95th percentile** of a typical embedding model's distance
|
|
2149
|
+
* distribution — **calibrate them per embedding model**: a different model's distances live on a
|
|
2150
|
+
* different scale, and an un-recalibrated band silently degrades to pass-through (everything ADDs) or
|
|
2151
|
+
* over-merges (everything reconciles).
|
|
2152
|
+
*/
|
|
2153
|
+
band?: {
|
|
2154
|
+
lo: number;
|
|
2155
|
+
hi: number;
|
|
2156
|
+
};
|
|
2157
|
+
/** Top-k candidates `searchScored` fetches per new note. Default 20 (bounds the LLM input). */
|
|
2158
|
+
searchLimit?: number;
|
|
2159
|
+
/** Cap on this-task notes consolidated in one batch (bounds the LLM input). Default 50. */
|
|
2160
|
+
maxNotesPerTask?: number;
|
|
2161
|
+
/** Independent wall-clock timeout (seconds) for the whole consolidation pass. Default 30. */
|
|
2162
|
+
timeoutSec?: number;
|
|
2163
|
+
}
|
|
2164
|
+
/**
|
|
2165
|
+
* design/98 §E.2 / §2.5 (S8b) — the deployment-trusted governance that EVERY sub-agent an LLM-authored
|
|
2166
|
+
* workflow script spawns INHERITS (tighten-only). The child spec is BUILT from this baseline + a strict
|
|
2167
|
+
* WHITELIST of safe work-fields the script may set — `{ ...base, ...pick(scriptSpec, WHITELIST_KEYS) }` then
|
|
2168
|
+
* `tightenTaskSpec(base, child)` (codex BLOCKER2: default-deny / complete-by-construction, NOT a blacklist
|
|
2169
|
+
* strip — a missed control-plane field would otherwise leak). It is captured from `RunnerDeps` (trusted,
|
|
2170
|
+
* never LLM-influenced), NEVER from the LLM-influenced initiating task spec.
|
|
2171
|
+
*
|
|
2172
|
+
* Why an EXPLICIT field (codex Q1/Q2 arbitration): `RunnerDeps` has no `tools`/`mcp`/`skills`/`principal`
|
|
2173
|
+
* (those are TaskSpec-only), so the capability a workflow child gets cannot be auto-derived from deps —
|
|
2174
|
+
* the deployment must DECLARE it here. Unset ⇒ self-orchestration is FAIL-CLOSED (the `run_workflow` tool is
|
|
2175
|
+
* not mounted, same hard deploy gate as a missing sandbox): a script-spawned agent must never run without a
|
|
2176
|
+
* governed baseline.
|
|
2177
|
+
*/
|
|
2178
|
+
export interface WorkflowGovernanceBaseline {
|
|
2179
|
+
/**
|
|
2180
|
+
* The deployment's trusted control-plane the child inherits — toolPolicy / onAsk / onQuestion / hooks /
|
|
2181
|
+
* principal / tools / mcp / skills / lspManager / checkpointStore / getApiKeyAndHeaders / promptProvider /
|
|
2182
|
+
* handsReadOnly / shellGate / limits / maxCostUsd / maxTokens, etc. Snapshotted into each child spec FIRST,
|
|
2183
|
+
* so every governance field comes from here; only whitelisted work-fields overlay it.
|
|
2184
|
+
*/
|
|
2185
|
+
base: Partial<TaskSpec>;
|
|
2186
|
+
/**
|
|
2187
|
+
* The allowed model NAMES an LLM-authored script may pick (design/98 §2.5, codex 新洞2). A script gives a
|
|
2188
|
+
* `modelName` string (never a `Model` object — that carries `baseUrl`/`headers` = exfil); the engine
|
|
2189
|
+
* resolves it against this list to a deploy-configured `Model` (the script never sees the object).
|
|
2190
|
+
* **FAIL-CLOSED**: `undefined`/empty ⇒ the script CANNOT pick a model (its `modelName` is rejected → the
|
|
2191
|
+
* child falls back to the workflow's default role). NEVER fail-open to the whole `models` catalog for an
|
|
2192
|
+
* LLM-authored workflow.
|
|
2193
|
+
*/
|
|
2194
|
+
workflowModelAllowlist?: string[];
|
|
2195
|
+
}
|
|
2196
|
+
/**
|
|
2197
|
+
* design/99 §K — the per-principal runtime ENTITLEMENTS the engine enforces server-side, resolved by a
|
|
2198
|
+
* deployment via {@link RunnerDeps.runtimeCapsResolver} from center's `GET /api/config/effective?principal=`.
|
|
2199
|
+
* Every field is TIGHTEN-ONLY (a cap only ever DENIES or FORCES; `undefined` = no per-principal restriction).
|
|
2200
|
+
* Only the two caps the ENGINE can enforce live here; `allowUltracode`/`allowBypassPermissions` are
|
|
2201
|
+
* shell-UX / service-settings-layer concerns (see {@link RunnerDeps.runtimeCapsResolver}).
|
|
2202
|
+
*/
|
|
2203
|
+
export interface RuntimeCaps {
|
|
2204
|
+
/** `false` DENIES workflow self-orchestration for this principal server-side — even on a deployment that is
|
|
2205
|
+
* capable ({@link RunnerDeps.workflowScriptRunner} + governance). The third stage of the workflows gate.
|
|
2206
|
+
* `undefined`/`true` = no per-principal restriction (the deployment capability still governs). */
|
|
2207
|
+
allowWorkflows?: boolean;
|
|
2208
|
+
/** `false` DENIES fork (`Agent(subagent_type:"fork")` — design/136: the only fork face since the standalone
|
|
2209
|
+
* tool was retired; the deny is the honest `fork.disabled` result, and since 1.256 it binds the Agent-fork
|
|
2210
|
+
* route too, closing the 1.254 governance bypass) for this principal server-side — even on a fork-capable
|
|
2211
|
+
* (durable-store) deployment. Fork is a compute-amplification primitive (a principal spawns
|
|
2212
|
+
* context-inheriting children, each spending on its own quota), so a multi-tenant operator gates it
|
|
2213
|
+
* per-principal the SAME way as {@link allowWorkflows}. `undefined`/`true` = no per-principal restriction
|
|
2214
|
+
* (the task `enableFork` + durable-store capability still govern). Tighten-only: it can DENY a capable
|
|
2215
|
+
* deployment, never GRANT beyond it. */
|
|
2216
|
+
allowFork?: boolean;
|
|
2217
|
+
/**
|
|
2218
|
+
* Observer agents (CC 2.1.206 parity, docs/CC206-OBSERVER-ANCHORS-2026-07-11.md §6): honor
|
|
2219
|
+
* {@link AgentDefinition.observer} auto-spawn declarations. **POLARITY NOTE — unlike
|
|
2220
|
+
* `allowWorkflows`/`allowFork` (`undefined` = unrestricted), this one is `=== true` EXPLICIT
|
|
2221
|
+
* opt-in, default OFF**: CC's gate pair is a default-UNSET experimental env var
|
|
2222
|
+
* (`CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS`) ANDed with a default-true statsig gate — the
|
|
2223
|
+
* composite ships dark. `undefined`/`false` ⇒ declarations resolve to unobserved (no warn: the
|
|
2224
|
+
* gate, not a config mistake).
|
|
2225
|
+
*/
|
|
2226
|
+
allowObservers?: boolean;
|
|
2227
|
+
/** `true` FORCES this principal's run onto the durable-approval path: the engine synthesizes a
|
|
2228
|
+
* `durableApproval{scope: principal}` so a policy `ask` suspends to the wire (a per-tool CC-faithful gate)
|
|
2229
|
+
* even when the caller did not opt in — center's fleet-wide "interactive runs gate" mandate. A
|
|
2230
|
+
* caller-supplied `TaskSpec.durableApproval` always wins (it may carry a tighter scope/ttl). */
|
|
2231
|
+
forceDurableGate?: boolean;
|
|
2232
|
+
}
|
|
2233
|
+
/**
|
|
2234
|
+
* design/129-B(黑板 [444])— one lifecycle event of a BACKGROUND delegation child, delivered to the
|
|
2235
|
+
* process-level {@link RunnerDeps.onBackgroundChildEvent} observer. Keys: `taskId` is the registry handle
|
|
2236
|
+
* (`a*` domain — the TaskOutput/TaskStop key); `progressTaskId`/`sessionId` are the child RUN's id (uuid
|
|
2237
|
+
* domain — the same key `task_progress` frames carry, [434] anchor).
|
|
2238
|
+
*/
|
|
2239
|
+
export interface BackgroundChildEvent {
|
|
2240
|
+
kind: "spawn" | "tick" | "terminal";
|
|
2241
|
+
/** Registry handle id (`a*` domain). Stable across all three kinds — the row key. */
|
|
2242
|
+
taskId: string;
|
|
2243
|
+
/** design/129: `true` when the child outlives its parent turn (session-scoped). */
|
|
2244
|
+
sessionScoped: boolean;
|
|
2245
|
+
/** Registry owner key (task-scoped: the host taskId; session-scoped: the sessionId). */
|
|
2246
|
+
owner?: string;
|
|
2247
|
+
/** Registry scope (tenant/principal isolation key). */
|
|
2248
|
+
scope?: string;
|
|
2249
|
+
/** spawn: the child's short description (bounded, display-safe). */
|
|
2250
|
+
description?: string;
|
|
2251
|
+
/** spawn: the HOST task's canonical taskId (parent attribution). */
|
|
2252
|
+
parentTaskId?: string;
|
|
2253
|
+
/** tick: the forwarded `task_progress` frame's own taskId (uuid domain; nested children carry theirs). */
|
|
2254
|
+
progressTaskId?: string;
|
|
2255
|
+
/** tick: the forwarded frame's parentTaskId (nested attribution) · terminal: absent. */
|
|
2256
|
+
progressParentTaskId?: string;
|
|
2257
|
+
/** tick: the child's display name, when the frame carried one. */
|
|
2258
|
+
name?: string;
|
|
2259
|
+
/**
|
|
2260
|
+
* tick (黑板 [558] B): the child's most recent tool intent as one human line ("Bash npm test",
|
|
2261
|
+
* "Edit src/x.ts") — derived from the last `tool_start` on the child's stream, so a parent can show
|
|
2262
|
+
* "what is it doing right now" with zero polling of the child. Absent until the child runs a tool.
|
|
2263
|
+
*/
|
|
2264
|
+
currentAction?: string;
|
|
2265
|
+
/** terminal: the child RUN's session id (uuid domain) when known. */
|
|
2266
|
+
sessionId?: string;
|
|
2267
|
+
/**
|
|
2268
|
+
* terminal (黑板 [558] C): a handle to the child's persisted transcript — the child RUN's session id
|
|
2269
|
+
* (uuid domain). A parent reads the last N steps on demand via the `AgentTranscript` tool (pull model:
|
|
2270
|
+
* it does NOT inflate the parent's context). Mirror of {@link sessionId} for terminal events; named
|
|
2271
|
+
* distinctly so a consumer keys "how do I read this child's history" without conflating it with routing.
|
|
2272
|
+
*/
|
|
2273
|
+
transcriptId?: string;
|
|
2274
|
+
/**
|
|
2275
|
+
* terminal (黑板 [558] A): the child's last ≤10 completed tool steps ({tool, target, outcome}) — the
|
|
2276
|
+
* residual a parent needs to write a PRECISE resume prompt ("you stopped at file X, step Y") for a
|
|
2277
|
+
* child that was stopped/killed mid-flight, WITHOUT reading the transcript. Bounded; absent if the
|
|
2278
|
+
* child ran no tools.
|
|
2279
|
+
*/
|
|
2280
|
+
recentSteps?: import("../agents/subagent-steps.js").SubagentStep[];
|
|
2281
|
+
/**
|
|
2282
|
+
* terminal (黑板 [558] D — core half): files the child mutated (Write/Edit/MultiEdit/NotebookEdit)
|
|
2283
|
+
* with edit counts. The LSP-aggregated `<new-diagnostics>` projection is the shell's half; core
|
|
2284
|
+
* supplies only the edited-file list. Bounded; absent if the child edited nothing.
|
|
2285
|
+
*/
|
|
2286
|
+
editedFiles?: import("../agents/subagent-steps.js").SubagentEditedFile[];
|
|
2287
|
+
/**
|
|
2288
|
+
* terminal (黑板 [558] E): `true` when the child can be revived with `SendMessage` (its session is
|
|
2289
|
+
* retained and it was not stopped by the user); `false` for a user-stopped / non-resumable child.
|
|
2290
|
+
* Lets a parent's orchestration logic decide "continue it" vs "start fresh" without trial-and-error.
|
|
2291
|
+
*/
|
|
2292
|
+
resumable?: boolean;
|
|
2293
|
+
/** terminal: the settled status. */
|
|
2294
|
+
status?: "completed" | "killed" | "failed";
|
|
2295
|
+
/** terminal, killed only (design/134 §3.3): who stopped it. MIRROR of task-registry `StopSource`
|
|
2296
|
+
* (the single source; inlined to avoid an import cycle — task-registry imports types.ts; third
|
|
2297
|
+
* mirror: task-notification.ts `TaskNotificationPayload.stoppedBy` — keep all three in sync).
|
|
2298
|
+
* OPEN ENUM: consumers must tolerate unknown values (a future "timeout" is not breaking). */
|
|
2299
|
+
stoppedBy?: "user" | "parent" | "system" | (string & {});
|
|
2300
|
+
/** terminal: bounded human summary (same text the task_notification carries). */
|
|
2301
|
+
summary?: string;
|
|
2302
|
+
/** tick: live rollup (`task_progress.usage`) · terminal: final `{tokens, turns, costMicroUsd}`. */
|
|
2303
|
+
usage?: {
|
|
2304
|
+
totalTokens?: number;
|
|
2305
|
+
toolUses?: number;
|
|
2306
|
+
durationMs?: number;
|
|
2307
|
+
tokens?: number;
|
|
2308
|
+
turns?: number;
|
|
2309
|
+
costMicroUsd?: number;
|
|
2310
|
+
};
|
|
2311
|
+
}
|
|
2312
|
+
/**
|
|
2313
|
+
* parity-204 — structured `RunnerDeps.loadProjectMemory` return (backward-compatible: a bare
|
|
2314
|
+
* `string | null` keeps its exact historical meaning). Adds the CC 2.1.204 `seededFromContext`
|
|
2315
|
+
* seam (cc204-bundle @17917159: CC preloads readFileState for CLAUDE.md/nested-memory files it
|
|
2316
|
+
* placed in context, and a DEFAULT whole-file Read of an unchanged seeded file answers with the
|
|
2317
|
+
* already-in-context reminder instead of re-transmitting the body — token economy, GA in 204).
|
|
2318
|
+
*/
|
|
2319
|
+
export interface ProjectMemoryLoad {
|
|
2320
|
+
/** The project-context text to inject — same semantics as returning a bare string (null/blank ⇒ no injection). */
|
|
2321
|
+
content: string | null;
|
|
2322
|
+
/**
|
|
2323
|
+
* Files whose FULL, disk-verbatim text the deployment has placed in the model's context (e.g. the
|
|
2324
|
+
* CLAUDE.md that `content` embeds). The Runner pre-seeds the hands' read state (through the same
|
|
2325
|
+
* resolveKey containment as a real Read — an out-of-root path is silently skipped), so a default
|
|
2326
|
+
* whole-file Read of an UNCHANGED seeded file returns the CC-verbatim reminder
|
|
2327
|
+
* (`This file is already in your context (see "Contents of <path>" above) and has not changed on
|
|
2328
|
+
* disk…`) instead of the body. `content` here MUST be the file's exact disk text at load time —
|
|
2329
|
+
* the unchanged check hashes it; never declare a truncated/annotated variant (CC's `isPartialView`
|
|
2330
|
+
* exemption). A file that later changes on disk always reads normally (hash mismatch bypasses the
|
|
2331
|
+
* dedup and disarms it). Requires hands (an executionEnv); ignored on a hands-less task.
|
|
2332
|
+
*/
|
|
2333
|
+
seededFiles?: ReadonlyArray<{
|
|
2334
|
+
path: string;
|
|
2335
|
+
content: string;
|
|
2336
|
+
}>;
|
|
2337
|
+
}
|
|
2338
|
+
/** Runtime dependencies shared across tasks. */
|
|
2339
|
+
export interface RunnerDeps {
|
|
2340
|
+
brain: Brain;
|
|
2341
|
+
/** Catalog used to resolve string ModelRefs to Model objects. */
|
|
2342
|
+
models?: Record<string, Model>;
|
|
2343
|
+
/**
|
|
2344
|
+
* 模型档位绑定(clay 拍 2026-07-11):sema 档位词(`max`/`pro`/`flash`/`lite`,`ultra` 预留)→ 具体模型
|
|
2345
|
+
* (catalog 名或 Model)。Runner 构造时经 `expandTiers` 增广进 catalog,使档位词与 CC alias
|
|
2346
|
+
* (`fable`/`mythos`/`opus`/`sonnet`/`haiku`,内置固定映射)在全部模型寻址面直接可用(TaskSpec.model /
|
|
2347
|
+
* roles / Agent 工具 model / workflow agent() / `@model` mention)。无绑定档沿 DEFAULT_TIER_ORDER 降档;
|
|
2348
|
+
* 与部署 catalog 同名键时 catalog WINS(SHADOW)。center 经配置域下发/覆写此表。
|
|
2349
|
+
*/
|
|
2350
|
+
tiers?: Record<string, ModelRef>;
|
|
2351
|
+
/**
|
|
2352
|
+
* F4 agentType 注册表(2026-07-11):部署声明的 {@link AgentDefinition} 集,workflow `agent(…,{agentType})`
|
|
2353
|
+
* 经此解析(内置 Explore/Plan 之上 SHADOW)。design/141 件A:Agent 工具 lane(`createSubagentTool`)未显式
|
|
2354
|
+
* 传 `agents` 时经 `Runner.agentCatalog` 自动取此表——同一 Runner 两 lane 单源;显式传参仍 WINS。
|
|
2355
|
+
*/
|
|
2356
|
+
agents?: AgentDefinition[];
|
|
2357
|
+
/** `false` 从 workflow agentType 注册表移除内置 Explore/Plan(镜像 createSubagentTool 同名开关)。 */
|
|
2358
|
+
builtinAgents?: boolean;
|
|
2359
|
+
/**
|
|
2360
|
+
* design/141 件2 — hands 工具带(Read/Write/Edit/Bash…)的部署方窄配置面。刻意不导出
|
|
2361
|
+
* `createHandsToolkit` 整厂(部署自装配塞 `spec.tools` 会被 Runner 的自动装配同名覆盖=反模式;
|
|
2362
|
+
* CC 亦无 options-bag 开放面,走单例+hook)。只开放安全子集,Runner 装配时合成:
|
|
2363
|
+
* - `beforeWrite` 与引擎的 MemoryEngine 写扫描门 **COMPOSE 而非替换**(部署 hook 先判,拒即拒;
|
|
2364
|
+
* 放行后引擎门仍全量生效——写保护不可能被部署配置绕过)。
|
|
2365
|
+
* Runner 私有编排字段(taskRegistry/detachHub/execClamp/cwdRef/…)不在此面,永不开放。
|
|
2366
|
+
*/
|
|
2367
|
+
hands?: HandsBandOptions;
|
|
2368
|
+
/**
|
|
2369
|
+
* design/96 §20 (P1a) — DEPLOYMENT-DECLARED training knowledge cutoff per model id (e.g.
|
|
2370
|
+
* `{ "qwen-3.5-35b": "2025-01", "deepseek-pro": "2024-07" }`). When the resolved model id is present, the
|
|
2371
|
+
* `# Environment` block shows `Knowledge cutoff: <value>` so the agent reasons about what it may not know.
|
|
2372
|
+
* Deployment-owned ON PURPOSE: core hardcodes no model→date map (a stale cutoff = a §25 honesty breach, and
|
|
2373
|
+
* the model catalog is a deployment/profile concern). Omitted ⇒ no cutoff line (honest absence). Optional.
|
|
2374
|
+
*/
|
|
2375
|
+
modelKnowledgeCutoffs?: Record<string, string>;
|
|
2376
|
+
/**
|
|
2377
|
+
* Default model roles: declare your models once and let every subsystem (main task, compaction,
|
|
2378
|
+
* subagent, team) resolve its role instead of repeating a model name. `TaskSpec.roles` overrides
|
|
2379
|
+
* per task/scenario. e.g. `{ default: "strong", summarize: "cheap", subagent: "cheap" }`.
|
|
2380
|
+
*/
|
|
2381
|
+
roles?: ModelRoles;
|
|
2382
|
+
/**
|
|
2383
|
+
* Session lifecycle/persistence backend. Defaults to `TtlSessionStore` (in-memory, 7-day idle TTL
|
|
2384
|
+
* — lost on restart). For **durable** sessions (a "session center" that survives restarts and is
|
|
2385
|
+
* shared across stateless replicas), supply a `TtlSessionStore` over a durable `SessionRepo`
|
|
2386
|
+
* (e.g. TiDB-backed), or a fully custom `SessionStore`. See `design/10-会话持久化与会话中心.md`.
|
|
2387
|
+
*/
|
|
2388
|
+
sessionStore?: import("./session.js").SessionStore;
|
|
2389
|
+
/**
|
|
2390
|
+
* Durable-checkpoint backend for suspend/resume (design/45). A task with `durableApproval` set
|
|
2391
|
+
* persists its awaiting-human checkpoints here and ends `status:"suspended"`; `runner.resume()` reads
|
|
2392
|
+
* them back — cross-replica when this is durable (service's approval/run-store). A task's own
|
|
2393
|
+
* `checkpointStore` overrides this. Omitted → no durable suspension (policy `ask` stays synchronous).
|
|
2394
|
+
*/
|
|
2395
|
+
checkpointStore?: import("./checkpoint-store.js").CheckpointStore;
|
|
2396
|
+
/**
|
|
2397
|
+
* design/101 §E19 — working-tree snapshot backend for {@link TaskSpec.rewindFiles}. A task with
|
|
2398
|
+
* `rewindFiles` captures a snapshot per completed turn (keyed by the leaf `SessionTreeEntry.id`) and, when it
|
|
2399
|
+
* also branches via {@link TaskSpec.resumeAt}, restores the snapshot for that entry. Omitted ⇒ rewind is OFF
|
|
2400
|
+
* (no snapshot/restore work). The default reference impl is {@link InMemoryFileSnapshotStore}; a deployment
|
|
2401
|
+
* supplies a durable / git / VM-snapshot backend behind the same seam (v1 restore is LOCAL-only).
|
|
2402
|
+
*/
|
|
2403
|
+
fileSnapshotStore?: import("./file-snapshot-store.js").FileSnapshotStore;
|
|
2404
|
+
/**
|
|
2405
|
+
* design/99 §E6 — DURABLE per-session permission rules (a deny-narrowing folded into the task-time tool
|
|
2406
|
+
* policy). Omitted ⇒ the feature is OFF (no rules read, zero behavior change). A deployment supplies a
|
|
2407
|
+
* cross-replica backend whose CAS-rev + tighten-only semantics match the core
|
|
2408
|
+
* {@link import("./session-policy-store.js").InMemorySessionPolicyStore}. Rules are read at prepare time for a
|
|
2409
|
+
* task carrying its own `sessionId` (a delegated subagent inherits none) and composed BEFORE the caller
|
|
2410
|
+
* policy, so they can only SUBTRACT capability. core does NOT verify owner/operator identity — the store
|
|
2411
|
+
* honors the `operator` flag the (service) caller freezes from a verified principal.
|
|
2412
|
+
*/
|
|
2413
|
+
sessionPolicyStore?: import("./session-policy-store.js").SessionPolicyStore;
|
|
2414
|
+
/**
|
|
2415
|
+
* design/99 §K (service [305]/center [318]) — resolve the **per-principal runtime ENTITLEMENTS** the engine
|
|
2416
|
+
* ENFORCES server-side, keyed by `spec.principal`. A deployment (the SERVICE) implements it over center's
|
|
2417
|
+
* `GET /api/config/effective?principal=` `runtimeCaps`. Resolved once at prepare time.
|
|
2418
|
+
*
|
|
2419
|
+
* 🔐 This is a TRUSTED deployment seam, NOT a caller-facing `TaskSpec` field: entitlements are purely
|
|
2420
|
+
* server-governed — an untrusted caller must never be able to self-grant a capability. `undefined` (no
|
|
2421
|
+
* resolver, or an unset cap) = NO per-principal restriction (TIGHTEN-ONLY: a cap can only ever DENY or
|
|
2422
|
+
* FORCE; absence falls back to the deployment-level default). Symmetric with {@link sessionPolicyStore}.
|
|
2423
|
+
*
|
|
2424
|
+
* core enforces only the caps it CAN enforce in the engine: `allowWorkflows` (the third stage of the
|
|
2425
|
+
* workflows gate — task opt-in ∧ deployment capability ∧ this) and `forceDurableGate` (forces a run onto
|
|
2426
|
+
* the durable-approval path so a policy `ask` suspends to the wire). `allowUltracode` is a shell/UX concern
|
|
2427
|
+
* (reasoning-tier, not a core primitive); `allowBypassPermissions` is enforced at the service settings-
|
|
2428
|
+
* resolution layer (the engine sees only a resolved policy, never a "this allow came from bypass" signal).
|
|
2429
|
+
*/
|
|
2430
|
+
runtimeCapsResolver?: (principal: string | undefined) => RuntimeCaps | undefined | Promise<RuntimeCaps | undefined>;
|
|
2431
|
+
/**
|
|
2432
|
+
* design/129-B(黑板 [444])— PROCESS-level observer for background delegation children (Agent/Fork
|
|
2433
|
+
* `run_in_background`): `spawn` (at registry registration) / `tick` (every forwarded `task_progress`)
|
|
2434
|
+
* / `terminal` (after the registry settle), for the child's WHOLE lifetime. Motivation: every per-leg
|
|
2435
|
+
* sink (`RunInternals.onForwardEvent` etc.) carries the SPAWNING turn's lifecycle — correct for sync
|
|
2436
|
+
* children, structurally wrong for a session-scoped background child that outlives the turn (the
|
|
2437
|
+
* deployment rightly freezes per-leg publishers at leg settle, which silences the child). This seam is
|
|
2438
|
+
* keyed to nothing but the process: wire it once at Runner construction and publish fleet rows /
|
|
2439
|
+
* completion pushes from it. Observability only — a throwing observer is swallowed, never faults a run.
|
|
2440
|
+
*/
|
|
2441
|
+
onBackgroundChildEvent?: (event: BackgroundChildEvent) => void;
|
|
2442
|
+
/**
|
|
2443
|
+
* design/98 (S8) — the HARD sandbox seam for LLM-AUTHORED workflow scripts (`TaskSpec.selfOrchestration`).
|
|
2444
|
+
* A deployment supplies an isolated-vm / separate-process runner whose `safeForUntrustedScripts === true`;
|
|
2445
|
+
* core does NOT ship one (the Node `vm` dev runner is NOT a security boundary). With this unset (or
|
|
2446
|
+
* `safeForUntrustedScripts:false`), `selfOrchestration` is FAIL-CLOSED: the `run_workflow` tool is not
|
|
2447
|
+
* mounted and the orchestration prompt is not injected. See {@link WorkflowGovernanceBaseline}.
|
|
2448
|
+
*/
|
|
2449
|
+
workflowScriptRunner?: import("../orchestration/workflow-script-runner.js").WorkflowScriptRunner;
|
|
2450
|
+
/**
|
|
2451
|
+
* design/98 §2.5 (S8b) — the deployment-trusted governance every workflow-spawned sub-agent inherits
|
|
2452
|
+
* (tighten-only). REQUIRED (alongside a hard `workflowScriptRunner`) for `selfOrchestration` to activate:
|
|
2453
|
+
* unset ⇒ FAIL-CLOSED (the `run_workflow` tool is not mounted — a script-spawned agent must never run
|
|
2454
|
+
* without a governed baseline). See {@link WorkflowGovernanceBaseline}.
|
|
2455
|
+
*/
|
|
2456
|
+
workflowGovernanceBaseline?: WorkflowGovernanceBaseline;
|
|
2457
|
+
/** design/98 §D.6 (S8c) — deployment hard CEILINGS for an LLM-authored workflow (script length / agent
|
|
2458
|
+
* count / timeouts / per-child cost+token caps / budget / result+log size). Defaults bound a runaway. */
|
|
2459
|
+
workflowLimits?: import("../orchestration/run-workflow-tool.js").WorkflowLimits;
|
|
2460
|
+
/** design/98 §D.5 (S8c) — re-invoke seam: called once when an LLM-authored workflow completes, with a
|
|
2461
|
+
* redacted, bounded summary. Unset ⇒ the run still completes + is queryable; the originator just isn't
|
|
2462
|
+
* pushed a notification. */
|
|
2463
|
+
workflowCompletionNotifier?: import("../orchestration/run-workflow-tool.js").WorkflowCompletionNotifier;
|
|
2464
|
+
/** design/97 S1b / design/98 §D.5 — persist LLM-authored workflow runs here for cross-replica `/workflows`
|
|
2465
|
+
* history (opt-in; in-process runs are still subscribable without it). */
|
|
2466
|
+
workflowRunStore?: import("./workflow-run-store.js").WorkflowRunStore;
|
|
2467
|
+
/** design/97 CORE-9 (Part A) — the LOAD-BEARING resume journal for LLM-authored (`run_workflow` tool) workflows
|
|
2468
|
+
* (the twin of `workflowRunStore`; service ships a durable Postgres/TiDB one). Wired into the auto-mounted
|
|
2469
|
+
* run_workflow tool so a tool-launched workflow can durably RESUME across a replica crash. Opt-in. */
|
|
2470
|
+
workflowJournalStore?: import("./workflow-journal-store.js").WorkflowJournalStore;
|
|
2471
|
+
/** B5/F2 + design/140 §6 1a — the script-persistence / named-registry seam, threaded into the auto-mounted
|
|
2472
|
+
* run_workflow tool: every invocation's resolved script is persisted (iterate via `{scriptPath}`), `{name}`
|
|
2473
|
+
* resolves a saved workflow, and a registration's `defaultArgs` merge under the call-time args. Opt-in
|
|
2474
|
+
* (absent ⇒ inline `script` + built-in names only). */
|
|
2475
|
+
workflowScriptStore?: import("../orchestration/workflow-script-store.js").WorkflowScriptStore;
|
|
2476
|
+
/** design/140 §6 1c — `false` removes the BUILT-IN named workflows (`team-discussion`, …) from the
|
|
2477
|
+
* auto-mounted run_workflow tool (the `builtinAgents:false` analog; default ON). A deployment
|
|
2478
|
+
* `workflowScriptStore` registration of the same name shadows a built-in regardless. */
|
|
2479
|
+
builtinWorkflows?: boolean;
|
|
2480
|
+
/**
|
|
2481
|
+
* design/97 CORE-9 (Part B) — a TRUSTED deployment sink for the steerable handle of every agent an LLM-authored
|
|
2482
|
+
* (`run_workflow` tool) workflow spawns. When set, the tool's `agent()` primitive runs each agent STEERABLE and
|
|
2483
|
+
* emits its {@link import("../orchestration/workflow.js").WorkflowAgentHandle} here (the script never receives
|
|
2484
|
+
* the handle — no host-context leak into the runner); the deployment registers it by `runId`+`label` to route a
|
|
2485
|
+
* human/cross-replica steer to `handle.steer(...)`. Unset ⇒ agents run non-steerable (no overhead). Opt-in.
|
|
2486
|
+
*
|
|
2487
|
+
* **Interaction with {@link workflowJournalStore} (audit note)**: a steerable agent runs via `agentStream`,
|
|
2488
|
+
* which is NOT journaled (a finished result can't be steered). So with BOTH set, a steerable workflow's
|
|
2489
|
+
* `resumeFromRunId` finds an empty journal and re-runs all agents LIVE — correct, but with no caching benefit
|
|
2490
|
+
* (durable resume re-executes rather than skips). Journal-able steerable agents are a follow-on.
|
|
2491
|
+
*/
|
|
2492
|
+
onWorkflowAgentSpawn?: (handle: import("../orchestration/workflow.js").WorkflowAgentHandle) => void;
|
|
2493
|
+
/** design/72 §2.2 (B): deployment default for the suspend-loop cap (see `TaskSpec.maxSuspends`).
|
|
2494
|
+
* Default 5 (loose — human-approval flows re-suspend rarely). A task's own `maxSuspends` overrides. */
|
|
2495
|
+
maxSuspends?: number;
|
|
2496
|
+
/**
|
|
2497
|
+
* design/91: injectable wall-clock source for **human-review timing** (and `Checkpoint.suspendedAt`).
|
|
2498
|
+
* Defaults to `Date.now`. The Runner reads EVERY human-time timestamp through this — the synchronous
|
|
2499
|
+
* `resolveAsk` wait (`t1 − t0`), the durable suspend's `suspendedAt`, and the resume's derived human
|
|
2500
|
+
* latency (`now() − suspendedAt`) — so a test can inject a controllable clock (`let t = 0; now = () => t`)
|
|
2501
|
+
* and assert `stats.humanReview` deterministically (design/87 §4.3 flaky-guard: no bare `Date.now()` in a
|
|
2502
|
+
* hard-gate test). **Scope = human-time only**: this is NOT a general clock for token/cost/turn accounting
|
|
2503
|
+
* (those keep `Date.now`); `humanReview` is a budget-EXCLUDED side observable, never folded into cost. */
|
|
2504
|
+
now?: () => number;
|
|
2505
|
+
/** @deprecated design/138 S4 (BREAKING) — the legacy MemoryStore runner path is RETIRED: with this set,
|
|
2506
|
+
* the Runner mounts NO remember/recall tools, injects NO `<user_memory>` block, and runs NO legacy
|
|
2507
|
+
* consolidation/selective/dynamic recall — it only emits a one-shot deprecation warning per prepared
|
|
2508
|
+
* task (`onError`, phase `"config"`). Migrate to {@link memoryBackend} (the injection-first memory
|
|
2509
|
+
* engine). The TYPE and the store implementations (InMemory/File/Pg) remain exported — a FileBackend
|
|
2510
|
+
* 等 store 仍可独立使用; this dep just no longer drives the runner. Field removal is the next major. */
|
|
2511
|
+
memoryStore?: import("./memory.js").MemoryStore;
|
|
2512
|
+
/**
|
|
2513
|
+
* design/138 S1 — the NEW-ARCHITECTURE memory seam (MemoryEngine over a {@link import("./memory-engine/types.js").MemoryBackend}).
|
|
2514
|
+
* When set AND `spec.memory.enabled`, the task runs the INJECTION-FIRST file-based memory lifecycle
|
|
2515
|
+
* (materialize → session file ops → harvest with the full gate set), the CC-verbatim `# Memory`
|
|
2516
|
+
* instruction + fenced derived index replace the legacy `<user_memory>` block, and NO remember/recall
|
|
2517
|
+
* tools are mounted (memory = the model's ordinary file skills). **S4 (codex 1.258 F6 doc fix): unset ⇒
|
|
2518
|
+
* the task runs MEMORY-LESS** — the legacy `memoryStore` runtime path was retired (one deprecation
|
|
2519
|
+
* warning via `onError` phase `"config"`); this field is the ONLY live memory seam.
|
|
2520
|
+
*/
|
|
2521
|
+
memoryBackend?: import("./memory-engine/types.js").MemoryBackend;
|
|
2522
|
+
/**
|
|
2523
|
+
* design/138 §2.7 — the memory-engine directory CONFIG ROOT used when {@link memoryBackend} does not
|
|
2524
|
+
* pin its own directory (a {@link import("./memory-engine/file-backend.js").FileMemoryEngineBackend}
|
|
2525
|
+
* exposes `directoryRoot` and wins). The per-repo memory dir derives as `<root>/<repoKey>/memory`
|
|
2526
|
+
* (repoKey = CC-style slug of the task root). Default: `AGENT_DATA_DIR` env or `~/.ai-agent`.
|
|
2527
|
+
* Location is PURE CONFIG (§2.7 r2.1): a deployment may equally construct the FileBackend over an
|
|
2528
|
+
* IN-REPO git-tracked directory for a project scope.
|
|
2529
|
+
*/
|
|
2530
|
+
memoryEngineDir?: string;
|
|
2531
|
+
/**
|
|
2532
|
+
* design/138 S2-B (O-F7/C-F3) — the Runner-owned harvest-report sink. Both harvest boundaries
|
|
2533
|
+
* (the checkpoint mint inside commitSuspendSaga, `phase: "checkpoint"`, and the task terminal in
|
|
2534
|
+
* runtask, `phase: "terminal"`) deliver their {@link import("./memory-engine/types.js").HarvestReport}
|
|
2535
|
+
* here instead of dropping it — trace/accounting/alerting is the deployment's call. Swallow-guarded:
|
|
2536
|
+
* a throwing consumer never fails the boundary. (The model-facing announcement lane is separate:
|
|
2537
|
+
* the engine enqueues gate events at its harvest tail; the NEXT session's first injection drains
|
|
2538
|
+
* them — 时机①.) Optional; unset ⇒ no behavior change beyond the report no longer being discarded.
|
|
2539
|
+
*/
|
|
2540
|
+
onMemoryHarvestReport?: (report: import("./memory-engine/types.js").HarvestReport, info: {
|
|
2541
|
+
sessionId: string;
|
|
2542
|
+
phase: "checkpoint" | "terminal";
|
|
2543
|
+
}) => void;
|
|
2544
|
+
/**
|
|
2545
|
+
* design/113 C4 — proactive project startup. The Runner calls this once during `prepareTask` (every prepare,
|
|
2546
|
+
* incl. durable resume — design/113 §4 H8) and injects the returned text as a READ-ONLY, FENCED, virtual
|
|
2547
|
+
* `"project"` memory layer at the TAIL (so the agent "sees" what project it is in from turn 1, like CC's
|
|
2548
|
+
* CLAUDE.md/git injection — the cure for "say hi → only greets"). The deployment/profile owns the CONTENT
|
|
2549
|
+
* (read CLAUDE.md / `.claude/` + fold in `git log -5`/status + a byte budget); core owns the seam + fence +
|
|
2550
|
+
* cache placement and NEVER hardcodes a filename (same trust posture as {@link executionEnvFactory}/
|
|
2551
|
+
* {@link promptProvider}/{@link modelKnowledgeCutoffs}). A RunnerDeps FUNCTION, not a `TaskSpec` field: it is
|
|
2552
|
+
* unserializable (durable resume) and reading files for an UNTRUSTED caller would be a confused-deputy hole
|
|
2553
|
+
* (design/44 §7 Q4). DECOUPLED from `memoryStore` — injects even with NO long-term memory configured (H5).
|
|
2554
|
+
*
|
|
2555
|
+
* `undefined` (default) ⇒ the whole path is skipped = byte-identical to today (full parity, H3). Returning
|
|
2556
|
+
* `null`/blank ⇒ no injection (also byte-identical). The content is fenced/sanitized like every other memory
|
|
2557
|
+
* layer (repo-controlled CLAUDE.md is UNTRUSTED data, not an instruction — H2). The ctx lets a profile tailor
|
|
2558
|
+
* or suppress: `handsEnabled:false` = a hands-less chat with no real project (return null); `isSubagent` =
|
|
2559
|
+
* a delegated child (a profile may trim CLAUDE.md for a cheap "grep this" subagent — H7).
|
|
2560
|
+
*/
|
|
2561
|
+
loadProjectMemory?: (ctx: {
|
|
2562
|
+
/** The task's working directory (= the execution env's cwd; a worktree task = its worktree root). */
|
|
2563
|
+
cwd: string;
|
|
2564
|
+
/** False ⇒ a hands-less chat (no real filesystem/project) — a profile typically returns null. */
|
|
2565
|
+
handsEnabled: boolean;
|
|
2566
|
+
/** True ⇒ a delegated subagent run (a profile may trim/suppress project content to control cost). */
|
|
2567
|
+
isSubagent: boolean;
|
|
2568
|
+
/** The subagent's type name, when `isSubagent` — lets a profile tailor content per agent type. */
|
|
2569
|
+
agentName?: string;
|
|
2570
|
+
}) => Promise<string | null | ProjectMemoryLoad> | string | null | ProjectMemoryLoad;
|
|
2571
|
+
/**
|
|
2572
|
+
* design/77 §2 Gate-2: the profile-injected predicate that decides whether a promotable artifact's
|
|
2573
|
+
* (opaque) outcome statistics clear the promotion bar. Core enforces the gate's *presence* (a promotable
|
|
2574
|
+
* write needs a verdict); this predicate supplies the *positivity* definition (the taxonomy/threshold
|
|
2575
|
+
* stays in the profile). **Unwired ⇒ promotable writes fail closed** (an absent gate never auto-passes).
|
|
2576
|
+
*/
|
|
2577
|
+
utilityGate?: import("./memory.js").UtilityGate;
|
|
2578
|
+
/**
|
|
2579
|
+
* @deprecated design/138 S4 — legacy memory consolidation (design/41) rode the retired memoryStore path
|
|
2580
|
+
* and no longer runs; ignored. (Engine-plane consolidation re-mount = design/138 §7, another稿.)
|
|
2581
|
+
* Type kept one major; removal is the next major.
|
|
2582
|
+
*/
|
|
2583
|
+
memoryConsolidation?: MemoryConsolidationConfig;
|
|
2584
|
+
/**
|
|
2585
|
+
* @deprecated design/138 S4 — selective recall (design/65 §2.2) served ONLY the retired legacy
|
|
2586
|
+
* `<user_memory>` injection path; ignored. The memory engine injects a bounded derived index instead
|
|
2587
|
+
* (MEMORY.md, CC parameters) and the model reads topic files on demand. Removal is the next major.
|
|
2588
|
+
*/
|
|
2589
|
+
memoryRecall?: {
|
|
2590
|
+
enabled?: boolean;
|
|
2591
|
+
/** Memory size (bytes) above which selective recall activates. Default 8000. */
|
|
2592
|
+
thresholdBytes?: number;
|
|
2593
|
+
/** Override the side-query selector; default = main-brain sub-query. */
|
|
2594
|
+
select?: import("./memory-recall.js").MemorySelector;
|
|
2595
|
+
/** Model for the default selector (default = the task's model). */
|
|
2596
|
+
selectorModel?: ModelRef;
|
|
2597
|
+
/** Max notes the side-query may select (default 5). */
|
|
2598
|
+
maxSelected?: number;
|
|
2599
|
+
/** Max 1-hop `[[name]]` link-followed notes appended after the selected ones (design/65 P3).
|
|
2600
|
+
* `0` disables link-following. Default 3. */
|
|
2601
|
+
maxLinked?: number;
|
|
2602
|
+
/** Side-query hard timeout (ms, default 5000). */
|
|
2603
|
+
timeoutMs?: number;
|
|
2604
|
+
};
|
|
2605
|
+
/** Override system-prompt assembly. Defaults to `defaultPromptProvider`. */
|
|
2606
|
+
promptProvider?: import("../prompts/default.js").PromptProvider;
|
|
2607
|
+
/**
|
|
2608
|
+
* design/99 §E23 — the LIVE-ONLY inbound-elicitation seam (an MCP server asking the END USER for input
|
|
2609
|
+
* mid-tool-call). Wired ONLY for servers that opted in via {@link McpServerSpec.elicitation}; absent ⇒ core
|
|
2610
|
+
* advertises no elicitation capability (fail-closed). The deployment answers synchronously (e.g. prompts the
|
|
2611
|
+
* terminal user); core replies to the server on the open connection.
|
|
2612
|
+
*/
|
|
2613
|
+
onElicit?: OnElicit;
|
|
2614
|
+
/**
|
|
2615
|
+
* design/116 CONFIRM-1 (clay 拍 加 seam 保体验): resize an over-limit MCP image so the model still SEES a
|
|
2616
|
+
* degraded image instead of a spill-to-disk note. Absent ⇒ core auto-detects `sharp` (dynamic import;
|
|
2617
|
+
* turnkey deployments with sharp installed get the CC experience with zero config) and otherwise spills.
|
|
2618
|
+
*/
|
|
2619
|
+
mcpImageResizer?: import("./mcp.js").McpImageResizer;
|
|
2620
|
+
/** Default tool-call gate for all tasks (a task's own `toolPolicy` overrides this). */
|
|
2621
|
+
toolPolicy?: import("./tool-policy.js").ToolPolicy;
|
|
2622
|
+
/**
|
|
2623
|
+
* How `ask` decisions resolve when a policy/hook requests human confirmation (design/37). Default
|
|
2624
|
+
* (omitted) = `"deny"`: **headless auto-deny** — no approver, so `ask` resolves deterministically to
|
|
2625
|
+
* deny with a model-readable reason (the safe default for stateless automation). `"allow"` to
|
|
2626
|
+
* auto-approve, or a fail-closed approver function. A task's own `onAsk` overrides this.
|
|
2627
|
+
*/
|
|
2628
|
+
onAsk?: import("./tool-policy.js").OnAsk;
|
|
2629
|
+
/** Content-ask seam (design/64 §5): when set, every task mounts an AskUserQuestion tool that routes a
|
|
2630
|
+
* model-issued question to this callback (a real human/UI). Distinct from `onAsk` (permission). A task's
|
|
2631
|
+
* own `onQuestion` overrides this. Unset ⇒ the tool is not mounted (the model can't ask). */
|
|
2632
|
+
onQuestion?: import("./ask-question.js").OnQuestion;
|
|
2633
|
+
/** LSP code-intelligence seam (design/64 §13.1): when set, every task mounts an `lsp` tool routed to this
|
|
2634
|
+
* manager (a deployment-provided language-server bridge, e.g. an E2B LSP sidecar). The manager returns
|
|
2635
|
+
* `undefined` for a file whose language has no server, and the tool degrades to "fall back to grep". A
|
|
2636
|
+
* task's own `lspManager` overrides this. Unset ⇒ no `lsp` tool. */
|
|
2637
|
+
lspManager?: import("./lsp.js").LspServerManager;
|
|
2638
|
+
/**
|
|
2639
|
+
* Default in-process hooks for all tasks (design/37): PreToolUse (rewrite/restrict args + inject
|
|
2640
|
+
* context), PostToolUse (rewrite output + inject context), UserPromptSubmit (block/inject before the
|
|
2641
|
+
* objective becomes a message). A task's own `hooks` overrides this. A PreToolUse hook's `allow`
|
|
2642
|
+
* never bypasses `toolPolicy` — the policy is always the final say.
|
|
2643
|
+
*/
|
|
2644
|
+
hooks?: import("./hooks.js").Hooks;
|
|
2645
|
+
/**
|
|
2646
|
+
* Policy for remote image URLs (`TaskSpec.images[].url`). Return false to reject. When set it
|
|
2647
|
+
* **replaces** the built-in SSRF guard (https-only + private/reserved-host block) — e.g. supply a
|
|
2648
|
+
* CDN allowlist, or a stricter resolve-and-pin check. Omit to use the safe default.
|
|
2649
|
+
*/
|
|
2650
|
+
allowImageUrl?: (url: string) => boolean;
|
|
2651
|
+
/**
|
|
2652
|
+
* Optional sink for best-effort background errors/warnings that are otherwise swallowed:
|
|
2653
|
+
* - `"compaction"` — a compaction failure (F8); a persistently failing one (flaky gateway, empty
|
|
2654
|
+
* summaries) is invisible without this and lets a session grow until it tops the window.
|
|
2655
|
+
* - `"prompt-cache"` — a legacy `PromptProvider.system` assembled a cache-hostile prompt (volatile
|
|
2656
|
+
* memory not at the tail); the prefix cache will miss every turn. Log/alert on both.
|
|
2657
|
+
* - `"prompt-constitution"` — a `stableSystem` provider returned an ALREADY-assembled prompt
|
|
2658
|
+
* (constitution anchor found); core passed it through un-doubled. Upgrade the provider to return
|
|
2659
|
+
* only the role base (or set `replaceAll: true` to own the whole base).
|
|
2660
|
+
* - `"memory"` — a post-task memory-consolidation pass failed or skipped a malformed reconcile
|
|
2661
|
+
* decision (design/41). Best-effort: the notes the model saved are kept; the task still succeeds.
|
|
2662
|
+
* - `"mcp"` — an MCP server failed to connect / list its tools and was skipped (fail-open, design/29);
|
|
2663
|
+
* the task runs with the remaining servers' tools. One call per failed server.
|
|
2664
|
+
*/
|
|
2665
|
+
onError?: (err: unknown, context: {
|
|
2666
|
+
phase: "compaction" | "prompt-cache" | "prompt-constitution" | "degraded" | "config" | "memory" | "mcp" | "interrupt-reconcile" | "suggestions" | "rewind" | "hook";
|
|
2667
|
+
sessionId: string;
|
|
2668
|
+
/**
|
|
2669
|
+
* Machine-readable sub-classification when the phase has one — currently the design/31
|
|
2670
|
+
* cache-break detector's root cause (`"model-switch" | "tool-schema" | "tool-set" |
|
|
2671
|
+
* "system-prefix" | "server-or-ttl"`). Lets the host pick its own log level: `"server-or-ttl"`
|
|
2672
|
+
* is usually benign in agentic tasks (slow tools ⇒ 5min+ request gaps expire provider caches —
|
|
2673
|
+
* service[64] flag②) and warrants info/warn, while the prefix-bug causes warrant attention.
|
|
2674
|
+
*/
|
|
2675
|
+
classification?: string;
|
|
2676
|
+
}) => void;
|
|
2677
|
+
/** Best-effort fire-and-forget trace sink (task/turn/brain/tool); `TaskSpec.tracer` overrides per task. */
|
|
2678
|
+
tracer?: import("./trace.js").TracerHook;
|
|
2679
|
+
/**
|
|
2680
|
+
* design/73 §1 v1 — fire-and-forget sink for {@link import("./task-outcome.js").TaskOutcome} facts
|
|
2681
|
+
* (the feedback ledger's core seam; tracer/onError posture — swallow-guarded, a throwing sink never
|
|
2682
|
+
* affects the run). 🔴 Red lines: core emits ONLY the `mechanical` tier (objective-oracle results —
|
|
2683
|
+
* llm_assisted/self-report never enter v1); every outcome carries `oracleHadRedRun`; ONE emission
|
|
2684
|
+
* point — `runGoal`'s terminal state (goal `doneCheck` = the natural mechanical oracle) plus explicit
|
|
2685
|
+
* `emitTaskOutcome` from harnesses that own a real oracle. Plain `runTask` never auto-emits (no
|
|
2686
|
+
* objective oracle → no fact). core emits facts only; aggregation/policy live in the service ledger.
|
|
2687
|
+
*/
|
|
2688
|
+
onTaskOutcome?: (outcome: import("./task-outcome.js").TaskOutcome) => void;
|
|
2689
|
+
/** Per-model pricing (per-1M absolute USD) keyed by model id; falls back to each `Model.cost`. */
|
|
2690
|
+
pricing?: Record<string, import("./pricing.js").ModelPricing>;
|
|
2691
|
+
/**
|
|
2692
|
+
* The execution environment the agent's "hand" acts on (design/44) — file system + shell. Default:
|
|
2693
|
+
* `StubExecutionEnv` (no real I/O, current behavior). Inject `NodeExecutionEnv` for local fs/shell, or
|
|
2694
|
+
* a sandboxed/remote impl for multi-tenant isolation. **Injecting a non-stub env is the opt-in** that
|
|
2695
|
+
* activates the file tool band. ⚠️ A bare `NodeExecutionEnv` is unsandboxed — a multi-tenant deployment
|
|
2696
|
+
* MUST inject a chroot/container/per-principal-scoped impl; do not expose raw `NodeExecutionEnv`.
|
|
2697
|
+
*/
|
|
2698
|
+
executionEnv?: import("../internal/harness.js").ExecutionEnv;
|
|
2699
|
+
/**
|
|
2700
|
+
* design/48 remote seam — a **trusted control-plane** factory that mints a FRESH execution env per
|
|
2701
|
+
* task (e.g. one isolated container per task in the remote model). Called once at task start; the env
|
|
2702
|
+
* it returns is owned by that task and released on task end. **Wins over** the shared static
|
|
2703
|
+
* `executionEnv`. Injecting it also activates the hand tool band (design/44), exactly like
|
|
2704
|
+
* `executionEnv`. This is the ONLY per-task env injection point — `TaskSpec` deliberately has no
|
|
2705
|
+
* `executionEnv`, so an untrusted caller can't swap the sandbox (design/44 §7 Q4); the trusted
|
|
2706
|
+
* deployment wires the factory.
|
|
2707
|
+
*/
|
|
2708
|
+
executionEnvFactory?: import("./remote-env.js").ExecutionEnvFactory;
|
|
2709
|
+
/**
|
|
2710
|
+
* design/77 §1 Gate-1 (oracleIsolation) — a **DISTINCT** trusted control-plane factory that mints the
|
|
2711
|
+
* ISOLATED grader env an out-of-process oracle grades in (the 4th auto-promote gate). It is a SIBLING of
|
|
2712
|
+
* {@link executionEnvFactory}, never the same env: the worker runs in `executionEnvFactory`'s env, the
|
|
2713
|
+
* grader in `graderEnvFactory`'s — so a worker can't corrupt the env that judges it. It inherits the exact
|
|
2714
|
+
* same trust contract: `TaskSpec` deliberately has NO env field (design/44 §7 Q4), so an untrusted caller
|
|
2715
|
+
* can never inject/swap a grader env and grade itself; only the trusted deployment wires this factory. The
|
|
2716
|
+
* env it mints is wrapped in a {@link import("./oracle-isolation.js").GraderEnv} (with the control-plane
|
|
2717
|
+
* `provenance` brand) at the call site, and asserted via
|
|
2718
|
+
* {@link import("./oracle-isolation.js").assertOracleIsolation} before any positive oracle verdict.
|
|
2719
|
+
* **Auto-promote stays mandate-OFF until the four gates are implemented + verified end-to-end** (design/77
|
|
2720
|
+
* §7); this seam only makes auto-accept implementable — it does not turn it on.
|
|
2721
|
+
*/
|
|
2722
|
+
graderEnvFactory?: import("./remote-env.js").ExecutionEnvFactory;
|
|
2723
|
+
/**
|
|
2724
|
+
* Containment root for the file tools (design/44 §4 invariant 7): every path must resolve within it,
|
|
2725
|
+
* else the tool rejects (`PathNotInRoot`). Default `process.cwd()`. A defense-in-depth guard rail at the
|
|
2726
|
+
* tool layer — NOT a sandbox (it does not constrain `bash`; that needs OS-level containment) and not a
|
|
2727
|
+
* substitute for an isolated `executionEnv`.
|
|
2728
|
+
*/
|
|
2729
|
+
rootPath?: string;
|
|
2730
|
+
/**
|
|
2731
|
+
* Backing store for offloaded large tool results (design/30). Default: a task-scoped
|
|
2732
|
+
* `InMemoryToolResultStore` (no cross-wake durability). Inject a durable store (keyed by ref) so an
|
|
2733
|
+
* offloaded result survives wake/resume.
|
|
2734
|
+
*/
|
|
2735
|
+
toolResultStore?: import("./tool-result-store.js").ToolResultStore;
|
|
2736
|
+
/**
|
|
2737
|
+
* Offload a tool result to the store + leave a preview when its text exceeds this many chars. Default
|
|
2738
|
+
* ~20000; set `0` or `Infinity` to disable offloading. Per-tool override via `ToolSpec.offloadThresholdChars`.
|
|
2739
|
+
*/
|
|
2740
|
+
toolResultThresholdChars?: number;
|
|
2741
|
+
/**
|
|
2742
|
+
* Two-phase prefix-cache-break detection (design/31): per turn, fingerprint the prefix and, on a
|
|
2743
|
+
* confirmed `cacheRead` drop, emit a root-cause finding via `onError(phase:"prompt-cache")`. Cheap
|
|
2744
|
+
* (hashes only) and only fires on a detected break. Default **on**; set `false` to disable.
|
|
2745
|
+
*/
|
|
2746
|
+
cacheBreakDetection?: boolean;
|
|
2747
|
+
/**
|
|
2748
|
+
* Aggregate inline-MEDIA (image) byte budget for the request (batch-C/§17.2 sibling of the text budget;
|
|
2749
|
+
* CC 2.1.196 `tengu_media_byte_cap` parity). Image reads (`Read` → ImageContent) are per-image-capped but
|
|
2750
|
+
* accumulate across turns; this bounds the SUM in the request by stripping the OLDEST images (replaced with a
|
|
2751
|
+
* marker) — request-only, non-destructive (the durable session keeps the image; the model can re-Read it).
|
|
2752
|
+
* Default {@link AGGREGATE_MEDIA_BUDGET_BYTES}; set `Infinity`/`0` to disable.
|
|
2753
|
+
*/
|
|
2754
|
+
mediaByteCapBytes?: number;
|
|
2755
|
+
/** Optional telemetry fired when {@link mediaByteCapBytes} strips media in a request (CC's
|
|
2756
|
+
* `tengu_media_byte_cap_stripped` fields). Pure observability — no effect on the request. */
|
|
2757
|
+
onMediaStripped?: (info: {
|
|
2758
|
+
totalBytes: number;
|
|
2759
|
+
limitBytes: number;
|
|
2760
|
+
removedCount: number;
|
|
2761
|
+
removedBytes: number;
|
|
2762
|
+
}) => void;
|
|
2763
|
+
/**
|
|
2764
|
+
* Deferred-tool disclosure policy (design/36). Default (omitted): deterministic per-tool — only tools
|
|
2765
|
+
* with `ToolSpec.defer === true` (and MCP tools, which default to deferred) are deferred, so the same
|
|
2766
|
+
* `TaskSpec` always yields the same `tools[]`. `"auto"`: additionally auto-defer tools when the total
|
|
2767
|
+
* inlined schema size would exceed a fraction of the model's context window. Auto is an explicit opt-in
|
|
2768
|
+
* (council minor #6) because an implicit threshold makes `tools[]` depend on the model/context, which
|
|
2769
|
+
* callers find hard to predict; explicit `defer` flags always win regardless of this setting.
|
|
2770
|
+
*/
|
|
2771
|
+
deferMode?: "auto";
|
|
2772
|
+
/**
|
|
2773
|
+
* design/84 Seam C — compact-boundary COST optimization (data-gated, default OFF). A FUNCTION seam (a
|
|
2774
|
+
* trusted control-plane injection), so it lives on `RunnerDeps` — NOT `TaskSpec`: `TaskSpec` is the
|
|
2775
|
+
* serializable, untrusted-caller, durable-resume-round-trippable per-task config (a function can be
|
|
2776
|
+
* neither serialized nor durably checkpointed, and the sandbox/env-class injections deliberately sit on
|
|
2777
|
+
* `RunnerDeps` for the same trust reason). Same placement as `memoryRecall.select` / `promptProvider` /
|
|
2778
|
+
* `executionEnvFactory`.
|
|
2779
|
+
*
|
|
2780
|
+
* When `summaryProvider` is set, BOTH compaction call sites (the within-task turn boundary AND `finish()`
|
|
2781
|
+
* at task end) consult it: a NON-EMPTY string is reused verbatim (the real `generateSummary` LLM call is
|
|
2782
|
+
* skipped); `null`/`undefined`/blank falls back to the existing LLM path (byte-identical to today).
|
|
2783
|
+
* `onCompaction` is a pure post-compaction observer. `maxConsecutiveProviderReuse` (default 3, CC parity)
|
|
2784
|
+
* forces a real summary after N consecutive reuses to bound drift; the Runner OWNS the consecutive-reuse
|
|
2785
|
+
* counter across both call sites for the task (reset on a real summary, incremented on a reused one), so
|
|
2786
|
+
* the caller does not have to thread it back. **Absent (default) ⇒ no behavior change whatsoever.**
|
|
2787
|
+
*
|
|
2788
|
+
* SCOPE (design/141 examples 批实测): the seam covers the whole-turn compaction sites only. A
|
|
2789
|
+
* SPLIT-TURN cut point (mid-turn prefix summarization — the common shape inside a long single-user-
|
|
2790
|
+
* message tool loop) bypasses the provider by design (A2 algorithm sovereignty): the turn-prefix
|
|
2791
|
+
* summary is engine-owned. Deployments needing a clean provider-visible boundary should shape work
|
|
2792
|
+
* as separate tasks sharing `sessionId`.
|
|
2793
|
+
*/
|
|
2794
|
+
summaryProvider?: import("./auto-compaction.js").MaybeCompactOptions["summaryProvider"];
|
|
2795
|
+
/** design/84 Seam C — pure post-compaction observer (fires only on a real compaction, never a no-op).
|
|
2796
|
+
* Consumed ONLY when `summaryProvider` is also set (the Seam C options early-return otherwise) — a
|
|
2797
|
+
* pure-observer deployment passes a provider that always returns `null` (keeps the LLM path intact). */
|
|
2798
|
+
onCompaction?: import("./auto-compaction.js").MaybeCompactOptions["onCompaction"];
|
|
2799
|
+
/** design/84 Seam C — force a real `generateSummary` after this many consecutive provider reuses (default
|
|
2800
|
+
* 3, CC parity). The Runner tracks the consecutive-reuse counter per task across both compaction sites. */
|
|
2801
|
+
maxConsecutiveProviderReuse?: number;
|
|
2802
|
+
/**
|
|
2803
|
+
* design/86 §3 缺口 A — DYNAMIC memory re-recall (CC `processSessionStartHooks('compact')` parity),
|
|
2804
|
+
* **opt-in & default OFF** (data-gated, like Seam C `summaryProvider`). Absent/`enabled:false` ⇒ NO behavior
|
|
2805
|
+
* change whatsoever: memory is the one-shot snapshot taken at task start (the stable prefix), exactly as today.
|
|
2806
|
+
*
|
|
2807
|
+
* When enabled, AFTER each REAL within-task compaction the Runner re-runs the EXISTING memory selector against
|
|
2808
|
+
* the CURRENT conversation (the most-recent messages), de-dups against everything already surfaced (the same
|
|
2809
|
+
* `priorSurfacedIds`/`priorSurfacedKeys` machinery the initial recall uses, seeded from the initial recall),
|
|
2810
|
+
* and injects any NEW relevant notes as a TAIL attachment user message (`harness.steer` → next request's tail).
|
|
2811
|
+
* It NEVER touches the stable system prefix (the prefix-cache the whole design rests on) and NEVER re-injects
|
|
2812
|
+
* an already-shown note. It needs a selective-capable store (`listStructuredNotes`/`getByIds`) + a selector
|
|
2813
|
+
* (the `memoryRecall.select` override, else the default brain sub-query); on selector failure/timeout it injects
|
|
2814
|
+
* nothing (no inject-all fallback mid-task). A FUNCTION/observer seam, so it lives on `RunnerDeps`, NOT `TaskSpec`
|
|
2815
|
+
* (the same trust placement as `memoryRecall.select` / `summaryProvider` / `executionEnvFactory`).
|
|
2816
|
+
*
|
|
2817
|
+
* Why compaction-triggered (not every turn): compaction is when fine detail is actually lost (the highest-value
|
|
2818
|
+
* moment to reground, CC parity); firing only post-compaction also bounds the extra selector LLM call (whether
|
|
2819
|
+
* the cost is worth it is a design/82 cost-per-truly-correct data-gated question — this is a THIN seam, no
|
|
2820
|
+
* provider/policy beyond the trigger is built in).
|
|
2821
|
+
*
|
|
2822
|
+
* @deprecated design/138 S4 — the dynamic re-recall seam served ONLY the retired legacy memoryStore
|
|
2823
|
+
* injection path; ignored (prepareTask never wires the seam state anymore). Removal is the next major.
|
|
2824
|
+
*/
|
|
2825
|
+
dynamicRecall?: import("./dynamic-recall.js").DynamicRecallConfig;
|
|
2826
|
+
}
|
|
2827
|
+
export type { AgentTool, Model, StreamFn, ThinkingLevel };
|
|
2828
|
+
//# sourceMappingURL=types.d.ts.map
|