@sema-agent/core 1.279.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +104 -0
- package/NOTICE.md +30 -0
- package/README.md +143 -0
- package/README.zh-CN.md +138 -0
- package/dist/agents/agent-definition.d.ts +3 -0
- package/dist/agents/agent-definition.d.ts.map +1 -0
- package/dist/agents/agent-definition.js +9 -0
- package/dist/agents/agent-definition.js.map +1 -0
- package/dist/agents/builtin-agents.d.ts +9 -0
- package/dist/agents/builtin-agents.d.ts.map +1 -0
- package/dist/agents/builtin-agents.js +114 -0
- package/dist/agents/builtin-agents.js.map +1 -0
- package/dist/agents/cascade.d.ts +44 -0
- package/dist/agents/cascade.d.ts.map +1 -0
- package/dist/agents/cascade.js +153 -0
- package/dist/agents/cascade.js.map +1 -0
- package/dist/agents/observer.d.ts +122 -0
- package/dist/agents/observer.d.ts.map +1 -0
- package/dist/agents/observer.js +365 -0
- package/dist/agents/observer.js.map +1 -0
- package/dist/agents/repair-loop.d.ts +49 -0
- package/dist/agents/repair-loop.d.ts.map +1 -0
- package/dist/agents/repair-loop.js +147 -0
- package/dist/agents/repair-loop.js.map +1 -0
- package/dist/agents/session-util.d.ts +3 -0
- package/dist/agents/session-util.d.ts.map +1 -0
- package/dist/agents/session-util.js +4 -0
- package/dist/agents/session-util.js.map +1 -0
- package/dist/agents/subagent-steps.d.ts +31 -0
- package/dist/agents/subagent-steps.d.ts.map +1 -0
- package/dist/agents/subagent-steps.js +167 -0
- package/dist/agents/subagent-steps.js.map +1 -0
- package/dist/agents/subagent.d.ts +152 -0
- package/dist/agents/subagent.d.ts.map +1 -0
- package/dist/agents/subagent.js +1698 -0
- package/dist/agents/subagent.js.map +1 -0
- package/dist/agents/suspend-guard.d.ts +6 -0
- package/dist/agents/suspend-guard.d.ts.map +1 -0
- package/dist/agents/suspend-guard.js +19 -0
- package/dist/agents/suspend-guard.js.map +1 -0
- package/dist/agents/teacher.d.ts +70 -0
- package/dist/agents/teacher.d.ts.map +1 -0
- package/dist/agents/teacher.js +462 -0
- package/dist/agents/teacher.js.map +1 -0
- package/dist/agents/team.d.ts +92 -0
- package/dist/agents/team.d.ts.map +1 -0
- package/dist/agents/team.js +231 -0
- package/dist/agents/team.js.map +1 -0
- package/dist/agents/tool-filter.d.ts +4 -0
- package/dist/agents/tool-filter.d.ts.map +1 -0
- package/dist/agents/tool-filter.js +18 -0
- package/dist/agents/tool-filter.js.map +1 -0
- package/dist/agents/verify.d.ts +46 -0
- package/dist/agents/verify.d.ts.map +1 -0
- package/dist/agents/verify.js +177 -0
- package/dist/agents/verify.js.map +1 -0
- package/dist/bench/metrics.d.ts +259 -0
- package/dist/bench/metrics.d.ts.map +1 -0
- package/dist/bench/metrics.js +439 -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 +373 -0
- package/dist/bin/sema-tb.js.map +1 -0
- package/dist/bin/tb-env.d.ts +2 -0
- package/dist/bin/tb-env.d.ts.map +1 -0
- package/dist/bin/tb-env.js +15 -0
- package/dist/bin/tb-env.js.map +1 -0
- package/dist/brain/anthropic.d.ts +16 -0
- package/dist/brain/anthropic.d.ts.map +1 -0
- package/dist/brain/anthropic.js +635 -0
- package/dist/brain/anthropic.js.map +1 -0
- package/dist/brain/circuit-breaker.d.ts +26 -0
- package/dist/brain/circuit-breaker.d.ts.map +1 -0
- package/dist/brain/circuit-breaker.js +118 -0
- package/dist/brain/circuit-breaker.js.map +1 -0
- package/dist/brain/degrading.d.ts +33 -0
- package/dist/brain/degrading.d.ts.map +1 -0
- package/dist/brain/degrading.js +175 -0
- package/dist/brain/degrading.js.map +1 -0
- package/dist/brain/errors.d.ts +14 -0
- package/dist/brain/errors.d.ts.map +1 -0
- package/dist/brain/errors.js +43 -0
- package/dist/brain/errors.js.map +1 -0
- package/dist/brain/failover.d.ts +3 -0
- package/dist/brain/failover.d.ts.map +1 -0
- package/dist/brain/failover.js +85 -0
- package/dist/brain/failover.js.map +1 -0
- package/dist/brain/model-presets.d.ts +5 -0
- package/dist/brain/model-presets.d.ts.map +1 -0
- package/dist/brain/model-presets.js +30 -0
- package/dist/brain/model-presets.js.map +1 -0
- package/dist/brain/openai.d.ts +13 -0
- package/dist/brain/openai.d.ts.map +1 -0
- package/dist/brain/openai.js +581 -0
- package/dist/brain/openai.js.map +1 -0
- package/dist/brain/reasoning.d.ts +33 -0
- package/dist/brain/reasoning.d.ts.map +1 -0
- package/dist/brain/reasoning.js +84 -0
- package/dist/brain/reasoning.js.map +1 -0
- package/dist/brain/repetition.d.ts +16 -0
- package/dist/brain/repetition.d.ts.map +1 -0
- package/dist/brain/repetition.js +96 -0
- package/dist/brain/repetition.js.map +1 -0
- package/dist/brain/request-params.d.ts +6 -0
- package/dist/brain/request-params.d.ts.map +1 -0
- package/dist/brain/request-params.js +44 -0
- package/dist/brain/request-params.js.map +1 -0
- package/dist/brain/retry.d.ts +3 -0
- package/dist/brain/retry.d.ts.map +1 -0
- package/dist/brain/retry.js +23 -0
- package/dist/brain/retry.js.map +1 -0
- package/dist/brain/routing.d.ts +7 -0
- package/dist/brain/routing.d.ts.map +1 -0
- package/dist/brain/routing.js +34 -0
- package/dist/brain/routing.js.map +1 -0
- package/dist/brain/status-sink.d.ts +27 -0
- package/dist/brain/status-sink.d.ts.map +1 -0
- package/dist/brain/status-sink.js +20 -0
- package/dist/brain/status-sink.js.map +1 -0
- package/dist/brain/stream-engine.d.ts +37 -0
- package/dist/brain/stream-engine.d.ts.map +1 -0
- package/dist/brain/stream-engine.js +295 -0
- package/dist/brain/stream-engine.js.map +1 -0
- package/dist/brain/timeout.d.ts +12 -0
- package/dist/brain/timeout.d.ts.map +1 -0
- package/dist/brain/timeout.js +34 -0
- package/dist/brain/timeout.js.map +1 -0
- package/dist/brain/tool-call-repair.d.ts +6 -0
- package/dist/brain/tool-call-repair.d.ts.map +1 -0
- package/dist/brain/tool-call-repair.js +58 -0
- package/dist/brain/tool-call-repair.js.map +1 -0
- package/dist/brain/walltime.d.ts +2 -0
- package/dist/brain/walltime.d.ts.map +1 -0
- package/dist/brain/walltime.js +2 -0
- package/dist/brain/walltime.js.map +1 -0
- package/dist/core/arg-summary.d.ts +3 -0
- package/dist/core/arg-summary.d.ts.map +1 -0
- package/dist/core/arg-summary.js +76 -0
- package/dist/core/arg-summary.js.map +1 -0
- package/dist/core/ask-question.d.ts +36 -0
- package/dist/core/ask-question.d.ts.map +1 -0
- package/dist/core/ask-question.js +171 -0
- package/dist/core/ask-question.js.map +1 -0
- package/dist/core/auto-compaction.d.ts +88 -0
- package/dist/core/auto-compaction.d.ts.map +1 -0
- package/dist/core/auto-compaction.js +253 -0
- package/dist/core/auto-compaction.js.map +1 -0
- package/dist/core/auto-mode-prompt-assets.d.ts +3 -0
- package/dist/core/auto-mode-prompt-assets.d.ts.map +1 -0
- package/dist/core/auto-mode-prompt-assets.js +3 -0
- package/dist/core/auto-mode-prompt-assets.js.map +1 -0
- package/dist/core/auto-mode-prompt.d.ts +22 -0
- package/dist/core/auto-mode-prompt.d.ts.map +1 -0
- package/dist/core/auto-mode-prompt.js +84 -0
- package/dist/core/auto-mode-prompt.js.map +1 -0
- package/dist/core/auto-mode.d.ts +35 -0
- package/dist/core/auto-mode.d.ts.map +1 -0
- package/dist/core/auto-mode.js +100 -0
- package/dist/core/auto-mode.js.map +1 -0
- package/dist/core/auto-promote.d.ts +26 -0
- package/dist/core/auto-promote.d.ts.map +1 -0
- package/dist/core/auto-promote.js +93 -0
- package/dist/core/auto-promote.js.map +1 -0
- package/dist/core/background-shell.d.ts +41 -0
- package/dist/core/background-shell.d.ts.map +1 -0
- package/dist/core/background-shell.js +21 -0
- package/dist/core/background-shell.js.map +1 -0
- package/dist/core/cache-break-detector.d.ts +29 -0
- package/dist/core/cache-break-detector.d.ts.map +1 -0
- package/dist/core/cache-break-detector.js +80 -0
- package/dist/core/cache-break-detector.js.map +1 -0
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.d.ts.map +1 -0
- package/dist/core/canonical-json.js +68 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/checkpoint-store.d.ts +257 -0
- package/dist/core/checkpoint-store.d.ts.map +1 -0
- package/dist/core/checkpoint-store.js +292 -0
- package/dist/core/checkpoint-store.js.map +1 -0
- package/dist/core/consolidate-scope.d.ts +19 -0
- package/dist/core/consolidate-scope.d.ts.map +1 -0
- package/dist/core/consolidate-scope.js +96 -0
- package/dist/core/consolidate-scope.js.map +1 -0
- package/dist/core/context-edit.d.ts +18 -0
- package/dist/core/context-edit.d.ts.map +1 -0
- package/dist/core/context-edit.js +98 -0
- package/dist/core/context-edit.js.map +1 -0
- package/dist/core/context-guard.d.ts +14 -0
- package/dist/core/context-guard.d.ts.map +1 -0
- package/dist/core/context-guard.js +110 -0
- package/dist/core/context-guard.js.map +1 -0
- package/dist/core/dynamic-recall.d.ts +33 -0
- package/dist/core/dynamic-recall.d.ts.map +1 -0
- package/dist/core/dynamic-recall.js +77 -0
- package/dist/core/dynamic-recall.js.map +1 -0
- package/dist/core/exec-gate.d.ts +30 -0
- package/dist/core/exec-gate.d.ts.map +1 -0
- package/dist/core/exec-gate.js +106 -0
- package/dist/core/exec-gate.js.map +1 -0
- package/dist/core/exec-output-tail.d.ts +15 -0
- package/dist/core/exec-output-tail.d.ts.map +1 -0
- package/dist/core/exec-output-tail.js +39 -0
- package/dist/core/exec-output-tail.js.map +1 -0
- package/dist/core/file-snapshot-store.d.ts +53 -0
- package/dist/core/file-snapshot-store.d.ts.map +1 -0
- package/dist/core/file-snapshot-store.js +244 -0
- package/dist/core/file-snapshot-store.js.map +1 -0
- package/dist/core/git-worktree-env.d.ts +16 -0
- package/dist/core/git-worktree-env.d.ts.map +1 -0
- package/dist/core/git-worktree-env.js +40 -0
- package/dist/core/git-worktree-env.js.map +1 -0
- package/dist/core/hooks.d.ts +128 -0
- package/dist/core/hooks.d.ts.map +1 -0
- package/dist/core/hooks.js +184 -0
- package/dist/core/hooks.js.map +1 -0
- package/dist/core/lsp-diagnostics.d.ts +31 -0
- package/dist/core/lsp-diagnostics.d.ts.map +1 -0
- package/dist/core/lsp-diagnostics.js +79 -0
- package/dist/core/lsp-diagnostics.js.map +1 -0
- package/dist/core/lsp-protocol.d.ts +10 -0
- package/dist/core/lsp-protocol.d.ts.map +1 -0
- package/dist/core/lsp-protocol.js +136 -0
- package/dist/core/lsp-protocol.js.map +1 -0
- package/dist/core/lsp-session.d.ts +27 -0
- package/dist/core/lsp-session.d.ts.map +1 -0
- package/dist/core/lsp-session.js +134 -0
- package/dist/core/lsp-session.js.map +1 -0
- package/dist/core/lsp.d.ts +56 -0
- package/dist/core/lsp.d.ts.map +1 -0
- package/dist/core/lsp.js +130 -0
- package/dist/core/lsp.js.map +1 -0
- package/dist/core/mcp.d.ts +108 -0
- package/dist/core/mcp.d.ts.map +1 -0
- package/dist/core/mcp.js +692 -0
- package/dist/core/mcp.js.map +1 -0
- package/dist/core/media-byte-cap.d.ts +13 -0
- package/dist/core/media-byte-cap.d.ts.map +1 -0
- package/dist/core/media-byte-cap.js +51 -0
- package/dist/core/media-byte-cap.js.map +1 -0
- package/dist/core/memory-engine/data-plane.d.ts +60 -0
- package/dist/core/memory-engine/data-plane.d.ts.map +1 -0
- package/dist/core/memory-engine/data-plane.js +198 -0
- package/dist/core/memory-engine/data-plane.js.map +1 -0
- package/dist/core/memory-engine/dual-root.d.ts +16 -0
- package/dist/core/memory-engine/dual-root.d.ts.map +1 -0
- package/dist/core/memory-engine/dual-root.js +75 -0
- package/dist/core/memory-engine/dual-root.js.map +1 -0
- package/dist/core/memory-engine/engine.d.ts +67 -0
- package/dist/core/memory-engine/engine.d.ts.map +1 -0
- package/dist/core/memory-engine/engine.js +828 -0
- package/dist/core/memory-engine/engine.js.map +1 -0
- package/dist/core/memory-engine/file-backend.d.ts +55 -0
- package/dist/core/memory-engine/file-backend.d.ts.map +1 -0
- package/dist/core/memory-engine/file-backend.js +752 -0
- package/dist/core/memory-engine/file-backend.js.map +1 -0
- package/dist/core/memory-engine/frontmatter.d.ts +13 -0
- package/dist/core/memory-engine/frontmatter.d.ts.map +1 -0
- package/dist/core/memory-engine/frontmatter.js +119 -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 +12 -0
- package/dist/core/memory-engine/index.js.map +1 -0
- package/dist/core/memory-engine/layout.d.ts +44 -0
- package/dist/core/memory-engine/layout.d.ts.map +1 -0
- package/dist/core/memory-engine/layout.js +459 -0
- package/dist/core/memory-engine/layout.js.map +1 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts +10 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts.map +1 -0
- package/dist/core/memory-engine/memory-backend-contract.js +269 -0
- package/dist/core/memory-engine/memory-backend-contract.js.map +1 -0
- package/dist/core/memory-engine/migrate.d.ts +8 -0
- package/dist/core/memory-engine/migrate.d.ts.map +1 -0
- package/dist/core/memory-engine/migrate.js +23 -0
- package/dist/core/memory-engine/migrate.js.map +1 -0
- package/dist/core/memory-engine/scan.d.ts +8 -0
- package/dist/core/memory-engine/scan.d.ts.map +1 -0
- package/dist/core/memory-engine/scan.js +49 -0
- package/dist/core/memory-engine/scan.js.map +1 -0
- package/dist/core/memory-engine/scope-contract.d.ts +44 -0
- package/dist/core/memory-engine/scope-contract.d.ts.map +1 -0
- package/dist/core/memory-engine/scope-contract.js +205 -0
- package/dist/core/memory-engine/scope-contract.js.map +1 -0
- package/dist/core/memory-engine/sync-client.d.ts +57 -0
- package/dist/core/memory-engine/sync-client.d.ts.map +1 -0
- package/dist/core/memory-engine/sync-client.js +257 -0
- package/dist/core/memory-engine/sync-client.js.map +1 -0
- package/dist/core/memory-engine/sync.d.ts +37 -0
- package/dist/core/memory-engine/sync.d.ts.map +1 -0
- package/dist/core/memory-engine/sync.js +68 -0
- package/dist/core/memory-engine/sync.js.map +1 -0
- package/dist/core/memory-engine/types.d.ts +128 -0
- package/dist/core/memory-engine/types.d.ts.map +1 -0
- package/dist/core/memory-engine/types.js +2 -0
- package/dist/core/memory-engine/types.js.map +1 -0
- package/dist/core/memory-recall.d.ts +82 -0
- package/dist/core/memory-recall.d.ts.map +1 -0
- package/dist/core/memory-recall.js +352 -0
- package/dist/core/memory-recall.js.map +1 -0
- package/dist/core/memory-vector.d.ts +4 -0
- package/dist/core/memory-vector.d.ts.map +1 -0
- package/dist/core/memory-vector.js +31 -0
- package/dist/core/memory-vector.js.map +1 -0
- package/dist/core/memory.d.ts +112 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +512 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/message-utils.d.ts +4 -0
- package/dist/core/message-utils.d.ts.map +1 -0
- package/dist/core/message-utils.js +7 -0
- package/dist/core/message-utils.js.map +1 -0
- package/dist/core/oracle-isolation.d.ts +16 -0
- package/dist/core/oracle-isolation.d.ts.map +1 -0
- package/dist/core/oracle-isolation.js +50 -0
- package/dist/core/oracle-isolation.js.map +1 -0
- package/dist/core/permission-rules.d.ts +35 -0
- package/dist/core/permission-rules.d.ts.map +1 -0
- package/dist/core/permission-rules.js +270 -0
- package/dist/core/permission-rules.js.map +1 -0
- package/dist/core/present-plan-tool.d.ts +8 -0
- package/dist/core/present-plan-tool.d.ts.map +1 -0
- package/dist/core/present-plan-tool.js +82 -0
- package/dist/core/present-plan-tool.js.map +1 -0
- package/dist/core/pricing.d.ts +22 -0
- package/dist/core/pricing.d.ts.map +1 -0
- package/dist/core/pricing.js +23 -0
- package/dist/core/pricing.js.map +1 -0
- package/dist/core/property-harness.d.ts +40 -0
- package/dist/core/property-harness.d.ts.map +1 -0
- package/dist/core/property-harness.js +121 -0
- package/dist/core/property-harness.js.map +1 -0
- package/dist/core/push-queue.d.ts +9 -0
- package/dist/core/push-queue.d.ts.map +1 -0
- package/dist/core/push-queue.js +41 -0
- package/dist/core/push-queue.js.map +1 -0
- package/dist/core/remote-env.d.ts +105 -0
- package/dist/core/remote-env.d.ts.map +1 -0
- package/dist/core/remote-env.js +27 -0
- package/dist/core/remote-env.js.map +1 -0
- package/dist/core/roles.d.ts +35 -0
- package/dist/core/roles.d.ts.map +1 -0
- package/dist/core/roles.js +182 -0
- package/dist/core/roles.js.map +1 -0
- package/dist/core/runner/active-skill-scope.d.ts +26 -0
- package/dist/core/runner/active-skill-scope.d.ts.map +1 -0
- package/dist/core/runner/active-skill-scope.js +116 -0
- package/dist/core/runner/active-skill-scope.js.map +1 -0
- package/dist/core/runner/assemble-result.d.ts +89 -0
- package/dist/core/runner/assemble-result.d.ts.map +1 -0
- package/dist/core/runner/assemble-result.js +141 -0
- package/dist/core/runner/assemble-result.js.map +1 -0
- package/dist/core/runner/call-cap.d.ts +38 -0
- package/dist/core/runner/call-cap.d.ts.map +1 -0
- package/dist/core/runner/call-cap.js +76 -0
- package/dist/core/runner/call-cap.js.map +1 -0
- package/dist/core/runner/grounding-signal.d.ts +2 -0
- package/dist/core/runner/grounding-signal.d.ts.map +1 -0
- package/dist/core/runner/grounding-signal.js +32 -0
- package/dist/core/runner/grounding-signal.js.map +1 -0
- package/dist/core/runner/image.d.ts +6 -0
- package/dist/core/runner/image.d.ts.map +1 -0
- package/dist/core/runner/image.js +116 -0
- package/dist/core/runner/image.js.map +1 -0
- package/dist/core/runner/memory-consolidation.d.ts +52 -0
- package/dist/core/runner/memory-consolidation.d.ts.map +1 -0
- package/dist/core/runner/memory-consolidation.js +253 -0
- package/dist/core/runner/memory-consolidation.js.map +1 -0
- package/dist/core/runner/prepare-task.d.ts +219 -0
- package/dist/core/runner/prepare-task.d.ts.map +1 -0
- package/dist/core/runner/prepare-task.js +2087 -0
- package/dist/core/runner/prepare-task.js.map +1 -0
- package/dist/core/runner/prompt-suggestions.d.ts +26 -0
- package/dist/core/runner/prompt-suggestions.d.ts.map +1 -0
- package/dist/core/runner/prompt-suggestions.js +104 -0
- package/dist/core/runner/prompt-suggestions.js.map +1 -0
- package/dist/core/runner/runtask.d.ts +53 -0
- package/dist/core/runner/runtask.d.ts.map +1 -0
- package/dist/core/runner/runtask.js +2703 -0
- package/dist/core/runner/runtask.js.map +1 -0
- package/dist/core/runner/session-rule-policy.d.ts +11 -0
- package/dist/core/runner/session-rule-policy.d.ts.map +1 -0
- package/dist/core/runner/session-rule-policy.js +76 -0
- package/dist/core/runner/session-rule-policy.js.map +1 -0
- package/dist/core/runner/strict-output-schema.d.ts +21 -0
- package/dist/core/runner/strict-output-schema.d.ts.map +1 -0
- package/dist/core/runner/strict-output-schema.js +304 -0
- package/dist/core/runner/strict-output-schema.js.map +1 -0
- package/dist/core/runner/synthetic-tools.d.ts +30 -0
- package/dist/core/runner/synthetic-tools.d.ts.map +1 -0
- package/dist/core/runner/synthetic-tools.js +124 -0
- package/dist/core/runner/synthetic-tools.js.map +1 -0
- package/dist/core/runner/tool-disclosure.d.ts +46 -0
- package/dist/core/runner/tool-disclosure.d.ts.map +1 -0
- package/dist/core/runner/tool-disclosure.js +220 -0
- package/dist/core/runner/tool-disclosure.js.map +1 -0
- package/dist/core/runner/turn-attachments.d.ts +110 -0
- package/dist/core/runner/turn-attachments.d.ts.map +1 -0
- package/dist/core/runner/turn-attachments.js +334 -0
- package/dist/core/runner/turn-attachments.js.map +1 -0
- package/dist/core/runner/usage-accounting.d.ts +19 -0
- package/dist/core/runner/usage-accounting.d.ts.map +1 -0
- package/dist/core/runner/usage-accounting.js +30 -0
- package/dist/core/runner/usage-accounting.js.map +1 -0
- package/dist/core/runtime.d.ts +4 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +12 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/core/safety-axis-vocab.d.ts +10 -0
- package/dist/core/safety-axis-vocab.d.ts.map +1 -0
- package/dist/core/safety-axis-vocab.js +12 -0
- package/dist/core/safety-axis-vocab.js.map +1 -0
- package/dist/core/safety-merge-corpus.d.ts +11 -0
- package/dist/core/safety-merge-corpus.d.ts.map +1 -0
- package/dist/core/safety-merge-corpus.js +195 -0
- package/dist/core/safety-merge-corpus.js.map +1 -0
- package/dist/core/scheduler.d.ts +55 -0
- package/dist/core/scheduler.d.ts.map +1 -0
- package/dist/core/scheduler.js +32 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/secret-env.d.ts +3 -0
- package/dist/core/secret-env.d.ts.map +1 -0
- package/dist/core/secret-env.js +13 -0
- package/dist/core/secret-env.js.map +1 -0
- package/dist/core/select-model.d.ts +11 -0
- package/dist/core/select-model.d.ts.map +1 -0
- package/dist/core/select-model.js +44 -0
- package/dist/core/select-model.js.map +1 -0
- package/dist/core/sensitive-path-policy.d.ts +9 -0
- package/dist/core/sensitive-path-policy.d.ts.map +1 -0
- package/dist/core/sensitive-path-policy.js +61 -0
- package/dist/core/sensitive-path-policy.js.map +1 -0
- package/dist/core/session-policy-store.d.ts +38 -0
- package/dist/core/session-policy-store.d.ts.map +1 -0
- package/dist/core/session-policy-store.js +112 -0
- package/dist/core/session-policy-store.js.map +1 -0
- package/dist/core/session-reconcile.d.ts +15 -0
- package/dist/core/session-reconcile.d.ts.map +1 -0
- package/dist/core/session-reconcile.js +48 -0
- package/dist/core/session-reconcile.js.map +1 -0
- package/dist/core/session-store.d.ts +36 -0
- package/dist/core/session-store.d.ts.map +1 -0
- package/dist/core/session-store.js +192 -0
- package/dist/core/session-store.js.map +1 -0
- package/dist/core/session.d.ts +44 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +27 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/spec-contract.d.ts +58 -0
- package/dist/core/spec-contract.d.ts.map +1 -0
- package/dist/core/spec-contract.js +256 -0
- package/dist/core/spec-contract.js.map +1 -0
- package/dist/core/strategy-store.d.ts +25 -0
- package/dist/core/strategy-store.d.ts.map +1 -0
- package/dist/core/strategy-store.js +81 -0
- package/dist/core/strategy-store.js.map +1 -0
- package/dist/core/stub-env.d.ts +28 -0
- package/dist/core/stub-env.d.ts.map +1 -0
- package/dist/core/stub-env.js +61 -0
- package/dist/core/stub-env.js.map +1 -0
- package/dist/core/task-notification.d.ts +56 -0
- package/dist/core/task-notification.d.ts.map +1 -0
- package/dist/core/task-notification.js +200 -0
- package/dist/core/task-notification.js.map +1 -0
- package/dist/core/task-outcome.d.ts +27 -0
- package/dist/core/task-outcome.d.ts.map +1 -0
- package/dist/core/task-outcome.js +12 -0
- package/dist/core/task-outcome.js.map +1 -0
- package/dist/core/task-registry.d.ts +188 -0
- package/dist/core/task-registry.d.ts.map +1 -0
- package/dist/core/task-registry.js +1443 -0
- package/dist/core/task-registry.js.map +1 -0
- package/dist/core/tighten-task-spec.d.ts +6 -0
- package/dist/core/tighten-task-spec.d.ts.map +1 -0
- package/dist/core/tighten-task-spec.js +50 -0
- package/dist/core/tighten-task-spec.js.map +1 -0
- package/dist/core/tool-detach.d.ts +10 -0
- package/dist/core/tool-detach.d.ts.map +1 -0
- package/dist/core/tool-detach.js +41 -0
- package/dist/core/tool-detach.js.map +1 -0
- package/dist/core/tool-errors.d.ts +8 -0
- package/dist/core/tool-errors.d.ts.map +1 -0
- package/dist/core/tool-errors.js +132 -0
- package/dist/core/tool-errors.js.map +1 -0
- package/dist/core/tool-name-aliases.d.ts +3 -0
- package/dist/core/tool-name-aliases.d.ts.map +1 -0
- package/dist/core/tool-name-aliases.js +60 -0
- package/dist/core/tool-name-aliases.js.map +1 -0
- package/dist/core/tool-policy.d.ts +75 -0
- package/dist/core/tool-policy.d.ts.map +1 -0
- package/dist/core/tool-policy.js +363 -0
- package/dist/core/tool-policy.js.map +1 -0
- package/dist/core/tool-result-budget.d.ts +17 -0
- package/dist/core/tool-result-budget.d.ts.map +1 -0
- package/dist/core/tool-result-budget.js +103 -0
- package/dist/core/tool-result-budget.js.map +1 -0
- package/dist/core/tool-result-store.d.ts +55 -0
- package/dist/core/tool-result-store.d.ts.map +1 -0
- package/dist/core/tool-result-store.js +154 -0
- package/dist/core/tool-result-store.js.map +1 -0
- package/dist/core/tools.d.ts +6 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +61 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/trace.d.ts +208 -0
- package/dist/core/trace.d.ts.map +1 -0
- package/dist/core/trace.js +10 -0
- package/dist/core/trace.js.map +1 -0
- package/dist/core/types.d.ts +684 -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 +7 -0
- package/dist/core/untrusted-egress.d.ts.map +1 -0
- package/dist/core/untrusted-egress.js +23 -0
- package/dist/core/untrusted-egress.js.map +1 -0
- package/dist/core/untrusted-text.d.ts +5 -0
- package/dist/core/untrusted-text.d.ts.map +1 -0
- package/dist/core/untrusted-text.js +36 -0
- package/dist/core/untrusted-text.js.map +1 -0
- package/dist/core/warm-resume.d.ts +6 -0
- package/dist/core/warm-resume.d.ts.map +1 -0
- package/dist/core/warm-resume.js +11 -0
- package/dist/core/warm-resume.js.map +1 -0
- package/dist/core/with-retry.d.ts +19 -0
- package/dist/core/with-retry.d.ts.map +1 -0
- package/dist/core/with-retry.js +36 -0
- package/dist/core/with-retry.js.map +1 -0
- package/dist/core/workflow-journal-store.d.ts +16 -0
- package/dist/core/workflow-journal-store.d.ts.map +1 -0
- package/dist/core/workflow-journal-store.js +34 -0
- package/dist/core/workflow-journal-store.js.map +1 -0
- package/dist/core/workflow-run-store-contract.d.ts +6 -0
- package/dist/core/workflow-run-store-contract.d.ts.map +1 -0
- package/dist/core/workflow-run-store-contract.js +144 -0
- package/dist/core/workflow-run-store-contract.js.map +1 -0
- package/dist/core/workflow-run-store.d.ts +54 -0
- package/dist/core/workflow-run-store.d.ts.map +1 -0
- package/dist/core/workflow-run-store.js +86 -0
- package/dist/core/workflow-run-store.js.map +1 -0
- package/dist/engine/compaction/compaction.d.ts +63 -0
- package/dist/engine/compaction/compaction.d.ts.map +1 -0
- package/dist/engine/compaction/compaction.js +770 -0
- package/dist/engine/compaction/compaction.js.map +1 -0
- package/dist/engine/compaction/utils.d.ts +19 -0
- package/dist/engine/compaction/utils.d.ts.map +1 -0
- package/dist/engine/compaction/utils.js +167 -0
- package/dist/engine/compaction/utils.js.map +1 -0
- package/dist/engine/execution-env/kill-tree.d.ts +10 -0
- package/dist/engine/execution-env/kill-tree.d.ts.map +1 -0
- package/dist/engine/execution-env/kill-tree.js +143 -0
- package/dist/engine/execution-env/kill-tree.js.map +1 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +98 -0
- package/dist/engine/execution-env/node-execution-env.d.ts.map +1 -0
- package/dist/engine/execution-env/node-execution-env.js +945 -0
- package/dist/engine/execution-env/node-execution-env.js.map +1 -0
- package/dist/engine/harness/agent-harness.d.ts +112 -0
- package/dist/engine/harness/agent-harness.d.ts.map +1 -0
- package/dist/engine/harness/agent-harness.js +932 -0
- package/dist/engine/harness/agent-harness.js.map +1 -0
- package/dist/engine/harness/messages.d.ts +12 -0
- package/dist/engine/harness/messages.d.ts.map +1 -0
- package/dist/engine/harness/messages.js +102 -0
- package/dist/engine/harness/messages.js.map +1 -0
- package/dist/engine/harness/types.d.ts +484 -0
- package/dist/engine/harness/types.d.ts.map +1 -0
- package/dist/engine/harness/types.js +91 -0
- package/dist/engine/harness/types.js.map +1 -0
- package/dist/engine/llm/diagnostics.d.ts +19 -0
- package/dist/engine/llm/diagnostics.d.ts.map +1 -0
- package/dist/engine/llm/diagnostics.js +28 -0
- package/dist/engine/llm/diagnostics.js.map +1 -0
- package/dist/engine/llm/event-stream.d.ts +22 -0
- package/dist/engine/llm/event-stream.d.ts.map +1 -0
- package/dist/engine/llm/event-stream.js +91 -0
- package/dist/engine/llm/event-stream.js.map +1 -0
- package/dist/engine/llm/index.d.ts +5 -0
- package/dist/engine/llm/index.d.ts.map +1 -0
- package/dist/engine/llm/index.js +5 -0
- package/dist/engine/llm/index.js.map +1 -0
- package/dist/engine/llm/types.d.ts +359 -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 +5 -0
- package/dist/engine/llm/validation.d.ts.map +1 -0
- package/dist/engine/llm/validation.js +293 -0
- package/dist/engine/llm/validation.js.map +1 -0
- package/dist/engine/loop/agent-loop.d.ts +19 -0
- package/dist/engine/loop/agent-loop.d.ts.map +1 -0
- package/dist/engine/loop/agent-loop.js +1087 -0
- package/dist/engine/loop/agent-loop.js.map +1 -0
- package/dist/engine/loop/runtime-deps.d.ts +10 -0
- package/dist/engine/loop/runtime-deps.d.ts.map +1 -0
- package/dist/engine/loop/runtime-deps.js +19 -0
- package/dist/engine/loop/runtime-deps.js.map +1 -0
- package/dist/engine/loop/types.d.ts +209 -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 +3 -0
- package/dist/engine/lsp/frame-decoder.d.ts.map +1 -0
- package/dist/engine/lsp/frame-decoder.js +36 -0
- package/dist/engine/lsp/frame-decoder.js.map +1 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +49 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts.map +1 -0
- package/dist/engine/lsp/node-lsp-manager.js +267 -0
- package/dist/engine/lsp/node-lsp-manager.js.map +1 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts +32 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts.map +1 -0
- package/dist/engine/lsp/stdio-lsp-transport.js +154 -0
- package/dist/engine/lsp/stdio-lsp-transport.js.map +1 -0
- package/dist/engine/session/import-validate.d.ts +13 -0
- package/dist/engine/session/import-validate.d.ts.map +1 -0
- package/dist/engine/session/import-validate.js +56 -0
- package/dist/engine/session/import-validate.js.map +1 -0
- package/dist/engine/session/memory-repo.d.ts +20 -0
- package/dist/engine/session/memory-repo.d.ts.map +1 -0
- package/dist/engine/session/memory-repo.js +54 -0
- package/dist/engine/session/memory-repo.js.map +1 -0
- package/dist/engine/session/memory-storage.d.ts +12 -0
- package/dist/engine/session/memory-storage.d.ts.map +1 -0
- package/dist/engine/session/memory-storage.js +16 -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 +27 -0
- package/dist/engine/session/session.d.ts.map +1 -0
- package/dist/engine/session/session.js +197 -0
- package/dist/engine/session/session.js.map +1 -0
- package/dist/engine/session/storage-base.d.ts +30 -0
- package/dist/engine/session/storage-base.d.ts.map +1 -0
- package/dist/engine/session/storage-base.js +138 -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 +156 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +141 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/harness.d.ts +19 -0
- package/dist/internal/harness.d.ts.map +1 -0
- package/dist/internal/harness.js +13 -0
- package/dist/internal/harness.js.map +1 -0
- package/dist/internal/llm.d.ts +3 -0
- package/dist/internal/llm.d.ts.map +1 -0
- package/dist/internal/llm.js +2 -0
- package/dist/internal/llm.js.map +1 -0
- package/dist/orchestration/builtin-workflows.d.ts +11 -0
- package/dist/orchestration/builtin-workflows.d.ts.map +1 -0
- package/dist/orchestration/builtin-workflows.js +134 -0
- package/dist/orchestration/builtin-workflows.js.map +1 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts +5 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts.map +1 -0
- package/dist/orchestration/dev-vm-script-runner.js +68 -0
- package/dist/orchestration/dev-vm-script-runner.js.map +1 -0
- package/dist/orchestration/goal.d.ts +40 -0
- package/dist/orchestration/goal.d.ts.map +1 -0
- package/dist/orchestration/goal.js +190 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/orchestration/run-spec.d.ts +21 -0
- package/dist/orchestration/run-spec.d.ts.map +1 -0
- package/dist/orchestration/run-spec.js +201 -0
- package/dist/orchestration/run-spec.js.map +1 -0
- package/dist/orchestration/run-workflow-tool.d.ts +80 -0
- package/dist/orchestration/run-workflow-tool.d.ts.map +1 -0
- package/dist/orchestration/run-workflow-tool.js +431 -0
- package/dist/orchestration/run-workflow-tool.js.map +1 -0
- package/dist/orchestration/workflow-governance.d.ts +30 -0
- package/dist/orchestration/workflow-governance.d.ts.map +1 -0
- package/dist/orchestration/workflow-governance.js +125 -0
- package/dist/orchestration/workflow-governance.js.map +1 -0
- package/dist/orchestration/workflow-meta.d.ts +13 -0
- package/dist/orchestration/workflow-meta.d.ts.map +1 -0
- package/dist/orchestration/workflow-meta.js +367 -0
- package/dist/orchestration/workflow-meta.js.map +1 -0
- package/dist/orchestration/workflow-observe.d.ts +18 -0
- package/dist/orchestration/workflow-observe.d.ts.map +1 -0
- package/dist/orchestration/workflow-observe.js +73 -0
- package/dist/orchestration/workflow-observe.js.map +1 -0
- package/dist/orchestration/workflow-primitives.d.ts +12 -0
- package/dist/orchestration/workflow-primitives.d.ts.map +1 -0
- package/dist/orchestration/workflow-primitives.js +56 -0
- package/dist/orchestration/workflow-primitives.js.map +1 -0
- package/dist/orchestration/workflow-sandbox-conformance.d.ts +5 -0
- package/dist/orchestration/workflow-sandbox-conformance.d.ts.map +1 -0
- package/dist/orchestration/workflow-sandbox-conformance.js +220 -0
- package/dist/orchestration/workflow-sandbox-conformance.js.map +1 -0
- package/dist/orchestration/workflow-script-runner.d.ts +39 -0
- package/dist/orchestration/workflow-script-runner.d.ts.map +1 -0
- package/dist/orchestration/workflow-script-runner.js +23 -0
- package/dist/orchestration/workflow-script-runner.js.map +1 -0
- package/dist/orchestration/workflow-script-store.d.ts +20 -0
- package/dist/orchestration/workflow-script-store.d.ts.map +1 -0
- package/dist/orchestration/workflow-script-store.js +73 -0
- package/dist/orchestration/workflow-script-store.js.map +1 -0
- package/dist/orchestration/workflow-size-guideline.d.ts +10 -0
- package/dist/orchestration/workflow-size-guideline.d.ts.map +1 -0
- package/dist/orchestration/workflow-size-guideline.js +38 -0
- package/dist/orchestration/workflow-size-guideline.js.map +1 -0
- package/dist/orchestration/workflow.d.ts +281 -0
- package/dist/orchestration/workflow.d.ts.map +1 -0
- package/dist/orchestration/workflow.js +1095 -0
- package/dist/orchestration/workflow.js.map +1 -0
- package/dist/prompts/default.d.ts +104 -0
- package/dist/prompts/default.d.ts.map +1 -0
- package/dist/prompts/default.js +397 -0
- package/dist/prompts/default.js.map +1 -0
- package/dist/prompts/supervisor.d.ts +5 -0
- package/dist/prompts/supervisor.d.ts.map +1 -0
- package/dist/prompts/supervisor.js +107 -0
- package/dist/prompts/supervisor.js.map +1 -0
- package/dist/scenarios/env.d.ts +13 -0
- package/dist/scenarios/env.d.ts.map +1 -0
- package/dist/scenarios/env.js +40 -0
- package/dist/scenarios/env.js.map +1 -0
- package/dist/scenarios/full-body.d.ts +13 -0
- package/dist/scenarios/full-body.d.ts.map +1 -0
- package/dist/scenarios/full-body.js +20 -0
- package/dist/scenarios/full-body.js.map +1 -0
- package/dist/scenarios/scenario-registry.d.ts +47 -0
- package/dist/scenarios/scenario-registry.d.ts.map +1 -0
- package/dist/scenarios/scenario-registry.js +139 -0
- package/dist/scenarios/scenario-registry.js.map +1 -0
- package/dist/scenarios/teacher-quickstart.d.ts +14 -0
- package/dist/scenarios/teacher-quickstart.d.ts.map +1 -0
- package/dist/scenarios/teacher-quickstart.js +13 -0
- package/dist/scenarios/teacher-quickstart.js.map +1 -0
- package/dist/server/http.d.ts +19 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +115 -0
- package/dist/server/http.js.map +1 -0
- package/dist/stores/file/checkpoint-store.d.ts +40 -0
- package/dist/stores/file/checkpoint-store.d.ts.map +1 -0
- package/dist/stores/file/checkpoint-store.js +198 -0
- package/dist/stores/file/checkpoint-store.js.map +1 -0
- package/dist/stores/file/file-snapshot-store.d.ts +25 -0
- package/dist/stores/file/file-snapshot-store.d.ts.map +1 -0
- package/dist/stores/file/file-snapshot-store.js +313 -0
- package/dist/stores/file/file-snapshot-store.js.map +1 -0
- package/dist/stores/file/fs-atomic.d.ts +24 -0
- package/dist/stores/file/fs-atomic.d.ts.map +1 -0
- package/dist/stores/file/fs-atomic.js +276 -0
- package/dist/stores/file/fs-atomic.js.map +1 -0
- package/dist/stores/file/index.d.ts +45 -0
- package/dist/stores/file/index.d.ts.map +1 -0
- package/dist/stores/file/index.js +77 -0
- package/dist/stores/file/index.js.map +1 -0
- package/dist/stores/file/memory-store.d.ts +35 -0
- package/dist/stores/file/memory-store.d.ts.map +1 -0
- package/dist/stores/file/memory-store.js +300 -0
- package/dist/stores/file/memory-store.js.map +1 -0
- package/dist/stores/file/session-policy-store.d.ts +11 -0
- package/dist/stores/file/session-policy-store.d.ts.map +1 -0
- package/dist/stores/file/session-policy-store.js +96 -0
- package/dist/stores/file/session-policy-store.js.map +1 -0
- package/dist/stores/file/session-store.d.ts +24 -0
- package/dist/stores/file/session-store.d.ts.map +1 -0
- package/dist/stores/file/session-store.js +134 -0
- package/dist/stores/file/session-store.js.map +1 -0
- package/dist/stores/file/tool-result-store.d.ts +12 -0
- package/dist/stores/file/tool-result-store.d.ts.map +1 -0
- package/dist/stores/file/tool-result-store.js +44 -0
- package/dist/stores/file/tool-result-store.js.map +1 -0
- package/dist/stores/file/workflow-journal-store.d.ts +17 -0
- package/dist/stores/file/workflow-journal-store.d.ts.map +1 -0
- package/dist/stores/file/workflow-journal-store.js +104 -0
- package/dist/stores/file/workflow-journal-store.js.map +1 -0
- package/dist/stores/file/workflow-run-store.d.ts +41 -0
- package/dist/stores/file/workflow-run-store.d.ts.map +1 -0
- package/dist/stores/file/workflow-run-store.js +147 -0
- package/dist/stores/file/workflow-run-store.js.map +1 -0
- package/dist/stores/pg.d.ts +96 -0
- package/dist/stores/pg.d.ts.map +1 -0
- package/dist/stores/pg.js +451 -0
- package/dist/stores/pg.js.map +1 -0
- package/dist/tools/fs/encoding.d.ts +16 -0
- package/dist/tools/fs/encoding.d.ts.map +1 -0
- package/dist/tools/fs/encoding.js +44 -0
- package/dist/tools/fs/encoding.js.map +1 -0
- package/dist/tools/fs/gh-rate-limit.d.ts +3 -0
- package/dist/tools/fs/gh-rate-limit.d.ts.map +1 -0
- package/dist/tools/fs/gh-rate-limit.js +16 -0
- package/dist/tools/fs/gh-rate-limit.js.map +1 -0
- package/dist/tools/fs/index.d.ts +74 -0
- package/dist/tools/fs/index.d.ts.map +1 -0
- package/dist/tools/fs/index.js +1576 -0
- package/dist/tools/fs/index.js.map +1 -0
- package/dist/tools/fs/pdf.d.ts +47 -0
- package/dist/tools/fs/pdf.d.ts.map +1 -0
- package/dist/tools/fs/pdf.js +124 -0
- package/dist/tools/fs/pdf.js.map +1 -0
- package/dist/tools/fs/repo-map.d.ts +5 -0
- package/dist/tools/fs/repo-map.d.ts.map +1 -0
- package/dist/tools/fs/repo-map.js +209 -0
- package/dist/tools/fs/repo-map.js.map +1 -0
- package/dist/tools/fs/safety.d.ts +52 -0
- package/dist/tools/fs/safety.d.ts.map +1 -0
- package/dist/tools/fs/safety.js +314 -0
- package/dist/tools/fs/safety.js.map +1 -0
- package/dist/tools/fs/search.d.ts +57 -0
- package/dist/tools/fs/search.d.ts.map +1 -0
- package/dist/tools/fs/search.js +574 -0
- package/dist/tools/fs/search.js.map +1 -0
- package/dist/tools/gitea-issue.d.ts +14 -0
- package/dist/tools/gitea-issue.d.ts.map +1 -0
- package/dist/tools/gitea-issue.js +74 -0
- package/dist/tools/gitea-issue.js.map +1 -0
- package/dist/tools/monitor.d.ts +20 -0
- package/dist/tools/monitor.d.ts.map +1 -0
- package/dist/tools/monitor.js +90 -0
- package/dist/tools/monitor.js.map +1 -0
- package/dist/tools/scheduler-tools.d.ts +15 -0
- package/dist/tools/scheduler-tools.d.ts.map +1 -0
- package/dist/tools/scheduler-tools.js +338 -0
- package/dist/tools/scheduler-tools.js.map +1 -0
- package/dist/tools/sql-adapters.d.ts +14 -0
- package/dist/tools/sql-adapters.d.ts.map +1 -0
- package/dist/tools/sql-adapters.js +13 -0
- package/dist/tools/sql-adapters.js.map +1 -0
- package/dist/tools/sql.d.ts +11 -0
- package/dist/tools/sql.d.ts.map +1 -0
- package/dist/tools/sql.js +104 -0
- package/dist/tools/sql.js.map +1 -0
- package/dist/tools/task-list.d.ts +14 -0
- package/dist/tools/task-list.d.ts.map +1 -0
- package/dist/tools/task-list.js +318 -0
- package/dist/tools/task-list.js.map +1 -0
- package/dist/tools/todo.d.ts +3 -0
- package/dist/tools/todo.d.ts.map +1 -0
- package/dist/tools/todo.js +97 -0
- package/dist/tools/todo.js.map +1 -0
- package/dist/tools/web.d.ts +26 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +498 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/tools/worktree.d.ts +18 -0
- package/dist/tools/worktree.d.ts.map +1 -0
- package/dist/tools/worktree.js +288 -0
- package/dist/tools/worktree.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,2087 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import { AgentHarness, DEFAULT_CHARS_PER_TOKEN, estimateContextTokens } from "../../internal/harness.js";
|
|
3
|
+
const PROMPT_HASH_SALT = randomBytes(16);
|
|
4
|
+
import { createAutoModeDecider } from "../auto-mode.js";
|
|
5
|
+
import { buildAutoModePrompt, renderAutoModeAction, renderAutoModeWindow } from "../auto-mode-prompt.js";
|
|
6
|
+
import { resolveModel, resolveTaskModel, roleModelIfSet } from "../roles.js";
|
|
7
|
+
import { primaryActivityArg } from "../arg-summary.js";
|
|
8
|
+
import { materializeMcpTools } from "../mcp.js";
|
|
9
|
+
import { brainToRuntime } from "../runtime.js";
|
|
10
|
+
import { MemoryEngine } from "../memory-engine/engine.js";
|
|
11
|
+
import { deriveControlPlaneDir, deriveProjectControlDir, deriveProjectMemoryDir, deriveRepoMemoryDir, drainMemoryAnnouncements, enqueueMemoryAnnouncement, lookupProjectIdHint, recordProjectIdHint, resolveMemoryEngineRoot } from "../memory-engine/layout.js";
|
|
12
|
+
import { assertScopeContractPlacement, parseScopeKey, resolveProjectId } from "../memory-engine/scope-contract.js";
|
|
13
|
+
import { classifyScopePlanes, derivePersonalControlDir, derivePersonalMemoryDir, mergeHarvestReports, mergeInjections, needsDualRoots, parsedProjectPlane } from "../memory-engine/dual-root.js";
|
|
14
|
+
import { FileMemoryEngineBackend } from "../memory-engine/file-backend.js";
|
|
15
|
+
import { Session, isSessionConflict, hasSessionFork } from "../session.js";
|
|
16
|
+
import { createAgentTranscriptTool, createSendMessageTool, createSubagentWorktreeHelper, forkGovernanceDenial, AGENT_TRANSCRIPT_TOOL_NAME, SEND_MESSAGE_TOOL_NAME, SubagentRetainLedger } from "../../agents/subagent.js";
|
|
17
|
+
import { combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, resolveAsk } from "../tool-policy.js";
|
|
18
|
+
import { ActiveSkillScope, createActiveSkillScopePolicy } from "./active-skill-scope.js";
|
|
19
|
+
import { computeCallCap, createCallCapRef, softExecDeadlineMs } from "./call-cap.js";
|
|
20
|
+
import { CHANGED_FILES_MTIME_EPS_MS } from "./turn-attachments.js";
|
|
21
|
+
import { emitTrace } from "../trace.js";
|
|
22
|
+
import { createSessionRulePolicy } from "./session-rule-policy.js";
|
|
23
|
+
import { cloneObserverInput, formatHookFeedback, runToolGate } from "../hooks.js";
|
|
24
|
+
import { reconcileInterruptedSession } from "../session-reconcile.js";
|
|
25
|
+
import { CacheBreakDetector, toolsToFingerprintInputs } from "../cache-break-detector.js";
|
|
26
|
+
import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
|
|
27
|
+
import { defineTool } from "../tools.js";
|
|
28
|
+
import { pathToUri } from "../lsp-protocol.js";
|
|
29
|
+
import { DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, firstPartyOffloadPolicy, InMemoryToolResultStore, RunnerSharedToolResultStore, ScopedToolResultStore, isVolatileOffloadStore, OFFLOAD_TOOL_NAME, makeReadToolResultTool, withToolResultOffload, } from "../tool-result-store.js";
|
|
30
|
+
import { OUTPUT_TOOL_NAME, SKILL_TOOL_NAME, buildSkillsBlock, makeOutputTool, makeReportBlockedTool, makeSkillTool, normalizeSkills } from "./synthetic-tools.js";
|
|
31
|
+
import { compileOutputSchema } from "./strict-output-schema.js";
|
|
32
|
+
import { TOOL_SEARCH_NAME, buildDeferredRegistry, classifyDeferred, extractDiscoveredToolNames, makePlaceholderTool, makeToolSearchTool, } from "./tool-disclosure.js";
|
|
33
|
+
import { composeMemoryBlock, normalizeMemorySpec } from "../memory.js";
|
|
34
|
+
import {} from "./memory-consolidation.js";
|
|
35
|
+
import { composeSystemPrompt, composeConstitution, defaultPromptProvider, buildEnvironmentContext, buildGitSnapshot, formatLocalDate, isValidTimeZone, CYBER_RISK, URL_SAFETY, DEFAULT_SYSTEM_PROMPT, PROJECT_CONTEXT_FRAMING } from "../../prompts/default.js";
|
|
36
|
+
import { clearStaleToolResults, dropEmptyFailureAssistants, editBudget } from "../context-edit.js";
|
|
37
|
+
import { capAggregateToolResults } from "../tool-result-budget.js";
|
|
38
|
+
import { capAggregateMediaBytes, AGGREGATE_MEDIA_BUDGET_BYTES } from "../media-byte-cap.js";
|
|
39
|
+
import { dropOrphanToolResults, guardBudget, trimToBudget } from "../context-guard.js";
|
|
40
|
+
import { StubExecutionEnv } from "../stub-env.js";
|
|
41
|
+
import { hasDestroy, isIsolated, isRemoteExecutionEnv, isSuspendable } from "../remote-env.js";
|
|
42
|
+
import { hasBackgroundShell } from "../background-shell.js";
|
|
43
|
+
import { createTaskOutputTool, createTaskStopTool, defaultTaskRegistry } from "../task-registry.js";
|
|
44
|
+
import { createMonitorTool } from "../../tools/monitor.js";
|
|
45
|
+
import { createWorktreeTools } from "../../tools/worktree.js";
|
|
46
|
+
import { bashReversibilityProbe, createHandsToolkit, seedReadFileStateFromContext, HAND_TOOL_EFFECTS, pdfModelCapabilitiesOf } from "../../tools/fs/index.js";
|
|
47
|
+
import { decodeTextBytes } from "../../tools/fs/encoding.js";
|
|
48
|
+
import { createAskUserQuestionTool } from "../ask-question.js";
|
|
49
|
+
import { createSchedulerTools } from "../../tools/scheduler-tools.js";
|
|
50
|
+
import { createPresentPlanTool, createEnterPlanModeTool, PRESENT_PLAN_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME } from "../present-plan-tool.js";
|
|
51
|
+
import { isSelfOrchestrationActive, selfOrchestrationFailClosedReason } from "../../orchestration/workflow-script-runner.js";
|
|
52
|
+
import { createRunWorkflowTool, RUN_WORKFLOW_TOOL_NAME } from "../../orchestration/run-workflow-tool.js";
|
|
53
|
+
import { createLspTool, gitCheckIgnoreFilter } from "../lsp.js";
|
|
54
|
+
import { resolveKey } from "../../tools/fs/safety.js";
|
|
55
|
+
import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, RESOURCE_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, remainingBudgetMicroUsd, } from "../checkpoint-store.js";
|
|
56
|
+
import { boundInputHashOf } from "../canonical-json.js";
|
|
57
|
+
const RECONCILE_MAX_RETRIES = 3;
|
|
58
|
+
const DEFAULT_MAX_SUSPENDS = 5;
|
|
59
|
+
const DEFAULT_MAX_SLICES = 100;
|
|
60
|
+
const ULTRA_REASONING_TIERS = new Set(["xhigh", "max"]);
|
|
61
|
+
const DEFAULT_RESOURCE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
62
|
+
const DEFAULT_UNATTENDED_APPROVAL_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
63
|
+
const ungatedWarnedShapes = new WeakMap();
|
|
64
|
+
export const DEFAULT_IRREVERSIBLE_SCOPE = "irreversible";
|
|
65
|
+
function batchContextAt(messages, currentId) {
|
|
66
|
+
let batch = [];
|
|
67
|
+
for (const m of messages) {
|
|
68
|
+
if (m.role === "assistant") {
|
|
69
|
+
const ids = m.content.filter((c) => c.type === "toolCall").map((c) => c.id);
|
|
70
|
+
if (ids.includes(currentId))
|
|
71
|
+
batch = ids;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const resolved = new Set(messages.filter((m) => m.role === "toolResult").map((m) => m.toolCallId));
|
|
75
|
+
const completedCallIds = batch.filter((id) => id !== currentId && resolved.has(id));
|
|
76
|
+
return { batchToolCallIds: batch, completedCallIds };
|
|
77
|
+
}
|
|
78
|
+
function detectConflicts(storage, ref) {
|
|
79
|
+
const guard = (fn) => async (...args) => {
|
|
80
|
+
try {
|
|
81
|
+
return await fn(...args);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
if (isSessionConflict(err)) {
|
|
85
|
+
ref.hit = true;
|
|
86
|
+
}
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
return new Proxy(storage, {
|
|
91
|
+
get(target, prop, receiver) {
|
|
92
|
+
const value = Reflect.get(target, prop, receiver);
|
|
93
|
+
if (typeof value !== "function") {
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
const bound = value.bind(target);
|
|
97
|
+
return prop === "appendEntry" || prop === "setLeafId"
|
|
98
|
+
? guard(bound)
|
|
99
|
+
: bound;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function raceAbort(p, signal, onAbort) {
|
|
104
|
+
if (signal.aborted)
|
|
105
|
+
return Promise.resolve(onAbort());
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
let settled = false;
|
|
108
|
+
const finish = (v) => {
|
|
109
|
+
if (settled)
|
|
110
|
+
return;
|
|
111
|
+
settled = true;
|
|
112
|
+
signal.removeEventListener("abort", onAbortEvent);
|
|
113
|
+
resolve(v);
|
|
114
|
+
};
|
|
115
|
+
const onAbortEvent = () => finish(onAbort());
|
|
116
|
+
signal.addEventListener("abort", onAbortEvent, { once: true });
|
|
117
|
+
p.then(finish, () => finish(onAbort()));
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async function forgetQuietly(sessions, sessionId) {
|
|
121
|
+
try {
|
|
122
|
+
if (sessions.forget)
|
|
123
|
+
await sessions.forget(sessionId);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export async function prepareTask(spec, deps, sessions, resume, _memorySelector, internals, runnerSelf) {
|
|
129
|
+
if (spec.resumeAt !== undefined) {
|
|
130
|
+
if (resume) {
|
|
131
|
+
const e = new Error("resumeAt cannot be combined with a durable resume");
|
|
132
|
+
e.code = "resume_at.conflicts_resume";
|
|
133
|
+
throw e;
|
|
134
|
+
}
|
|
135
|
+
if (!spec.sessionId) {
|
|
136
|
+
const e = new Error("resumeAt requires a sessionId (the session to branch)");
|
|
137
|
+
e.code = "resume_at.no_session";
|
|
138
|
+
throw e;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const resolvedRole = resolveTaskModel(spec, deps);
|
|
142
|
+
const model = resolvedRole.model;
|
|
143
|
+
const thinking = spec.thinking ?? resolvedRole.thinking ?? model.defaultThinking;
|
|
144
|
+
const compModel = spec.compactionModel
|
|
145
|
+
? resolveModel(spec.compactionModel, deps.models)
|
|
146
|
+
: roleModelIfSet("summarize", spec, deps);
|
|
147
|
+
const toolEffects = new Map();
|
|
148
|
+
const egressTools = new Set();
|
|
149
|
+
const irreversibleTools = new Set();
|
|
150
|
+
const irreversibilityTier = new Map();
|
|
151
|
+
const reversibilityProbes = new Map();
|
|
152
|
+
let shellGatedBash = false;
|
|
153
|
+
let shellGatedMonitor = false;
|
|
154
|
+
for (const t of spec.tools ?? []) {
|
|
155
|
+
if (t.name.includes("__")) {
|
|
156
|
+
const e = new Error(`Tool name "${t.name}" is invalid: "__" is reserved for the MCP namespace (mcp__<server>__<tool>) and must not appear in a caller tool name.`);
|
|
157
|
+
e.code = "config.tool_name_invalid";
|
|
158
|
+
throw e;
|
|
159
|
+
}
|
|
160
|
+
if (t.effect) {
|
|
161
|
+
toolEffects.set(t.name, t.effect);
|
|
162
|
+
}
|
|
163
|
+
const tier = t.irreversibility ?? (t.reversibilityProbe ? "maybe" : undefined);
|
|
164
|
+
if (tier !== undefined) {
|
|
165
|
+
irreversibilityTier.set(t.name, tier);
|
|
166
|
+
if (tier === "always" || tier === "maybe")
|
|
167
|
+
irreversibleTools.add(t.name);
|
|
168
|
+
}
|
|
169
|
+
if (t.reversibilityProbe)
|
|
170
|
+
reversibilityProbes.set(t.name, t.reversibilityProbe);
|
|
171
|
+
if (t.egress) {
|
|
172
|
+
if (t.effect !== undefined && t.effect !== "write") {
|
|
173
|
+
const e = new Error(`Tool "${t.name}" declares egress:true with effect:"${t.effect}" — an egress tool (external write) must have effect:"write" (or omit effect; write is the default).`);
|
|
174
|
+
e.code = "config.egress_requires_write_effect";
|
|
175
|
+
throw e;
|
|
176
|
+
}
|
|
177
|
+
egressTools.add(t.name);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
toolEffects.set(OFFLOAD_TOOL_NAME, "read");
|
|
181
|
+
if (deps.executionEnvFactory || deps.executionEnv) {
|
|
182
|
+
for (const [name, effect] of Object.entries(HAND_TOOL_EFFECTS))
|
|
183
|
+
toolEffects.set(name, effect);
|
|
184
|
+
if (spec.handsReadOnly === true)
|
|
185
|
+
toolEffects.set("Bash", "read");
|
|
186
|
+
}
|
|
187
|
+
if (spec.enablePlanMode === true) {
|
|
188
|
+
toolEffects.set(PRESENT_PLAN_TOOL_NAME, "read");
|
|
189
|
+
toolEffects.set(ENTER_PLAN_MODE_TOOL_NAME, "read");
|
|
190
|
+
}
|
|
191
|
+
if (spec.requireExistingSession && !spec.sessionId) {
|
|
192
|
+
const e = new Error(`requireExistingSession requires a sessionId — cannot require an existing session without one (design/114 Phase3)`);
|
|
193
|
+
e.code = "resume.session_not_found";
|
|
194
|
+
throw e;
|
|
195
|
+
}
|
|
196
|
+
let acquired;
|
|
197
|
+
let session;
|
|
198
|
+
let conflictRef;
|
|
199
|
+
for (let attempt = 0;; attempt++) {
|
|
200
|
+
try {
|
|
201
|
+
acquired = await sessions.acquire(spec.sessionId, spec.requireExistingSession ? { requireExisting: true } : undefined);
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
if (spec.requireExistingSession && err?.code === "not_found") {
|
|
205
|
+
const e = new Error(`requireExistingSession: session "${spec.sessionId}" does not exist — refusing a silent fresh run (design/114 Phase3)`);
|
|
206
|
+
e.code = "resume.session_not_found";
|
|
207
|
+
throw e;
|
|
208
|
+
}
|
|
209
|
+
throw err;
|
|
210
|
+
}
|
|
211
|
+
conflictRef = { hit: false };
|
|
212
|
+
session = new Session(detectConflicts(acquired.session.getStorage(), conflictRef));
|
|
213
|
+
if (!spec.sessionId) {
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
if (resume) {
|
|
218
|
+
await session.getStorage().setLeafId(resume.leafId);
|
|
219
|
+
}
|
|
220
|
+
else if (spec.resumeAt !== undefined) {
|
|
221
|
+
const entry = await session.getEntry(spec.resumeAt);
|
|
222
|
+
if (!entry) {
|
|
223
|
+
const e = new Error(`resumeAt entry "${spec.resumeAt}" not found in session "${spec.sessionId}"`);
|
|
224
|
+
e.code = "resume_at.not_found";
|
|
225
|
+
throw e;
|
|
226
|
+
}
|
|
227
|
+
if (entry.type !== "message" && entry.type !== "custom_message") {
|
|
228
|
+
const e = new Error(`resumeAt entry "${spec.resumeAt}" is a "${entry.type}" entry; resume-at requires a message boundary`);
|
|
229
|
+
e.code = "resume_at.not_a_message";
|
|
230
|
+
throw e;
|
|
231
|
+
}
|
|
232
|
+
if (entry.type === "message") {
|
|
233
|
+
const msg = entry.message;
|
|
234
|
+
if (msg?.role === "toolResult") {
|
|
235
|
+
const e = new Error(`resumeAt entry "${spec.resumeAt}" is a tool-result (mid-turn); resume-at requires a settled turn boundary (a user message or a finished assistant turn)`);
|
|
236
|
+
e.code = "resume_at.not_a_message";
|
|
237
|
+
throw e;
|
|
238
|
+
}
|
|
239
|
+
if (msg?.role === "assistant" && Array.isArray(msg.content) && msg.content.some((p) => p?.type === "toolCall")) {
|
|
240
|
+
const e = new Error(`resumeAt entry "${spec.resumeAt}" ends a turn mid-tool-call; resume-at requires a settled turn boundary`);
|
|
241
|
+
e.code = "resume_at.not_a_message";
|
|
242
|
+
throw e;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
await session.getStorage().setLeafId(spec.resumeAt);
|
|
246
|
+
}
|
|
247
|
+
await reconcileInterruptedSession(session, toolEffects, resume?.suspendedBatch);
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
if (isSessionConflict(err) && attempt < RECONCILE_MAX_RETRIES) {
|
|
252
|
+
if (sessions.forget) {
|
|
253
|
+
await Promise.resolve(sessions.forget(spec.sessionId)).catch(() => undefined);
|
|
254
|
+
}
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
await Promise.resolve(sessions.forget ? sessions.forget(acquired.sessionId) : undefined).catch(() => undefined);
|
|
258
|
+
throw err;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const sessionId = acquired.sessionId;
|
|
262
|
+
const hostTaskId = spec.taskId ?? sessionId;
|
|
263
|
+
const taskScope = spec.principal ?? "default";
|
|
264
|
+
defaultTaskRegistry.maybeGc();
|
|
265
|
+
const forgetOnThrow = () => forgetQuietly(sessions, sessionId);
|
|
266
|
+
const extraBodyCollisions = reservedCollisions(model.extraBody, reservedFor(model.api));
|
|
267
|
+
if (extraBodyCollisions.length > 0) {
|
|
268
|
+
deps.onError?.(new Error(`model.extraBody contains reserved key(s) [${extraBodyCollisions.join(", ")}] that core owns and sets itself — they are ignored. Remove them from extraBody.`), { phase: "config", sessionId });
|
|
269
|
+
}
|
|
270
|
+
const nestedStats = { tokens: 0, turns: 0, tasks: 0, costUsd: 0, costMicroUsd: 0 };
|
|
271
|
+
if (resume) {
|
|
272
|
+
nestedStats.tokens = resume.seed.nestedStats.tokens;
|
|
273
|
+
nestedStats.turns = resume.seed.nestedStats.turns;
|
|
274
|
+
nestedStats.tasks = resume.seed.nestedStats.tasks;
|
|
275
|
+
nestedStats.costUsd = resume.seed.nestedStats.costUsd;
|
|
276
|
+
nestedStats.costMicroUsd = resume.seed.nestedStats.costMicroUsd;
|
|
277
|
+
}
|
|
278
|
+
const reportUsage = (u) => {
|
|
279
|
+
nestedStats.tokens += u.tokens;
|
|
280
|
+
nestedStats.turns += u.turns;
|
|
281
|
+
nestedStats.tasks += u.tasks;
|
|
282
|
+
nestedStats.costUsd += u.costUsd ?? 0;
|
|
283
|
+
nestedStats.costMicroUsd += u.costMicroUsd ?? 0;
|
|
284
|
+
};
|
|
285
|
+
const explicitGlobalThreshold = spec.toolResultThresholdChars ?? deps.toolResultThresholdChars;
|
|
286
|
+
const offloadThreshold = explicitGlobalThreshold ?? DEFAULT_TOOL_RESULT_THRESHOLD_CHARS;
|
|
287
|
+
const offloadEnabled = Number.isFinite(offloadThreshold) && offloadThreshold > 0;
|
|
288
|
+
const rawOffloadStore = offloadEnabled ? (deps.toolResultStore ?? new InMemoryToolResultStore()) : undefined;
|
|
289
|
+
const offloadStore = rawOffloadStore instanceof RunnerSharedToolResultStore
|
|
290
|
+
? new ScopedToolResultStore(rawOffloadStore, taskScope)
|
|
291
|
+
: rawOffloadStore;
|
|
292
|
+
const maybeOffload = (tool, perTool) => {
|
|
293
|
+
if (!offloadStore || perTool?.offload === false)
|
|
294
|
+
return tool;
|
|
295
|
+
return withToolResultOffload(tool, offloadStore, perTool?.offloadThresholdChars ?? offloadThreshold, sessionId);
|
|
296
|
+
};
|
|
297
|
+
const firstPartyOffload = (tool) => {
|
|
298
|
+
const policy = firstPartyOffloadPolicy(tool.name);
|
|
299
|
+
if (policy.offload === false)
|
|
300
|
+
return maybeOffload(tool, policy);
|
|
301
|
+
return maybeOffload(tool, explicitGlobalThreshold === undefined ? policy : undefined);
|
|
302
|
+
};
|
|
303
|
+
const mcpOffload = (tool) => {
|
|
304
|
+
if (explicitGlobalThreshold !== undefined)
|
|
305
|
+
return maybeOffload(tool);
|
|
306
|
+
return maybeOffload(tool, { offloadThresholdChars: tool.mcpMaxResultSizeChars ?? 50_000 });
|
|
307
|
+
};
|
|
308
|
+
if (offloadStore && (spec.tools ?? []).some((t) => t.name === OFFLOAD_TOOL_NAME)) {
|
|
309
|
+
const e = new Error(`Tool name "${OFFLOAD_TOOL_NAME}" is reserved when large-result offload is enabled.`);
|
|
310
|
+
e.code = "config.reserved_tool_name";
|
|
311
|
+
await forgetOnThrow();
|
|
312
|
+
throw e;
|
|
313
|
+
}
|
|
314
|
+
let ownedEnv;
|
|
315
|
+
let mcp;
|
|
316
|
+
try {
|
|
317
|
+
ownedEnv = deps.executionEnvFactory
|
|
318
|
+
? await deps.executionEnvFactory({
|
|
319
|
+
sessionId,
|
|
320
|
+
taskId: spec.taskId,
|
|
321
|
+
...(internals?.isolation ? { isolation: internals.isolation } : {}),
|
|
322
|
+
...(internals?.parentCwd ? { parentCwd: internals.parentCwd } : {}),
|
|
323
|
+
})
|
|
324
|
+
: undefined;
|
|
325
|
+
}
|
|
326
|
+
catch (factoryErr) {
|
|
327
|
+
await forgetOnThrow();
|
|
328
|
+
throw factoryErr;
|
|
329
|
+
}
|
|
330
|
+
const executionEnv = ownedEnv ?? deps.executionEnv ?? new StubExecutionEnv();
|
|
331
|
+
const handsEnabled = ownedEnv !== undefined || deps.executionEnv !== undefined;
|
|
332
|
+
const taskRootPath = internals?.isolation === "worktree" || !deps.rootPath ? executionEnv.cwd : deps.rootPath;
|
|
333
|
+
const abortController = new AbortController();
|
|
334
|
+
if (spec.signal?.aborted)
|
|
335
|
+
abortController.abort();
|
|
336
|
+
try {
|
|
337
|
+
if (resume?.workspaceHandle !== undefined) {
|
|
338
|
+
const failResume = (message, cause) => {
|
|
339
|
+
const e = new Error(message, cause ? { cause } : undefined);
|
|
340
|
+
e.code = "resume.env_failed";
|
|
341
|
+
throw e;
|
|
342
|
+
};
|
|
343
|
+
const handle = resume.workspaceHandle;
|
|
344
|
+
if (ownedEnv === undefined || !isRemoteExecutionEnv(ownedEnv)) {
|
|
345
|
+
failResume("resume needs a RemoteExecutionEnv from executionEnvFactory to restore the workspace snapshot");
|
|
346
|
+
}
|
|
347
|
+
else if (handle.snapshotId === undefined) {
|
|
348
|
+
if (handle.restoreMode !== "park_only" && isSuspendable(ownedEnv)) {
|
|
349
|
+
failResume("checkpoint workspaceHandle has no snapshotId and is not a park_only handle, but the resumed env is suspendable — refusing to resume on a possibly-unrestored workspace (corrupt checkpoint?)");
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
const restoreSignal = spec.signal
|
|
354
|
+
? AbortSignal.any([abortController.signal, spec.signal])
|
|
355
|
+
: abortController.signal;
|
|
356
|
+
const restored = await ownedEnv.resumeVM(handle.snapshotId, { abortSignal: restoreSignal });
|
|
357
|
+
if (!restored.ok) {
|
|
358
|
+
failResume(`resumeVM failed (${restored.error.code}): ${restored.error.message}`, restored.error);
|
|
359
|
+
}
|
|
360
|
+
const init = await ownedEnv.postResumeInit();
|
|
361
|
+
if (!init.ok) {
|
|
362
|
+
failResume(`postResumeInit failed (${init.error.code}): ${init.error.message}`, init.error);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const rewindTarget = spec.resumeAt !== undefined ? (spec.rewindFiles ? spec.resumeAt : undefined) : spec.rewindFilesTo;
|
|
367
|
+
if (rewindTarget !== undefined && deps.fileSnapshotStore && handsEnabled) {
|
|
368
|
+
const restoreRoot = taskRootPath;
|
|
369
|
+
const restoreSignal = spec.signal ? AbortSignal.any([abortController.signal, spec.signal]) : abortController.signal;
|
|
370
|
+
const restored = await deps.fileSnapshotStore.restore(sessionId, rewindTarget, executionEnv, restoreRoot, restoreSignal);
|
|
371
|
+
if (!restored.ok) {
|
|
372
|
+
if (restored.error.code === "not_found") {
|
|
373
|
+
try {
|
|
374
|
+
deps.onError?.(new Error(`rewind-files: no snapshot for entry "${rewindTarget}" — files left unchanged`), { phase: "rewind", sessionId });
|
|
375
|
+
}
|
|
376
|
+
catch {
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
const e = new Error(`rewind-files restore failed (${restored.error.code}): ${restored.error.message}`);
|
|
381
|
+
e.code = "rewind.restore_failed";
|
|
382
|
+
throw e;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
const harnessRef = {};
|
|
387
|
+
const skillScope = new ActiveSkillScope();
|
|
388
|
+
const forwardSink = internals?.onForwardEvent;
|
|
389
|
+
const forwardEvent = forwardSink
|
|
390
|
+
? (e) => {
|
|
391
|
+
if (e.type === "task_progress")
|
|
392
|
+
forwardSink(e);
|
|
393
|
+
else if (spec.forwardSubagentEvents === true &&
|
|
394
|
+
(e.type === "text_delta" || e.type === "reasoning_delta" || e.type === "tool_start" || e.type === "tool_end")) {
|
|
395
|
+
forwardSink(e);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
: undefined;
|
|
399
|
+
const reviewRequestRef = {};
|
|
400
|
+
const requestReview = (opts) => {
|
|
401
|
+
if (reviewRequestRef.pending === undefined) {
|
|
402
|
+
reviewRequestRef.pending = opts?.reason !== undefined ? { reason: opts.reason } : {};
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
const requestStopAfterTurn = () => {
|
|
406
|
+
harnessRef.current?.requestStopAfterTurn();
|
|
407
|
+
};
|
|
408
|
+
const planModeRef = { active: false };
|
|
409
|
+
const enterPlanMode = () => {
|
|
410
|
+
planModeRef.active = true;
|
|
411
|
+
};
|
|
412
|
+
const subagentRetain = spec.retainSubagentSessions ? new SubagentRetainLedger(spec.retainSubagentSessions) : undefined;
|
|
413
|
+
const worktreeIsolation = spec.handsReadOnly !== true ? createSubagentWorktreeHelper(executionEnv, taskRootPath) : undefined;
|
|
414
|
+
let agentForkDenial;
|
|
415
|
+
let observersActive = false;
|
|
416
|
+
let autoModeDecider;
|
|
417
|
+
const tools = (spec.tools ?? []).map((t) => maybeOffload(defineTool({
|
|
418
|
+
...t,
|
|
419
|
+
execute: (args, ctx) => t.execute(args, {
|
|
420
|
+
...ctx,
|
|
421
|
+
reportUsage,
|
|
422
|
+
model: harnessRef.current?.getModel(),
|
|
423
|
+
thinkingLevel: harnessRef.current?.getThinkingLevel(),
|
|
424
|
+
principal: spec.principal,
|
|
425
|
+
clientContext: spec.clientContext,
|
|
426
|
+
parentCwd: taskRootPath,
|
|
427
|
+
activeSkillScope: () => skillScope.active(),
|
|
428
|
+
taskId: hostTaskId,
|
|
429
|
+
sessionId,
|
|
430
|
+
...(spec.backgroundScope !== undefined ? { backgroundScope: spec.backgroundScope } : {}),
|
|
431
|
+
...(deps.onBackgroundChildEvent ? { onBackgroundChildEvent: deps.onBackgroundChildEvent } : {}),
|
|
432
|
+
...(internals?.onTaskNotification ? { onTaskNotification: internals.onTaskNotification } : {}),
|
|
433
|
+
...(forwardEvent ? { forwardEvent } : {}),
|
|
434
|
+
...(internals?.onSubagentSpawn ? { onSubagentSpawn: internals.onSubagentSpawn } : {}),
|
|
435
|
+
...(subagentRetain ? { subagentRetain } : {}),
|
|
436
|
+
...(worktreeIsolation ? { worktreeIsolation } : {}),
|
|
437
|
+
...(internals?.insideFork === true ? { insideFork: true } : {}),
|
|
438
|
+
...(agentForkDenial !== undefined ? { forkAccess: { denied: agentForkDenial } } : {}),
|
|
439
|
+
...(observersActive ? { observersAllowed: true } : {}),
|
|
440
|
+
requestReview,
|
|
441
|
+
requestStopAfterTurn,
|
|
442
|
+
...(spec.enablePlanMode === true ? { enterPlanMode } : {}),
|
|
443
|
+
}),
|
|
444
|
+
}), t));
|
|
445
|
+
const blockedRef = {};
|
|
446
|
+
if (spec.enableBlockedReport !== false) {
|
|
447
|
+
tools.push(makeReportBlockedTool(blockedRef));
|
|
448
|
+
}
|
|
449
|
+
if (spec.enablePlanMode === true) {
|
|
450
|
+
tools.push(defineTool(createPresentPlanTool(requestReview)));
|
|
451
|
+
if ((spec.checkpointStore ?? deps.checkpointStore) !== undefined) {
|
|
452
|
+
tools.push(defineTool(createEnterPlanModeTool(enterPlanMode)));
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
let runtimeCaps;
|
|
456
|
+
if (deps.runtimeCapsResolver) {
|
|
457
|
+
try {
|
|
458
|
+
runtimeCaps = (await deps.runtimeCapsResolver(spec.principal)) ?? undefined;
|
|
459
|
+
}
|
|
460
|
+
catch (err) {
|
|
461
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
|
|
462
|
+
runtimeCaps = { allowWorkflows: false, allowFork: false };
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
agentForkDenial = forkGovernanceDenial(spec.enableFork, runtimeCaps?.allowFork);
|
|
466
|
+
observersActive = runtimeCaps?.allowObservers === true;
|
|
467
|
+
if (runtimeCaps?.autoMode === true && deps.autoMode !== undefined) {
|
|
468
|
+
const am = deps.autoMode;
|
|
469
|
+
let classifierModel;
|
|
470
|
+
try {
|
|
471
|
+
classifierModel = resolveTaskModel({ modelRole: "classifier" }, deps).model;
|
|
472
|
+
}
|
|
473
|
+
catch {
|
|
474
|
+
classifierModel = model;
|
|
475
|
+
}
|
|
476
|
+
const classifierSystemPrompt = buildAutoModePrompt(am);
|
|
477
|
+
const classifierRuntime = brainToRuntime(deps.brain);
|
|
478
|
+
autoModeDecider = createAutoModeDecider({
|
|
479
|
+
...(am.timeoutMs !== undefined ? { timeoutMs: am.timeoutMs } : {}),
|
|
480
|
+
...(am.failureThreshold !== undefined ? { failureThreshold: am.failureThreshold } : {}),
|
|
481
|
+
...(am.onBreakerOpen !== undefined ? { onBreakerOpen: am.onBreakerOpen } : {}),
|
|
482
|
+
classify: async (input, signal) => {
|
|
483
|
+
const ctx = await session.buildContext();
|
|
484
|
+
const known = ctx.messages.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult");
|
|
485
|
+
const userPrompt = renderAutoModeWindow(known, am.window) + renderAutoModeAction(input);
|
|
486
|
+
const response = await classifierRuntime.completeSimple(classifierModel, { systemPrompt: classifierSystemPrompt, messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] }, { signal });
|
|
487
|
+
return response.content
|
|
488
|
+
.filter((c) => c.type === "text")
|
|
489
|
+
.map((c) => c.text)
|
|
490
|
+
.join("");
|
|
491
|
+
},
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
const deploymentWorkflowReady = runnerSelf !== undefined && isSelfOrchestrationActive(spec, deps);
|
|
495
|
+
const selfOrchestrationActive = deploymentWorkflowReady && runtimeCaps?.allowWorkflows !== false;
|
|
496
|
+
if (deploymentWorkflowReady && runtimeCaps?.allowWorkflows === false) {
|
|
497
|
+
deps.onError?.(new Error(`self-orchestration DENIED for principal "${spec.principal ?? ""}" by runtimeCaps.allowWorkflows=false ` +
|
|
498
|
+
`(per-principal entitlement governance, not a misconfiguration — the run_workflow tool is not mounted)`), { phase: "config", sessionId });
|
|
499
|
+
}
|
|
500
|
+
let workflowToolsActive = false;
|
|
501
|
+
if (selfOrchestrationActive && runnerSelf && deps.workflowScriptRunner && deps.workflowGovernanceBaseline) {
|
|
502
|
+
workflowToolsActive = true;
|
|
503
|
+
toolEffects.set(RUN_WORKFLOW_TOOL_NAME, "write");
|
|
504
|
+
tools.push(await createRunWorkflowTool({
|
|
505
|
+
runner: runnerSelf,
|
|
506
|
+
scriptRunner: deps.workflowScriptRunner,
|
|
507
|
+
governanceBaseline: deps.workflowGovernanceBaseline,
|
|
508
|
+
models: deps.models,
|
|
509
|
+
agents: deps.agents,
|
|
510
|
+
builtinAgents: deps.builtinAgents,
|
|
511
|
+
store: deps.workflowRunStore,
|
|
512
|
+
journalStore: deps.workflowJournalStore,
|
|
513
|
+
scriptStore: deps.workflowScriptStore,
|
|
514
|
+
builtinWorkflows: deps.builtinWorkflows,
|
|
515
|
+
onAgentSpawn: deps.onWorkflowAgentSpawn,
|
|
516
|
+
scope: taskScope,
|
|
517
|
+
notifier: deps.workflowCompletionNotifier,
|
|
518
|
+
originatingSessionId: sessionId,
|
|
519
|
+
taskRegistry: defaultTaskRegistry,
|
|
520
|
+
taskNotification: internals?.onTaskNotification,
|
|
521
|
+
taskOwner: hostTaskId,
|
|
522
|
+
limits: deps.workflowLimits,
|
|
523
|
+
sourceTaskId: hostTaskId,
|
|
524
|
+
principal: spec.principal,
|
|
525
|
+
workflowDepth: internals?.workflowDepth,
|
|
526
|
+
parentCwd: taskRootPath,
|
|
527
|
+
parentThinking: () => harnessRef.current?.getThinkingLevel() ?? thinking,
|
|
528
|
+
}));
|
|
529
|
+
}
|
|
530
|
+
const suspendRef = {};
|
|
531
|
+
const reviewRef = {};
|
|
532
|
+
const suspendLoopRef = { hit: false };
|
|
533
|
+
const compactionReuseRef = { consecutive: 0 };
|
|
534
|
+
const trimPressureRef = { droppedMessages: false };
|
|
535
|
+
const liveSpendRef = {};
|
|
536
|
+
const now = deps.now ?? Date.now;
|
|
537
|
+
const humanReviewRef = {
|
|
538
|
+
count: resume?.priorHumanReview?.count ?? 0,
|
|
539
|
+
totalWaitMs: resume?.priorHumanReview?.totalWaitMs ?? 0,
|
|
540
|
+
gates: resume?.priorHumanReview?.gates ? [...resume.priorHumanReview.gates] : [],
|
|
541
|
+
};
|
|
542
|
+
const priorSuspendCount = resume?.priorSuspendCount ?? 0;
|
|
543
|
+
const maxSuspends = spec.maxSuspends ?? deps.maxSuspends ?? DEFAULT_MAX_SUSPENDS;
|
|
544
|
+
const maxSlices = spec.resourceSuspend?.maxSlices ?? DEFAULT_MAX_SLICES;
|
|
545
|
+
const priorLedger = resume?.priorLedger;
|
|
546
|
+
const resourceTotal = spec.resourceSuspend
|
|
547
|
+
? {
|
|
548
|
+
totalBudgetMicroUsd: spec.resourceSuspend.totalBudgetUsd !== undefined ? Math.round(spec.resourceSuspend.totalBudgetUsd * 1e6) : undefined,
|
|
549
|
+
}
|
|
550
|
+
: undefined;
|
|
551
|
+
const budgetSnapshot = {
|
|
552
|
+
resourceRemainingMicroUsd: priorLedger
|
|
553
|
+
? remainingBudgetMicroUsd(priorLedger)
|
|
554
|
+
: resourceTotal?.totalBudgetMicroUsd,
|
|
555
|
+
resourceSpentMicroUsd: priorLedger?.spentMicroUsd ?? 0,
|
|
556
|
+
suspendCount: priorSuspendCount,
|
|
557
|
+
};
|
|
558
|
+
let readFileStateForCheckpoint;
|
|
559
|
+
let seedContextFiles;
|
|
560
|
+
let handsCwdRef;
|
|
561
|
+
let worktreeSessionRef;
|
|
562
|
+
let backgroundTaskToolsActive = false;
|
|
563
|
+
let suspendForResource;
|
|
564
|
+
let suspendForReview;
|
|
565
|
+
const outputRef = {};
|
|
566
|
+
if (resume?.seed.outputRef) {
|
|
567
|
+
outputRef.value = resume.seed.outputRef.value;
|
|
568
|
+
outputRef.set = resume.seed.outputRef.set;
|
|
569
|
+
}
|
|
570
|
+
if (spec.outputSchema) {
|
|
571
|
+
if ((spec.tools ?? []).some((t) => t.name === OUTPUT_TOOL_NAME)) {
|
|
572
|
+
const e = new Error(`Tool name "${OUTPUT_TOOL_NAME}" is reserved when TaskSpec.outputSchema is set.`);
|
|
573
|
+
e.code = "config.reserved_tool_name";
|
|
574
|
+
throw e;
|
|
575
|
+
}
|
|
576
|
+
const compiled = compileOutputSchema(spec.outputSchema);
|
|
577
|
+
if ("error" in compiled) {
|
|
578
|
+
const e = new Error(`TaskSpec.outputSchema is not a valid JSON Schema: ${compiled.error}`);
|
|
579
|
+
e.code = "config.invalid_output_schema";
|
|
580
|
+
throw e;
|
|
581
|
+
}
|
|
582
|
+
if (!compiled.strict) {
|
|
583
|
+
try {
|
|
584
|
+
deps.onError?.(new Error(`structured-output: strict schema derivation fell back to non-strict (${compiled.fallbackReason}) — the schema is served to the model as-is`), { phase: "config", sessionId });
|
|
585
|
+
}
|
|
586
|
+
catch {
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
tools.push(makeOutputTool(outputRef, spec.outputSchema, compiled.strict ? compiled.modelSchema : undefined));
|
|
590
|
+
}
|
|
591
|
+
mcp = spec.mcp?.length
|
|
592
|
+
? await materializeMcpTools(spec.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer)
|
|
593
|
+
: { tools: [], toolAxes: [], warnings: [], serverInstructions: [], instructionsDelta: { pendingAdds: [], pendingRemovals: [] }, statuses: [], dispose: async () => { } };
|
|
594
|
+
for (const w of mcp.warnings)
|
|
595
|
+
deps.onError?.(w, { phase: "mcp", sessionId });
|
|
596
|
+
{
|
|
597
|
+
const callerNames = new Set((spec.tools ?? []).flatMap((t) => [t.name, ...(t.aliases ?? [])]));
|
|
598
|
+
const clash = mcp.tools.find((t) => [t.name, ...(t.aliases ?? [])].some((name) => callerNames.has(name)));
|
|
599
|
+
if (clash) {
|
|
600
|
+
await mcp.dispose();
|
|
601
|
+
const e = new Error(`Tool name "${clash.name}" is reserved by an injected MCP tool — a caller tool of the same name would silently shadow it.`);
|
|
602
|
+
e.code = "config.reserved_tool_name";
|
|
603
|
+
throw e;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
tools.push(...mcp.tools.map((t) => mcpOffload(t)));
|
|
607
|
+
for (const axis of mcp.toolAxes) {
|
|
608
|
+
if (axis.irreversibility === "always") {
|
|
609
|
+
irreversibilityTier.set(axis.name, "always");
|
|
610
|
+
irreversibleTools.add(axis.name);
|
|
611
|
+
}
|
|
612
|
+
if (axis.egress) {
|
|
613
|
+
if (axis.effect !== undefined && axis.effect !== "write") {
|
|
614
|
+
const e = new Error(`MCP tool "${axis.name}" resolves to egress:true with effect:"${axis.effect}" — an egress tool (external write) must have effect:"write". Clear egress (toolAxes egress:false) if it is a pure read, or set effect:"write".`);
|
|
615
|
+
e.code = "config.egress_requires_write_effect";
|
|
616
|
+
throw e;
|
|
617
|
+
}
|
|
618
|
+
egressTools.add(axis.name);
|
|
619
|
+
}
|
|
620
|
+
if (!toolEffects.has(axis.name))
|
|
621
|
+
toolEffects.set(axis.name, axis.effect ?? "write");
|
|
622
|
+
}
|
|
623
|
+
const callCapOn = spec.limits?.callCapByDeadline !== false;
|
|
624
|
+
const callCapRef = spec.limits?.timeoutSec &&
|
|
625
|
+
spec.limits.timeoutSec > 0 &&
|
|
626
|
+
(callCapOn || spec.limits.gracefulFinalize !== false)
|
|
627
|
+
? createCallCapRef()
|
|
628
|
+
: undefined;
|
|
629
|
+
if (callCapRef) {
|
|
630
|
+
callCapRef.staticCapTokens =
|
|
631
|
+
spec.limits?.maxOutputTokens !== undefined && spec.limits.maxOutputTokens > 0
|
|
632
|
+
? spec.limits.maxOutputTokens
|
|
633
|
+
: model.maxTokens;
|
|
634
|
+
}
|
|
635
|
+
const execClamp = callCapRef
|
|
636
|
+
? {
|
|
637
|
+
deadlineMs: () => softExecDeadlineMs(callCapRef),
|
|
638
|
+
onClamp: () => {
|
|
639
|
+
callCapRef.toolClamps = (callCapRef.toolClamps ?? 0) + 1;
|
|
640
|
+
},
|
|
641
|
+
}
|
|
642
|
+
: undefined;
|
|
643
|
+
const memoryWriteGateRef = {};
|
|
644
|
+
const additionalRootsCanonical = [];
|
|
645
|
+
if (handsEnabled) {
|
|
646
|
+
const rootRaw = taskRootPath;
|
|
647
|
+
const canon = await executionEnv.canonicalPath(rootRaw);
|
|
648
|
+
const rootCanonical = canon.ok ? canon.value : rootRaw;
|
|
649
|
+
for (const dir of spec.additionalDirectories ?? []) {
|
|
650
|
+
if (!dir || !dir.trim())
|
|
651
|
+
continue;
|
|
652
|
+
const c = await executionEnv.canonicalPath(dir);
|
|
653
|
+
if (c.ok) {
|
|
654
|
+
additionalRootsCanonical.push(c.value);
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
deps.onError?.(new Error(`additionalDirectories entry skipped (cannot canonicalize): ${dir}`), {
|
|
658
|
+
phase: "config",
|
|
659
|
+
sessionId,
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
const readFileState = new Map(resume?.seed.readFileState ?? []);
|
|
664
|
+
readFileStateForCheckpoint = readFileState;
|
|
665
|
+
seedContextFiles = async (files) => {
|
|
666
|
+
for (const f of files) {
|
|
667
|
+
const rk = await resolveKey(executionEnv, rootCanonical, f.path, undefined, undefined, additionalRootsCanonical);
|
|
668
|
+
if (rk.ok)
|
|
669
|
+
seedReadFileStateFromContext(readFileState, rk.key, f.content);
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
const handsIncludeShell = !(executionEnv instanceof StubExecutionEnv);
|
|
673
|
+
const handsReadOnly = spec.handsReadOnly === true;
|
|
674
|
+
backgroundTaskToolsActive = handsIncludeShell && !handsReadOnly && hasBackgroundShell(executionEnv);
|
|
675
|
+
if (handsIncludeShell && !handsReadOnly) {
|
|
676
|
+
handsCwdRef = { current: rootCanonical };
|
|
677
|
+
if (resume?.seed.handsCwd !== undefined)
|
|
678
|
+
handsCwdRef.current = resume.seed.handsCwd;
|
|
679
|
+
}
|
|
680
|
+
const band = createHandsToolkit(executionEnv, readFileState, rootCanonical, {
|
|
681
|
+
...(additionalRootsCanonical.length > 0 ? { additionalRoots: additionalRootsCanonical } : {}),
|
|
682
|
+
includeShell: handsIncludeShell,
|
|
683
|
+
readOnly: handsReadOnly,
|
|
684
|
+
...(handsCwdRef ? { cwdRef: handsCwdRef } : {}),
|
|
685
|
+
taskRegistry: defaultTaskRegistry,
|
|
686
|
+
taskOwner: hostTaskId,
|
|
687
|
+
taskScope,
|
|
688
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
689
|
+
...(internals?.onTaskNotification !== undefined ? { taskNotification: internals.onTaskNotification } : {}),
|
|
690
|
+
...(internals?.detachHub !== undefined ? { detachHub: internals.detachHub } : {}),
|
|
691
|
+
...(execClamp !== undefined ? { execClamp } : {}),
|
|
692
|
+
pdfModelCapabilities: pdfModelCapabilitiesOf(model),
|
|
693
|
+
...(deps.hands?.bashReadonlyAllow !== undefined ? { bashReadonlyAllow: deps.hands.bashReadonlyAllow } : {}),
|
|
694
|
+
...(deps.hands?.commitCoAuthor !== undefined ? { commitCoAuthor: deps.hands.commitCoAuthor } : {}),
|
|
695
|
+
...(deps.hands?.readImageDownsampler !== undefined ? { readImageDownsampler: deps.hands.readImageDownsampler } : {}),
|
|
696
|
+
beforeWrite: async (w) => {
|
|
697
|
+
const deploymentGate = deps.hands?.beforeWrite;
|
|
698
|
+
if (deploymentGate) {
|
|
699
|
+
const verdict = await deploymentGate(w);
|
|
700
|
+
if (verdict !== undefined && verdict.ok === false)
|
|
701
|
+
return verdict;
|
|
702
|
+
}
|
|
703
|
+
return memoryWriteGateRef.current?.(w);
|
|
704
|
+
},
|
|
705
|
+
mountBackgroundTaskTools: false,
|
|
706
|
+
});
|
|
707
|
+
{
|
|
708
|
+
const bandNames = new Set(band.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
|
|
709
|
+
const shadowed = (spec.tools ?? []).filter((t) => [t.name, ...(t.aliases ?? [])].some((n) => bandNames.has(n)));
|
|
710
|
+
if (shadowed.length > 0) {
|
|
711
|
+
const names = shadowed.map((t) => `"${t.name}"`).join(", ");
|
|
712
|
+
deps.onError?.(new Error(`spec.tools ${shadowed.length > 1 ? "entries" : "entry"} ${names} collide${shadowed.length > 1 ? "" : "s"} with the built-in hands tool band — the built-in wins (registered later; the harness tool Map is last-write-wins) and the caller tool never dispatches this task. Rename the caller tool, or don't inject executionEnv if you intend to replace the band.`), { phase: "config", sessionId });
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
tools.push(...band.map((t) => firstPartyOffload(t)));
|
|
716
|
+
const shellGate = spec.shellGate ?? "off";
|
|
717
|
+
if (shellGate !== "off" && !(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
|
|
718
|
+
shellGatedBash = !egressTools.has("Bash") && !irreversibilityTier.has("Bash");
|
|
719
|
+
irreversibilityTier.set("Bash", shellGate === "always" ? "always" : "maybe");
|
|
720
|
+
irreversibleTools.add("Bash");
|
|
721
|
+
if (shellGate === "classify")
|
|
722
|
+
reversibilityProbes.set("Bash", bashReversibilityProbe());
|
|
723
|
+
if (backgroundTaskToolsActive) {
|
|
724
|
+
shellGatedMonitor = !egressTools.has("Monitor") && !irreversibilityTier.has("Monitor");
|
|
725
|
+
irreversibilityTier.set("Monitor", shellGate === "always" ? "always" : "maybe");
|
|
726
|
+
irreversibleTools.add("Monitor");
|
|
727
|
+
if (shellGate === "classify")
|
|
728
|
+
reversibilityProbes.set("Monitor", bashReversibilityProbe());
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
if (backgroundTaskToolsActive || workflowToolsActive) {
|
|
733
|
+
toolEffects.set("TaskOutput", "read");
|
|
734
|
+
toolEffects.set("TaskStop", "write");
|
|
735
|
+
tools.push(firstPartyOffload(createTaskOutputTool({ registry: defaultTaskRegistry, owner: hostTaskId, scope: taskScope, sessionId, workflowStore: deps.workflowRunStore })), firstPartyOffload(createTaskStopTool({ registry: defaultTaskRegistry, owner: hostTaskId, scope: taskScope, sessionId, workflowStore: deps.workflowRunStore })));
|
|
736
|
+
if (runnerSelf && !(spec.tools ?? []).some((t) => t.name === SEND_MESSAGE_TOOL_NAME)) {
|
|
737
|
+
tools.push(firstPartyOffload(createSendMessageTool({
|
|
738
|
+
runner: runnerSelf,
|
|
739
|
+
registry: defaultTaskRegistry,
|
|
740
|
+
...(subagentRetain ? { retain: subagentRetain } : {}),
|
|
741
|
+
owner: hostTaskId,
|
|
742
|
+
scope: taskScope,
|
|
743
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
744
|
+
...(internals?.onTaskNotification !== undefined ? { notify: internals.onTaskNotification } : {}),
|
|
745
|
+
...(internals?.onSubagentSpawn !== undefined ? { sink: internals.onSubagentSpawn } : {}),
|
|
746
|
+
})));
|
|
747
|
+
if (!(spec.tools ?? []).some((t) => t.name === AGENT_TRANSCRIPT_TOOL_NAME)) {
|
|
748
|
+
tools.push(firstPartyOffload(createAgentTranscriptTool({
|
|
749
|
+
runner: runnerSelf,
|
|
750
|
+
registry: defaultTaskRegistry,
|
|
751
|
+
owner: hostTaskId,
|
|
752
|
+
scope: taskScope,
|
|
753
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
754
|
+
})));
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
if (backgroundTaskToolsActive) {
|
|
759
|
+
toolEffects.set("Monitor", "write");
|
|
760
|
+
tools.push(firstPartyOffload(createMonitorTool(executionEnv, {
|
|
761
|
+
registry: defaultTaskRegistry,
|
|
762
|
+
owner: hostTaskId,
|
|
763
|
+
scope: taskScope,
|
|
764
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
765
|
+
...(internals?.onTaskNotification !== undefined ? { onTaskNotification: internals.onTaskNotification } : {}),
|
|
766
|
+
...(handsCwdRef !== undefined ? { cwdRef: handsCwdRef } : {}),
|
|
767
|
+
})));
|
|
768
|
+
}
|
|
769
|
+
if (handsCwdRef !== undefined) {
|
|
770
|
+
toolEffects.set("EnterWorktree", "write");
|
|
771
|
+
toolEffects.set("ExitWorktree", "write");
|
|
772
|
+
worktreeSessionRef = { ...(resume?.seed.activeWorktree ? { current: { ...resume.seed.activeWorktree } } : {}) };
|
|
773
|
+
tools.push(...createWorktreeTools(executionEnv, { repoRoot: taskRootPath, cwdRef: handsCwdRef, session: worktreeSessionRef }).map((t) => firstPartyOffload(t)));
|
|
774
|
+
}
|
|
775
|
+
if (offloadStore)
|
|
776
|
+
tools.push(makeReadToolResultTool(offloadStore));
|
|
777
|
+
const onQuestion = spec.onQuestion ?? deps.onQuestion;
|
|
778
|
+
if (onQuestion)
|
|
779
|
+
tools.push(createAskUserQuestionTool(onQuestion, { principal: spec.principal, sourceTaskId: sessionId }));
|
|
780
|
+
if (spec.handsReadOnly !== true) {
|
|
781
|
+
const schedScope = sessionId ?? spec.principal ?? spec.taskId ?? "default";
|
|
782
|
+
tools.push(...createSchedulerTools(executionEnv, {
|
|
783
|
+
scope: schedScope,
|
|
784
|
+
...(spec.principal !== undefined ? { principal: spec.principal } : {}),
|
|
785
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
786
|
+
requestStopAfterTurn,
|
|
787
|
+
}));
|
|
788
|
+
}
|
|
789
|
+
if (internals?.insideFork !== true &&
|
|
790
|
+
runnerSelf &&
|
|
791
|
+
sessionId !== undefined &&
|
|
792
|
+
hasSessionFork(runnerSelf.sessions) &&
|
|
793
|
+
agentForkDenial === "principal") {
|
|
794
|
+
deps.onError?.(new Error(`Fork DENIED for principal "${spec.principal ?? ""}" by runtimeCaps.allowFork=false ` +
|
|
795
|
+
`(per-principal entitlement governance, not a misconfiguration — Agent(subagent_type:"fork") will refuse honestly)`), { phase: "config", sessionId });
|
|
796
|
+
}
|
|
797
|
+
const lspManager = spec.lspManager ?? deps.lspManager;
|
|
798
|
+
if (lspManager) {
|
|
799
|
+
const lspRoot = taskRootPath;
|
|
800
|
+
tools.push(createLspTool(lspManager, { isPathIgnored: gitCheckIgnoreFilter(executionEnv, lspRoot), env: executionEnv }));
|
|
801
|
+
}
|
|
802
|
+
const lspDiagnostics = spec.lspDiagnostics !== false && lspManager?.diagnostics !== undefined && handsEnabled && spec.handsReadOnly !== true
|
|
803
|
+
? lspManager.diagnostics
|
|
804
|
+
: undefined;
|
|
805
|
+
const nudgeLspOnEdit = lspDiagnostics
|
|
806
|
+
? (rawPath) => {
|
|
807
|
+
const baseDir = handsCwdRef?.current ?? taskRootPath;
|
|
808
|
+
const isAbsForm = rawPath.startsWith("/") || /^[A-Za-z]:[\\/]/.test(rawPath);
|
|
809
|
+
const joinSep = baseDir.includes("\\") ? "\\" : "/";
|
|
810
|
+
const normalizeSegments = (pth) => {
|
|
811
|
+
const isUnc = pth.startsWith("\\\\");
|
|
812
|
+
const drive = /^[A-Za-z]:/.exec(pth)?.[0] ?? "";
|
|
813
|
+
const rest = pth.slice(drive.length + (isUnc ? 2 : 0));
|
|
814
|
+
const sep = pth.includes("\\") ? "\\" : "/";
|
|
815
|
+
const abs = rest.startsWith("/") || rest.startsWith("\\");
|
|
816
|
+
const outSegs = [];
|
|
817
|
+
for (const seg of rest.split(/[\\/]+/)) {
|
|
818
|
+
if (!seg || seg === ".")
|
|
819
|
+
continue;
|
|
820
|
+
if (seg === "..") {
|
|
821
|
+
if (outSegs.length > 0 && outSegs[outSegs.length - 1] !== "..")
|
|
822
|
+
outSegs.pop();
|
|
823
|
+
else if (!abs)
|
|
824
|
+
outSegs.push("..");
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
outSegs.push(seg);
|
|
828
|
+
}
|
|
829
|
+
return (isUnc ? sep + sep : "") + drive + (abs ? sep : "") + outSegs.join(sep);
|
|
830
|
+
};
|
|
831
|
+
const filePath = normalizeSegments(isAbsForm ? rawPath : baseDir.replace(/[\\/]+$/, "") + joinSep + rawPath);
|
|
832
|
+
lspDiagnostics.fileEdited(pathToUri(filePath));
|
|
833
|
+
void lspManager
|
|
834
|
+
.sessionFor(filePath, undefined, executionEnv)
|
|
835
|
+
.then((session) => session?.notifyFileChanged?.(filePath))
|
|
836
|
+
.catch(() => undefined);
|
|
837
|
+
}
|
|
838
|
+
: undefined;
|
|
839
|
+
const memorySpec = normalizeMemorySpec(spec.memory);
|
|
840
|
+
const useMemoryEngine = Boolean(memorySpec && memorySpec.enabled && deps.memoryBackend);
|
|
841
|
+
let memoryEngineSession;
|
|
842
|
+
if (useMemoryEngine && memorySpec) {
|
|
843
|
+
try {
|
|
844
|
+
const backend = deps.memoryBackend;
|
|
845
|
+
const pinned = backend.directoryRoot;
|
|
846
|
+
const engineRoot = resolveMemoryEngineRoot(deps.memoryEngineDir);
|
|
847
|
+
const repoRoot = deps.rootPath ?? taskRootPath;
|
|
848
|
+
let identityKey;
|
|
849
|
+
if (memorySpec.scopeContract === "v2" && repoRoot) {
|
|
850
|
+
const consumesProjectIdentity = [...memorySpec.scopes, ...(memorySpec.writeScope !== null ? [memorySpec.writeScope] : [])]
|
|
851
|
+
.map(parseScopeKey)
|
|
852
|
+
.some((k) => k.kind === "proj" || k.kind === "userproj");
|
|
853
|
+
let marker = null;
|
|
854
|
+
try {
|
|
855
|
+
marker = resolveProjectId(repoRoot);
|
|
856
|
+
}
|
|
857
|
+
catch (err) {
|
|
858
|
+
if (consumesProjectIdentity)
|
|
859
|
+
throw err;
|
|
860
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
|
|
861
|
+
}
|
|
862
|
+
if (marker) {
|
|
863
|
+
identityKey = marker.projectId;
|
|
864
|
+
const firstSwitch = lookupProjectIdHint(engineRoot, repoRoot) !== marker.projectId;
|
|
865
|
+
recordProjectIdHint(engineRoot, repoRoot, marker.projectId);
|
|
866
|
+
if (firstSwitch) {
|
|
867
|
+
try {
|
|
868
|
+
const oldCtl = deriveControlPlaneDir(engineRoot, repoRoot);
|
|
869
|
+
const newCtl = deriveProjectControlDir(engineRoot, marker.projectId);
|
|
870
|
+
const drained = drainMemoryAnnouncements(oldCtl);
|
|
871
|
+
for (const ann of drained.queue)
|
|
872
|
+
enqueueMemoryAnnouncement(newCtl, ann);
|
|
873
|
+
}
|
|
874
|
+
catch {
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
if (memorySpec.writeScope !== null) {
|
|
878
|
+
const w = parseScopeKey(memorySpec.writeScope);
|
|
879
|
+
if ((w.kind === "proj" || w.kind === "userproj") && w.projectId !== marker.projectId) {
|
|
880
|
+
const e = new Error(`memory scope contract v2: writeScope ${memorySpec.writeScope} targets projectId ${w.projectId}, ` +
|
|
881
|
+
`but this checkout's marker (.sema/project) declares ${marker.projectId} — refusing a mis-addressed write.`);
|
|
882
|
+
e.code = "config.memory_project_identity";
|
|
883
|
+
throw e;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
else {
|
|
888
|
+
const hint = lookupProjectIdHint(engineRoot, repoRoot);
|
|
889
|
+
if (hint !== undefined) {
|
|
890
|
+
deps.onError?.(new Error(`memory project marker missing but recoverable: ${repoRoot} previously carried projectId ${hint} ` +
|
|
891
|
+
`(.sema/project deleted?). Restore the marker to keep the identity-keyed memory mount; this session ` +
|
|
892
|
+
`falls back to the path-derived key.`), { phase: "config", sessionId });
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
const memoryDir = typeof pinned === "string" && pinned
|
|
897
|
+
? pinned
|
|
898
|
+
: identityKey !== undefined
|
|
899
|
+
? deriveProjectMemoryDir(engineRoot, identityKey)
|
|
900
|
+
: deriveRepoMemoryDir(engineRoot, repoRoot);
|
|
901
|
+
const planes = memorySpec.scopeContract === "v2" ? classifyScopePlanes(memorySpec.scopes, memorySpec.writeScope) : undefined;
|
|
902
|
+
const dual = planes !== undefined && needsDualRoots(planes);
|
|
903
|
+
const personalOnly = planes !== undefined && !dual && planes.project.length === 0 && planes.writePlane !== "project" && (planes.personal.length > 0 || planes.writePlane === "personal");
|
|
904
|
+
if (memorySpec.scopeContract === "v2" && !personalOnly) {
|
|
905
|
+
assertScopeContractPlacement({
|
|
906
|
+
parsedScopes: dual
|
|
907
|
+
? parsedProjectPlane(planes, memorySpec.writeScope)
|
|
908
|
+
: [...memorySpec.scopes, ...(memorySpec.writeScope !== null ? [memorySpec.writeScope] : [])].map(parseScopeKey),
|
|
909
|
+
memoryDir,
|
|
910
|
+
repoRoot,
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
const personalMemoryDir = derivePersonalMemoryDir(engineRoot);
|
|
914
|
+
const personalControlDir = derivePersonalControlDir(engineRoot);
|
|
915
|
+
const makePersonalEngine = () => new MemoryEngine({
|
|
916
|
+
backend: typeof pinned === "string" && pinned
|
|
917
|
+
? new FileMemoryEngineBackend(personalMemoryDir, { controlDir: personalControlDir })
|
|
918
|
+
: backend,
|
|
919
|
+
memoryDir: personalMemoryDir,
|
|
920
|
+
controlDir: personalControlDir,
|
|
921
|
+
});
|
|
922
|
+
let writeEngine;
|
|
923
|
+
let writeHandle;
|
|
924
|
+
let injectFn;
|
|
925
|
+
let harvestBoth;
|
|
926
|
+
if (dual) {
|
|
927
|
+
const projectEngine = new MemoryEngine({
|
|
928
|
+
backend,
|
|
929
|
+
memoryDir,
|
|
930
|
+
controlDir: identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveControlPlaneDir(engineRoot, repoRoot),
|
|
931
|
+
});
|
|
932
|
+
const personalEngine = makePersonalEngine();
|
|
933
|
+
const p = planes;
|
|
934
|
+
const projectHandle = await projectEngine.materialize(p.project, p.writePlane === "project" ? memorySpec.writeScope : null);
|
|
935
|
+
const personalHandle = await personalEngine.materialize(p.personal, p.writePlane === "personal" ? memorySpec.writeScope : null);
|
|
936
|
+
const writeIsPersonal = p.writePlane === "personal";
|
|
937
|
+
writeEngine = writeIsPersonal ? personalEngine : projectEngine;
|
|
938
|
+
writeHandle = writeIsPersonal ? personalHandle : projectHandle;
|
|
939
|
+
injectFn = () => mergeInjections(projectEngine.inject(projectHandle), personalEngine.inject(personalHandle));
|
|
940
|
+
harvestBoth = async () => {
|
|
941
|
+
const writeFirst = writeIsPersonal ? [personalEngine, personalHandle] : [projectEngine, projectHandle];
|
|
942
|
+
const readOther = writeIsPersonal ? [projectEngine, projectHandle] : [personalEngine, personalHandle];
|
|
943
|
+
const writeReport = await writeFirst[0].harvest(writeFirst[1]);
|
|
944
|
+
let readReport;
|
|
945
|
+
let readFailure;
|
|
946
|
+
try {
|
|
947
|
+
readReport = await readOther[0].harvest(readOther[1]);
|
|
948
|
+
}
|
|
949
|
+
catch (err) {
|
|
950
|
+
readFailure = err instanceof Error ? err.message : String(err);
|
|
951
|
+
}
|
|
952
|
+
const merged = readReport !== undefined ? mergeHarvestReports(writeReport, readReport) : writeReport;
|
|
953
|
+
if (readFailure !== undefined)
|
|
954
|
+
merged.warnings.push(`read-plane harvest failed (write-plane yield committed): ${readFailure}`);
|
|
955
|
+
return merged;
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
else if (personalOnly) {
|
|
959
|
+
const personalEngine = makePersonalEngine();
|
|
960
|
+
const handle = await personalEngine.materialize(memorySpec.scopes, memorySpec.writeScope);
|
|
961
|
+
writeEngine = personalEngine;
|
|
962
|
+
writeHandle = handle;
|
|
963
|
+
injectFn = () => personalEngine.inject(handle);
|
|
964
|
+
harvestBoth = () => personalEngine.harvest(handle);
|
|
965
|
+
}
|
|
966
|
+
else {
|
|
967
|
+
const engine = new MemoryEngine({
|
|
968
|
+
backend,
|
|
969
|
+
memoryDir,
|
|
970
|
+
controlDir: identityKey !== undefined ? deriveProjectControlDir(engineRoot, identityKey) : deriveControlPlaneDir(engineRoot, repoRoot),
|
|
971
|
+
});
|
|
972
|
+
const handle = await engine.materialize(memorySpec.scopes, memorySpec.writeScope);
|
|
973
|
+
writeEngine = engine;
|
|
974
|
+
writeHandle = handle;
|
|
975
|
+
injectFn = () => engine.inject(handle);
|
|
976
|
+
harvestBoth = () => engine.harvest(handle);
|
|
977
|
+
}
|
|
978
|
+
memoryWriteGateRef.current = (w) => writeEngine.gateWrite(writeHandle, w.key, w.content);
|
|
979
|
+
const harvestSafe = async (phase = "terminal") => {
|
|
980
|
+
try {
|
|
981
|
+
const report = await harvestBoth();
|
|
982
|
+
if (!report.ok && report.incident) {
|
|
983
|
+
deps.onError?.(new Error(`memory harvest refused (${report.incident.kind}): ${report.incident.detail}`), { phase: "memory", sessionId });
|
|
984
|
+
}
|
|
985
|
+
try {
|
|
986
|
+
deps.onMemoryHarvestReport?.(report, { sessionId, phase });
|
|
987
|
+
}
|
|
988
|
+
catch {
|
|
989
|
+
}
|
|
990
|
+
return report;
|
|
991
|
+
}
|
|
992
|
+
catch (err) {
|
|
993
|
+
try {
|
|
994
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "memory", sessionId });
|
|
995
|
+
}
|
|
996
|
+
catch {
|
|
997
|
+
}
|
|
998
|
+
return undefined;
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
memoryEngineSession = { engine: writeEngine, handle: writeHandle, inject: injectFn, harvest: harvestSafe };
|
|
1002
|
+
}
|
|
1003
|
+
catch (err) {
|
|
1004
|
+
if (typeof err.code === "string" && (err.code.startsWith("config.memory_scope") || err.code.startsWith("config.memory_project"))) {
|
|
1005
|
+
throw err;
|
|
1006
|
+
}
|
|
1007
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "memory", sessionId });
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
let memoryBlock;
|
|
1011
|
+
if (memorySpec && memorySpec.enabled && !useMemoryEngine) {
|
|
1012
|
+
const detail = deps.memoryStore
|
|
1013
|
+
? "RunnerDeps.memoryStore is retired (design/138 S4): the legacy remember/recall tools and <user_memory> injection no longer run. Configure RunnerDeps.memoryBackend (memory engine) instead; this task runs memory-less."
|
|
1014
|
+
: "TaskSpec.memory is enabled but RunnerDeps.memoryBackend is not configured; memory is inactive for this task (the legacy memoryStore fallback was retired in design/138 S4).";
|
|
1015
|
+
deps.onError?.(new Error(detail), { phase: "config", sessionId });
|
|
1016
|
+
}
|
|
1017
|
+
if (memoryEngineSession) {
|
|
1018
|
+
const injection = memoryEngineSession.inject();
|
|
1019
|
+
if (injection.block.trim())
|
|
1020
|
+
memoryBlock = injection.block;
|
|
1021
|
+
}
|
|
1022
|
+
if (deps.loadProjectMemory) {
|
|
1023
|
+
let loaded = null;
|
|
1024
|
+
try {
|
|
1025
|
+
loaded = await Promise.resolve(deps.loadProjectMemory({
|
|
1026
|
+
cwd: taskRootPath,
|
|
1027
|
+
handsEnabled,
|
|
1028
|
+
isSubagent: internals?.parentTaskId !== undefined,
|
|
1029
|
+
...(internals?.agentName ? { agentName: internals.agentName } : {}),
|
|
1030
|
+
}));
|
|
1031
|
+
}
|
|
1032
|
+
catch (err) {
|
|
1033
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
|
|
1034
|
+
}
|
|
1035
|
+
const projectMem = loaded !== null && typeof loaded === "object" ? loaded.content : loaded;
|
|
1036
|
+
const seededFiles = loaded !== null && typeof loaded === "object" ? loaded.seededFiles : undefined;
|
|
1037
|
+
if (seededFiles?.length && seedContextFiles) {
|
|
1038
|
+
try {
|
|
1039
|
+
await seedContextFiles(seededFiles);
|
|
1040
|
+
}
|
|
1041
|
+
catch (err) {
|
|
1042
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
if (projectMem != null && projectMem.trim()) {
|
|
1046
|
+
const projectBlock = `${PROJECT_CONTEXT_FRAMING}\n\n${composeMemoryBlock(projectMem, "project")}`;
|
|
1047
|
+
memoryBlock = memoryBlock ? `${memoryBlock}\n\n${projectBlock}` : projectBlock;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
const skillSpecs = normalizeSkills(spec.skills);
|
|
1051
|
+
const inheritedFrames = internals?.inheritedManifestScope ?? [];
|
|
1052
|
+
for (const frame of inheritedFrames) {
|
|
1053
|
+
skillScope.push(frame);
|
|
1054
|
+
}
|
|
1055
|
+
const hasSkillManifest = skillSpecs.some((s) => s.manifest !== undefined) || inheritedFrames.length > 0;
|
|
1056
|
+
if (skillSpecs.length > 0) {
|
|
1057
|
+
if (tools.some((t) => t.name === SKILL_TOOL_NAME)) {
|
|
1058
|
+
const e = new Error(`Tool name "${SKILL_TOOL_NAME}" is reserved when spec.skills is present.`);
|
|
1059
|
+
e.code = "config.reserved_tool_name";
|
|
1060
|
+
throw e;
|
|
1061
|
+
}
|
|
1062
|
+
tools.push(makeSkillTool(skillSpecs, skillScope));
|
|
1063
|
+
}
|
|
1064
|
+
const skillsBlock = buildSkillsBlock(skillSpecs);
|
|
1065
|
+
const provider = spec.promptProvider ?? deps.promptProvider ?? defaultPromptProvider;
|
|
1066
|
+
const promptPolicyEnabled = Boolean(spec.toolPolicy ?? deps.toolPolicy);
|
|
1067
|
+
const promptHooks = spec.hooks ?? deps.hooks;
|
|
1068
|
+
const promptHooksEnabled = Boolean(promptHooks?.preToolUse || promptHooks?.postToolUse);
|
|
1069
|
+
const failClosedReason = selfOrchestrationFailClosedReason(spec, deps);
|
|
1070
|
+
if (failClosedReason) {
|
|
1071
|
+
deps.onError?.(new Error(failClosedReason), { phase: "config", sessionId });
|
|
1072
|
+
}
|
|
1073
|
+
const featureFlags = {
|
|
1074
|
+
policyEnabled: promptPolicyEnabled,
|
|
1075
|
+
hooksEnabled: promptHooksEnabled,
|
|
1076
|
+
isolationEnabled: isIsolated(executionEnv),
|
|
1077
|
+
orchestrationEnabled: selfOrchestrationActive,
|
|
1078
|
+
goalEnabled: internals?.goalMode === true,
|
|
1079
|
+
awarenessEnabled: thinking !== undefined && ULTRA_REASONING_TIERS.has(thinking),
|
|
1080
|
+
worktreeIsolated: internals?.isolation === "worktree" && ownedEnv !== undefined,
|
|
1081
|
+
withinTaskCompactionEnabled: (spec.compaction?.enabled ?? true) && (spec.compaction?.withinTask ?? true),
|
|
1082
|
+
};
|
|
1083
|
+
const userSystemPrompt = spec.systemPrompt ?? resolvedRole.systemPrompt ?? internals?.defaultSystemPrompt;
|
|
1084
|
+
const userAppendSystemPrompt = spec.appendSystemPrompt;
|
|
1085
|
+
const mcpInstructionsBlock = mcp.serverInstructions.length
|
|
1086
|
+
? `# MCP Server Instructions\n${mcp.serverInstructions.map((s) => `## ${s.server}\n${s.text}`).join("\n\n")}`
|
|
1087
|
+
: undefined;
|
|
1088
|
+
const userTz = spec.clientContext?.timeZone;
|
|
1089
|
+
const tzValid = userTz !== undefined && isValidTimeZone(userTz);
|
|
1090
|
+
const envFacts = { date: formatLocalDate(new Date(), tzValid ? userTz : undefined), modelId: model.id };
|
|
1091
|
+
if (tzValid)
|
|
1092
|
+
envFacts.timeZone = userTz;
|
|
1093
|
+
if (spec.clientContext?.userEmail)
|
|
1094
|
+
envFacts.userEmail = spec.clientContext.userEmail;
|
|
1095
|
+
const declaredCutoff = deps.modelKnowledgeCutoffs?.[model.id];
|
|
1096
|
+
if (declaredCutoff)
|
|
1097
|
+
envFacts.knowledgeCutoff = declaredCutoff;
|
|
1098
|
+
if (spec.envFacts?.profile)
|
|
1099
|
+
envFacts.sandboxProfile = spec.envFacts.profile;
|
|
1100
|
+
if (spec.envFacts?.capabilities && spec.envFacts.capabilities.length > 0)
|
|
1101
|
+
envFacts.sandboxCapabilities = [...spec.envFacts.capabilities];
|
|
1102
|
+
if (spec.envFacts?.pkgSource)
|
|
1103
|
+
envFacts.sandboxPkgSource = spec.envFacts.pkgSource;
|
|
1104
|
+
if (spec.envFacts?.egress === "none" || spec.envFacts?.egress === "allowlist" || spec.envFacts?.egress === "full")
|
|
1105
|
+
envFacts.sandboxEgress = spec.envFacts.egress;
|
|
1106
|
+
if (spec.envFacts?.scratchpadDir)
|
|
1107
|
+
envFacts.scratchpadDir = spec.envFacts.scratchpadDir;
|
|
1108
|
+
if (handsEnabled) {
|
|
1109
|
+
envFacts.cwd = taskRootPath;
|
|
1110
|
+
if (additionalRootsCanonical.length > 0) {
|
|
1111
|
+
envFacts.additionalDirectories = [...additionalRootsCanonical];
|
|
1112
|
+
}
|
|
1113
|
+
try {
|
|
1114
|
+
const probe = await executionEnv.exec('uname -s; uname -r; (git rev-parse --is-inside-work-tree 2>/dev/null || echo false); (git symbolic-ref --short -q HEAD 2>/dev/null || echo "HEAD (detached)"); (git rev-parse --show-toplevel 2>/dev/null || echo); (test -n "$(git status --porcelain 2>/dev/null | head -1)" && echo dirty || echo clean); (s=$(ps -p $$ -o comm= 2>/dev/null); s=${s##*/}; echo "${s#-}"); (test "$(git rev-parse --git-dir 2>/dev/null)" != "$(git rev-parse --git-common-dir 2>/dev/null)" && echo linked || echo main)', { cwd: envFacts.cwd, timeout: 10 });
|
|
1115
|
+
if (probe.ok && probe.value.exitCode === 0) {
|
|
1116
|
+
const lines = probe.value.stdout.split("\n");
|
|
1117
|
+
if (lines.length >= 6) {
|
|
1118
|
+
const [osName, osVer, git, branch, worktreeRoot, dirty] = lines;
|
|
1119
|
+
if (osName?.trim())
|
|
1120
|
+
envFacts.platform = osName.trim();
|
|
1121
|
+
if (osVer?.trim())
|
|
1122
|
+
envFacts.osVersion = osVer.trim();
|
|
1123
|
+
envFacts.isGitRepo = (git ?? "").trim() === "true";
|
|
1124
|
+
if (envFacts.isGitRepo) {
|
|
1125
|
+
const b = (branch ?? "").trim();
|
|
1126
|
+
if (b)
|
|
1127
|
+
envFacts.gitBranch = b;
|
|
1128
|
+
const root = (worktreeRoot ?? "").trim();
|
|
1129
|
+
if (root)
|
|
1130
|
+
envFacts.gitWorktreeRoot = root;
|
|
1131
|
+
const d = (dirty ?? "").trim();
|
|
1132
|
+
if (d === "dirty" || d === "clean")
|
|
1133
|
+
envFacts.gitDirty = d === "dirty";
|
|
1134
|
+
}
|
|
1135
|
+
const sh = (lines[6] ?? "").trim();
|
|
1136
|
+
if (sh)
|
|
1137
|
+
envFacts.shell = sh;
|
|
1138
|
+
if (envFacts.isGitRepo && (lines[7] ?? "").trim() === "linked")
|
|
1139
|
+
envFacts.isLinkedWorktree = true;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
catch {
|
|
1144
|
+
}
|
|
1145
|
+
if (envFacts.isGitRepo === true) {
|
|
1146
|
+
const SEP = "@@SEMA_ENV_GIT_SPLIT@@";
|
|
1147
|
+
try {
|
|
1148
|
+
const snap = await executionEnv.exec(`(m=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null); m=\${m#origin/}; for s in "$m" main master; do if [ -n "$s" ] && git show-ref --verify --quiet "refs/remotes/origin/$s"; then echo "$s"; break; fi; done) || true; echo "${SEP}"; (git config user.name 2>/dev/null || true); echo "${SEP}"; gs=$(git --no-optional-locks status --short) || exit 41; printf '%s\\n' "$gs"; echo "${SEP}"; gl=$(git --no-optional-locks log --oneline -n 5) || exit 42; printf '%s\\n' "$gl"`, { cwd: envFacts.cwd, timeout: 10 });
|
|
1149
|
+
if (snap.ok && snap.value.exitCode === 0) {
|
|
1150
|
+
const parts = snap.value.stdout.split(`${SEP}\n`);
|
|
1151
|
+
if (parts.length === 4) {
|
|
1152
|
+
envFacts.gitSnapshot = buildGitSnapshot({
|
|
1153
|
+
branch: envFacts.gitBranch ?? "HEAD",
|
|
1154
|
+
mainBranch: parts[0].trim() || "main",
|
|
1155
|
+
...(parts[1].trim() ? { userName: parts[1].trim() } : {}),
|
|
1156
|
+
status: parts[2],
|
|
1157
|
+
log: parts[3],
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
else {
|
|
1162
|
+
const reason = snap.ok
|
|
1163
|
+
? snap.value.exitCode === 41
|
|
1164
|
+
? "git status failed (exit 41)"
|
|
1165
|
+
: snap.value.exitCode === 42
|
|
1166
|
+
? "git log failed (exit 42)"
|
|
1167
|
+
: `git exited ${snap.value.exitCode}`
|
|
1168
|
+
: `exec failed: ${snap.error.message}`;
|
|
1169
|
+
deps.onError?.(new Error(`env git snapshot skipped — ${reason}`), { phase: "degraded", sessionId, classification: "env-git-snapshot" });
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
catch (err) {
|
|
1173
|
+
deps.onError?.(new Error(`env git snapshot skipped — ${err instanceof Error ? err.message : String(err)}`), { phase: "degraded", sessionId, classification: "env-git-snapshot" });
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
let systemPrompt;
|
|
1178
|
+
let renderWithDate;
|
|
1179
|
+
const promptCtx = { userSystemPrompt, userAppendSystemPrompt, tools, memoryEnabled: false, consolidationEnabled: false, ...featureFlags };
|
|
1180
|
+
let promptConstitution = "core";
|
|
1181
|
+
let promptBlocks = [];
|
|
1182
|
+
const finishStable = (stableCore) => {
|
|
1183
|
+
const stable = composeSystemPrompt(composeSystemPrompt(stableCore, skillsBlock), mcpInstructionsBlock);
|
|
1184
|
+
if (skillsBlock?.trim())
|
|
1185
|
+
promptBlocks.push({ id: "skills.block", text: skillsBlock });
|
|
1186
|
+
if (mcpInstructionsBlock?.trim())
|
|
1187
|
+
promptBlocks.push({ id: "mcp.instructions", text: mcpInstructionsBlock });
|
|
1188
|
+
renderWithDate = (date) => composeSystemPrompt(composeSystemPrompt(stable, buildEnvironmentContext({ ...envFacts, date }) || undefined), memoryBlock);
|
|
1189
|
+
systemPrompt = renderWithDate(envFacts.date);
|
|
1190
|
+
const envBlock = buildEnvironmentContext({ ...envFacts, date: envFacts.date });
|
|
1191
|
+
if (envBlock?.trim())
|
|
1192
|
+
promptBlocks.push({ id: "env.context", text: envBlock });
|
|
1193
|
+
if (memoryBlock?.trim())
|
|
1194
|
+
promptBlocks.push({ id: "memory.tail", text: memoryBlock });
|
|
1195
|
+
};
|
|
1196
|
+
if (provider === defaultPromptProvider) {
|
|
1197
|
+
const c = composeConstitution(userSystemPrompt ?? DEFAULT_SYSTEM_PROMPT, promptCtx);
|
|
1198
|
+
promptBlocks = [...c.blocks];
|
|
1199
|
+
finishStable(c.text);
|
|
1200
|
+
}
|
|
1201
|
+
else if (provider.stableSystem) {
|
|
1202
|
+
const roleOut = provider.stableSystem(promptCtx);
|
|
1203
|
+
if (provider.replaceAll) {
|
|
1204
|
+
promptConstitution = "replaced";
|
|
1205
|
+
promptBlocks = [{ id: "provider.replace_all", text: roleOut }];
|
|
1206
|
+
finishStable(roleOut);
|
|
1207
|
+
}
|
|
1208
|
+
else if (roleOut.includes(CYBER_RISK) && roleOut.includes(URL_SAFETY) && roleOut.includes("# Harness")) {
|
|
1209
|
+
promptConstitution = "provider-assembled";
|
|
1210
|
+
promptBlocks = [{ id: "provider.assembled", text: roleOut }];
|
|
1211
|
+
deps.onError?.(new Error("prompt-constitution: this PromptProvider returns an already-assembled prompt (constitution anchor found). Core now appends the constitution structurally — return ONLY the role base from stableSystem (or set replaceAll:true to own the whole base). Passed through un-doubled."), { phase: "prompt-constitution", sessionId });
|
|
1212
|
+
finishStable(roleOut);
|
|
1213
|
+
}
|
|
1214
|
+
else {
|
|
1215
|
+
const c = composeConstitution(roleOut, promptCtx);
|
|
1216
|
+
promptBlocks = [...c.blocks];
|
|
1217
|
+
finishStable(c.text);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
else if (provider.system) {
|
|
1221
|
+
systemPrompt = provider.system({ ...promptCtx, memoryBlock });
|
|
1222
|
+
promptConstitution = "legacy";
|
|
1223
|
+
promptBlocks = [{ id: "provider.legacy", text: systemPrompt }];
|
|
1224
|
+
const memTrim = memoryBlock?.trim();
|
|
1225
|
+
if (memTrim && systemPrompt.includes(memTrim) && !systemPrompt.trimEnd().endsWith(memTrim)) {
|
|
1226
|
+
deps.onError?.(new Error("prompt-cache: the <user_memory> block is not at the END of the system prompt — the cacheable prefix changes every turn, so vLLM/Anthropic prefix caching will miss. Put memoryBlock LAST (STABLE→VARIABLE), or implement PromptProvider.stableSystem and let core place memory."), { phase: "prompt-cache", sessionId });
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
else {
|
|
1230
|
+
const c = composeConstitution(userSystemPrompt ?? DEFAULT_SYSTEM_PROMPT, promptCtx);
|
|
1231
|
+
promptBlocks = [...c.blocks];
|
|
1232
|
+
finishStable(c.text);
|
|
1233
|
+
}
|
|
1234
|
+
if (model.promptGuidance && model.promptGuidance.length > 0) {
|
|
1235
|
+
const guidance = model.promptGuidance.join("\n\n");
|
|
1236
|
+
const baseRender = renderWithDate;
|
|
1237
|
+
if (baseRender) {
|
|
1238
|
+
renderWithDate = (date) => composeSystemPrompt(baseRender(date), guidance);
|
|
1239
|
+
systemPrompt = renderWithDate(envFacts.date);
|
|
1240
|
+
}
|
|
1241
|
+
else {
|
|
1242
|
+
systemPrompt = composeSystemPrompt(systemPrompt, guidance) ?? systemPrompt;
|
|
1243
|
+
}
|
|
1244
|
+
promptBlocks.push({ id: "model.guidance", text: guidance });
|
|
1245
|
+
}
|
|
1246
|
+
const promptManifest = {
|
|
1247
|
+
constitution: promptConstitution,
|
|
1248
|
+
blocks: promptBlocks.map((b) => ({ id: b.id, chars: b.text.length, hash: createHash("sha256").update(PROMPT_HASH_SALT).update(b.text).digest("hex").slice(0, 12) })),
|
|
1249
|
+
};
|
|
1250
|
+
const userToolNames = (spec.tools ?? []).map((t) => t.name);
|
|
1251
|
+
const mcpToolNames = mcp.tools.map((t) => t.name);
|
|
1252
|
+
const deferred = classifyDeferred({
|
|
1253
|
+
specs: spec.tools ?? [],
|
|
1254
|
+
mcpToolNames,
|
|
1255
|
+
fullTools: tools.filter((t) => userToolNames.includes(t.name) || mcpToolNames.includes(t.name)),
|
|
1256
|
+
deferMode: deps.deferMode,
|
|
1257
|
+
model,
|
|
1258
|
+
});
|
|
1259
|
+
const activeTools = new Set();
|
|
1260
|
+
const fpRef = {};
|
|
1261
|
+
let harnessTools = tools;
|
|
1262
|
+
let toolsDeltaRef;
|
|
1263
|
+
if (deferred.size > 0) {
|
|
1264
|
+
if (deferred.has(TOOL_SEARCH_NAME) || tools.some((t) => t.name === TOOL_SEARCH_NAME)) {
|
|
1265
|
+
const e = new Error(`Tool name "${TOOL_SEARCH_NAME}" is reserved when deferred tools are present.`);
|
|
1266
|
+
e.code = "config.reserved_tool_name";
|
|
1267
|
+
throw e;
|
|
1268
|
+
}
|
|
1269
|
+
const registry = buildDeferredRegistry(deferred, tools);
|
|
1270
|
+
const placeholders = new Map([...registry.values()].map((i) => [i.name, makePlaceholderTool(i)]));
|
|
1271
|
+
const { messages } = await session.buildContext();
|
|
1272
|
+
for (const n of extractDiscoveredToolNames(messages, registry)) {
|
|
1273
|
+
if (deferred.has(n))
|
|
1274
|
+
activeTools.add(n);
|
|
1275
|
+
}
|
|
1276
|
+
if (resume) {
|
|
1277
|
+
for (const n of resume.seed.activeTools)
|
|
1278
|
+
if (deferred.has(n))
|
|
1279
|
+
activeTools.add(n);
|
|
1280
|
+
}
|
|
1281
|
+
let toolSearch;
|
|
1282
|
+
const buildToolList = (active) => {
|
|
1283
|
+
const list = tools.map((t) => (deferred.has(t.name) && !active.has(t.name) ? placeholders.get(t.name) : t));
|
|
1284
|
+
list.push(toolSearch);
|
|
1285
|
+
return list;
|
|
1286
|
+
};
|
|
1287
|
+
const announcedTools = new Set(activeTools);
|
|
1288
|
+
toolsDeltaRef = { pending: [] };
|
|
1289
|
+
const deltaRef = toolsDeltaRef;
|
|
1290
|
+
const rematerialize = async (active) => {
|
|
1291
|
+
const list = buildToolList(active);
|
|
1292
|
+
await harnessRef.current.setTools(list);
|
|
1293
|
+
if (fpRef.current)
|
|
1294
|
+
fpRef.current.tools = toolsToFingerprintInputs(list);
|
|
1295
|
+
for (const n of active) {
|
|
1296
|
+
if (!announcedTools.has(n)) {
|
|
1297
|
+
announcedTools.add(n);
|
|
1298
|
+
deltaRef.pending.push(n);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
};
|
|
1302
|
+
toolSearch = makeToolSearchTool({ registry, active: activeTools, rematerialize });
|
|
1303
|
+
harnessTools = buildToolList(activeTools);
|
|
1304
|
+
}
|
|
1305
|
+
const agentListingSpec = (spec.tools ?? []).find((t) => t.agentListing !== undefined && t.agentListing.length > 0);
|
|
1306
|
+
const agentListing = agentListingSpec
|
|
1307
|
+
? { entries: agentListingSpec.agentListing, toolName: agentListingSpec.name, seedAnnounced: resume !== undefined }
|
|
1308
|
+
: undefined;
|
|
1309
|
+
let promptDate = envFacts.date;
|
|
1310
|
+
let renderedPrompt = systemPrompt;
|
|
1311
|
+
const liveSystemPrompt = renderWithDate
|
|
1312
|
+
? () => {
|
|
1313
|
+
const today = formatLocalDate(new Date(), tzValid ? userTz : undefined);
|
|
1314
|
+
if (today !== promptDate) {
|
|
1315
|
+
promptDate = today;
|
|
1316
|
+
renderedPrompt = renderWithDate(today);
|
|
1317
|
+
if (fpRef.current)
|
|
1318
|
+
fpRef.current.systemPrompt = renderedPrompt;
|
|
1319
|
+
}
|
|
1320
|
+
return renderedPrompt;
|
|
1321
|
+
}
|
|
1322
|
+
: undefined;
|
|
1323
|
+
const harness = new AgentHarness({
|
|
1324
|
+
...(spec.limits?.maxOutputTokens !== undefined && spec.limits.maxOutputTokens > 0
|
|
1325
|
+
? { maxOutputTokens: spec.limits.maxOutputTokens }
|
|
1326
|
+
: {}),
|
|
1327
|
+
...(callCapRef !== undefined && callCapOn
|
|
1328
|
+
? {
|
|
1329
|
+
maxOutputTokensPerCall: () => {
|
|
1330
|
+
if (callCapRef.reasoningObserved === true)
|
|
1331
|
+
return undefined;
|
|
1332
|
+
const cap = computeCallCap(callCapRef, Date.now(), (thinking ?? "off") !== "off");
|
|
1333
|
+
if (cap !== undefined)
|
|
1334
|
+
callCapRef.shrinks = (callCapRef.shrinks ?? 0) + 1;
|
|
1335
|
+
return cap;
|
|
1336
|
+
},
|
|
1337
|
+
}
|
|
1338
|
+
: {}),
|
|
1339
|
+
...(callCapRef !== undefined
|
|
1340
|
+
? { callDeadlineMsPerCall: () => softExecDeadlineMs(callCapRef) }
|
|
1341
|
+
: {}),
|
|
1342
|
+
...(spec.resilience !== undefined ? { resilience: spec.resilience } : {}),
|
|
1343
|
+
loopTrace: (step) => {
|
|
1344
|
+
if (step.kind !== "continue")
|
|
1345
|
+
return;
|
|
1346
|
+
if (step.reason === "next_turn" || step.reason === "steer_injected" || step.reason === "follow_up_injected")
|
|
1347
|
+
return;
|
|
1348
|
+
emitTrace(deps.tracer, () => ({
|
|
1349
|
+
kind: "loop.recovery",
|
|
1350
|
+
version: 1,
|
|
1351
|
+
taskId: spec.taskId ?? sessionId,
|
|
1352
|
+
reason: step.reason,
|
|
1353
|
+
ts: Date.now(),
|
|
1354
|
+
}));
|
|
1355
|
+
},
|
|
1356
|
+
...(spec.streamingToolExecution === true ? { streamingToolExecution: true } : {}),
|
|
1357
|
+
followUpMode: "all",
|
|
1358
|
+
env: executionEnv,
|
|
1359
|
+
session,
|
|
1360
|
+
tools: harnessTools,
|
|
1361
|
+
model,
|
|
1362
|
+
thinkingLevel: thinking ?? "off",
|
|
1363
|
+
systemPrompt: liveSystemPrompt ?? systemPrompt,
|
|
1364
|
+
getApiKeyAndHeaders: spec.getApiKeyAndHeaders,
|
|
1365
|
+
runtime: brainToRuntime(deps.brain),
|
|
1366
|
+
});
|
|
1367
|
+
harnessRef.current = harness;
|
|
1368
|
+
let releaseSignal = () => undefined;
|
|
1369
|
+
if (spec.signal) {
|
|
1370
|
+
if (spec.signal.aborted) {
|
|
1371
|
+
abortController.abort();
|
|
1372
|
+
}
|
|
1373
|
+
else {
|
|
1374
|
+
const sig = spec.signal;
|
|
1375
|
+
const onExternalAbort = () => {
|
|
1376
|
+
abortController.abort();
|
|
1377
|
+
void harness.abort();
|
|
1378
|
+
};
|
|
1379
|
+
sig.addEventListener("abort", onExternalAbort, { once: true });
|
|
1380
|
+
releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
const policy = spec.toolPolicy ?? deps.toolPolicy;
|
|
1384
|
+
let sessionRulePolicy;
|
|
1385
|
+
if (deps.sessionPolicyStore && spec.sessionId) {
|
|
1386
|
+
const rules = await deps.sessionPolicyStore.getRules(spec.sessionId, spec.principal);
|
|
1387
|
+
if (rules) {
|
|
1388
|
+
sessionRulePolicy = createSessionRulePolicy(rules, { env: executionEnv, rootPath: taskRootPath, toolEffects });
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
const skillScopePolicy = hasSkillManifest
|
|
1392
|
+
? createActiveSkillScopePolicy({
|
|
1393
|
+
scope: skillScope,
|
|
1394
|
+
env: executionEnv,
|
|
1395
|
+
rootPath: taskRootPath,
|
|
1396
|
+
toolEffects,
|
|
1397
|
+
})
|
|
1398
|
+
: undefined;
|
|
1399
|
+
const narrowingLayers = [sessionRulePolicy, skillScopePolicy].filter((p) => p !== undefined);
|
|
1400
|
+
const denyNarrowingPolicy = narrowingLayers.length === 0 ? undefined : narrowingLayers.length === 1 ? narrowingLayers[0] : combinePolicies(...narrowingLayers);
|
|
1401
|
+
const policyLayers = policy !== undefined ? [...narrowingLayers, policy, ...narrowingLayers] : narrowingLayers;
|
|
1402
|
+
const integrityGuardLayers = [createTranscriptIntegrityPolicy(), createUnverifiableDeletePolicy()];
|
|
1403
|
+
const guardedPolicyLayers = policy !== undefined ? [...integrityGuardLayers, ...policyLayers, ...integrityGuardLayers] : [...integrityGuardLayers, ...policyLayers];
|
|
1404
|
+
const effectivePolicy = guardedPolicyLayers.length === 1 ? guardedPolicyLayers[0] : combinePolicies(...guardedPolicyLayers);
|
|
1405
|
+
const hooks = spec.hooks ?? deps.hooks;
|
|
1406
|
+
const onAsk = spec.onAsk ?? deps.onAsk;
|
|
1407
|
+
const handWriteTools = handsEnabled
|
|
1408
|
+
? Object.keys(HAND_TOOL_EFFECTS).filter((name) => {
|
|
1409
|
+
const eff = HAND_TOOL_EFFECTS[name];
|
|
1410
|
+
return eff === "write" || eff === "idempotent";
|
|
1411
|
+
})
|
|
1412
|
+
: [];
|
|
1413
|
+
const hasEffectAwareGate = Boolean(policyLayers.length > 0 || hooks?.preToolUse);
|
|
1414
|
+
const destructiveMcpUngated = mcp.tools.some((t) => !irreversibleTools.has(t.name) && !egressTools.has(t.name) && (toolEffects.get(t.name) ?? "write") !== "read");
|
|
1415
|
+
const firstPartyWriteUngated = (spec.tools ?? [])
|
|
1416
|
+
.map((t) => t.name)
|
|
1417
|
+
.filter((name) => !irreversibleTools.has(name) && !egressTools.has(name) && toolEffects.get(name) === "write");
|
|
1418
|
+
if (!hasEffectAwareGate && (handWriteTools.length > 0 || destructiveMcpUngated || firstPartyWriteUngated.length > 0)) {
|
|
1419
|
+
const what = [
|
|
1420
|
+
handWriteTools.length > 0 ? `hand tools [${handWriteTools.join(", ")}]` : undefined,
|
|
1421
|
+
destructiveMcpUngated ? "MCP write tools" : undefined,
|
|
1422
|
+
firstPartyWriteUngated.length > 0 ? `write tools [${firstPartyWriteUngated.join(", ")}]` : undefined,
|
|
1423
|
+
]
|
|
1424
|
+
.filter(Boolean)
|
|
1425
|
+
.join(" + ");
|
|
1426
|
+
if (!ungatedWarnedShapes.get(deps)?.has(what)) {
|
|
1427
|
+
let shapes = ungatedWarnedShapes.get(deps);
|
|
1428
|
+
if (!shapes) {
|
|
1429
|
+
shapes = new Set();
|
|
1430
|
+
ungatedWarnedShapes.set(deps, shapes);
|
|
1431
|
+
}
|
|
1432
|
+
shapes.add(what);
|
|
1433
|
+
deps.onError?.(new Error(`write-capable ${what} are present but UNGATED — wire an effect-aware tool policy (or a PreToolUse hook). ` +
|
|
1434
|
+
`bash/MCP irreversible actions are otherwise unadjudicated; the deployment sandbox/egress boundary is the only protection (design/77 §4, design/53 §2.H). ` +
|
|
1435
|
+
`(This warning fires once per deployment per tool-set shape.)`), { phase: "config", sessionId });
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
const preToolContexts = new Map();
|
|
1439
|
+
const blockedToolCalls = new Set();
|
|
1440
|
+
const blockedTracked = Boolean(hooks?.postToolUse || hooks?.preToolUse || hooks?.postToolUseFailure || hooks?.postToolBatch);
|
|
1441
|
+
const resourceSuspendEligible = spec.resourceSuspend !== undefined &&
|
|
1442
|
+
(spec.checkpointStore ?? deps.checkpointStore) !== undefined &&
|
|
1443
|
+
!(offloadStore !== undefined && isVolatileOffloadStore(offloadStore)) &&
|
|
1444
|
+
(ownedEnv === undefined || isRemoteExecutionEnv(ownedEnv));
|
|
1445
|
+
if (spec.resourceSuspend !== undefined && !resourceSuspendEligible) {
|
|
1446
|
+
const why = (spec.checkpointStore ?? deps.checkpointStore) === undefined
|
|
1447
|
+
? "no CheckpointStore is wired"
|
|
1448
|
+
: offloadStore !== undefined && isVolatileOffloadStore(offloadStore)
|
|
1449
|
+
? "tool-result offload uses the in-memory store (a resume needs durable results)"
|
|
1450
|
+
: "the per-task execution env is not a RemoteExecutionEnv (it would be destroyed on suspend)";
|
|
1451
|
+
deps.onError?.(new Error(`resourceSuspend is set but INACTIVE: ${why}; resource limits will hard-fail, not suspend`), {
|
|
1452
|
+
phase: "config",
|
|
1453
|
+
sessionId,
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
if (effectivePolicy || hooks?.preToolUse || egressTools.size > 0 || irreversibleTools.size > 0 || resourceSuspendEligible || spec.enablePlanMode === true) {
|
|
1457
|
+
const adjudicate = effectivePolicy
|
|
1458
|
+
? (req) => raceAbort(Promise.resolve(effectivePolicy.check({ ...req, budget: budgetSnapshot }, abortController.signal)), abortController.signal, () => ({
|
|
1459
|
+
action: "deny",
|
|
1460
|
+
reason: "policy check aborted (task timed out or cancelled)",
|
|
1461
|
+
}))
|
|
1462
|
+
: undefined;
|
|
1463
|
+
const resolveAskBound = async (decision, req) => {
|
|
1464
|
+
const t0 = now();
|
|
1465
|
+
const resolved = await resolveAsk({
|
|
1466
|
+
toolName: req.toolName,
|
|
1467
|
+
toolCallId: req.toolCallId,
|
|
1468
|
+
args: req.args,
|
|
1469
|
+
message: decision.message ?? decision.reason ?? `approval required for "${req.toolName}"`,
|
|
1470
|
+
principal: spec.principal,
|
|
1471
|
+
sourceTaskId: sessionId,
|
|
1472
|
+
}, onAsk, abortController.signal);
|
|
1473
|
+
const waitMs = Math.max(0, now() - t0);
|
|
1474
|
+
humanReviewRef.count += 1;
|
|
1475
|
+
humanReviewRef.totalWaitMs += waitMs;
|
|
1476
|
+
const toolArg = primaryActivityArg(req.args);
|
|
1477
|
+
humanReviewRef.gates.push({
|
|
1478
|
+
kind: "human",
|
|
1479
|
+
waitMs,
|
|
1480
|
+
decision: resolved.action === "allow" ? "allow" : "deny",
|
|
1481
|
+
toolName: req.toolName,
|
|
1482
|
+
...(toolArg !== undefined ? { toolArg } : {}),
|
|
1483
|
+
});
|
|
1484
|
+
return resolved;
|
|
1485
|
+
};
|
|
1486
|
+
const hooksWithPermissionDenied = hooks?.permissionDenied ? hooks : undefined;
|
|
1487
|
+
const notifyPermissionDenied = hooksWithPermissionDenied
|
|
1488
|
+
? async (payload) => {
|
|
1489
|
+
try {
|
|
1490
|
+
await hooksWithPermissionDenied.permissionDenied(payload);
|
|
1491
|
+
}
|
|
1492
|
+
catch (err) {
|
|
1493
|
+
try {
|
|
1494
|
+
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "hook", sessionId });
|
|
1495
|
+
}
|
|
1496
|
+
catch {
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
: undefined;
|
|
1501
|
+
const checkpointStore = spec.checkpointStore ?? deps.checkpointStore;
|
|
1502
|
+
const durableApproval = spec.durableApproval ??
|
|
1503
|
+
(runtimeCaps?.forceDurableGate ? { scope: spec.principal || DEFAULT_IRREVERSIBLE_SCOPE } : undefined);
|
|
1504
|
+
const serializeCheckpointState = (workspaceHandle) => ({
|
|
1505
|
+
activeTools: [...activeTools],
|
|
1506
|
+
outputRef: { value: outputRef.value, set: outputRef.set },
|
|
1507
|
+
nestedStats: { ...nestedStats },
|
|
1508
|
+
consolidationNotes: undefined,
|
|
1509
|
+
readFileState: readFileStateForCheckpoint ? [...readFileStateForCheckpoint.entries()] : undefined,
|
|
1510
|
+
repairBundle: internals?.repairBundle !== undefined
|
|
1511
|
+
? structuredClone(internals.repairBundle)
|
|
1512
|
+
: resume?.seed.repairBundle !== undefined
|
|
1513
|
+
? structuredClone(resume.seed.repairBundle)
|
|
1514
|
+
: undefined,
|
|
1515
|
+
workspaceHandle,
|
|
1516
|
+
handsCwd: handsCwdRef?.current,
|
|
1517
|
+
activeWorktree: worktreeSessionRef?.current ? { ...worktreeSessionRef.current } : undefined,
|
|
1518
|
+
runningBackgroundTasks: (() => {
|
|
1519
|
+
const live = defaultTaskRegistry
|
|
1520
|
+
.list({ owner: hostTaskId, scope: taskScope, sessionId })
|
|
1521
|
+
.filter((t) => t.status === "pending" || t.status === "running")
|
|
1522
|
+
.map((t) => ({ id: t.task_id, ...(t.description !== undefined ? { description: t.description } : {}) }));
|
|
1523
|
+
return live.length > 0 ? live : undefined;
|
|
1524
|
+
})(),
|
|
1525
|
+
pendingSteer: undefined,
|
|
1526
|
+
});
|
|
1527
|
+
const commitSuspendSaga = async (token, cp, remoteEnv, remoteHandle) => {
|
|
1528
|
+
if (!checkpointStore)
|
|
1529
|
+
return false;
|
|
1530
|
+
if (memoryEngineSession)
|
|
1531
|
+
await memoryEngineSession.harvest("checkpoint");
|
|
1532
|
+
try {
|
|
1533
|
+
await checkpointStore.put(token, cp);
|
|
1534
|
+
return true;
|
|
1535
|
+
}
|
|
1536
|
+
catch (putErr) {
|
|
1537
|
+
deps.onError?.(putErr, { phase: "config", sessionId });
|
|
1538
|
+
if (remoteEnv !== undefined && remoteHandle?.snapshotId !== undefined) {
|
|
1539
|
+
const back = await remoteEnv.resumeVM(remoteHandle.snapshotId, { abortSignal: abortController.signal });
|
|
1540
|
+
if (back.ok) {
|
|
1541
|
+
const init = await remoteEnv.postResumeInit();
|
|
1542
|
+
if (init.ok)
|
|
1543
|
+
return false;
|
|
1544
|
+
deps.onError?.(init.error, { phase: "config", sessionId });
|
|
1545
|
+
}
|
|
1546
|
+
else {
|
|
1547
|
+
deps.onError?.(back.error, { phase: "config", sessionId });
|
|
1548
|
+
}
|
|
1549
|
+
abortController.abort();
|
|
1550
|
+
void harness.abort();
|
|
1551
|
+
return false;
|
|
1552
|
+
}
|
|
1553
|
+
return false;
|
|
1554
|
+
}
|
|
1555
|
+
};
|
|
1556
|
+
const publishCommittedSuspend = (token, gate, scope) => {
|
|
1557
|
+
const ref = gate.kind === "needs_review" || gate.kind === "plan_review" ? reviewRef : suspendRef;
|
|
1558
|
+
ref.token = token;
|
|
1559
|
+
ref.gate = gate;
|
|
1560
|
+
ref.scope = scope;
|
|
1561
|
+
};
|
|
1562
|
+
const suspendLoopCapHit = (count, cap, detail) => {
|
|
1563
|
+
if (count + 1 <= cap)
|
|
1564
|
+
return false;
|
|
1565
|
+
suspendLoopRef.hit = true;
|
|
1566
|
+
abortController.abort();
|
|
1567
|
+
void harness.abort();
|
|
1568
|
+
try {
|
|
1569
|
+
deps.onError?.(new Error(`suspend loop: task already suspended ${count} time(s) (max ${cap}); refusing to suspend again${detail}`), { phase: "config", sessionId });
|
|
1570
|
+
}
|
|
1571
|
+
catch {
|
|
1572
|
+
}
|
|
1573
|
+
return true;
|
|
1574
|
+
};
|
|
1575
|
+
const suspendableEnv = ownedEnv !== undefined && isSuspendable(ownedEnv) ? ownedEnv : undefined;
|
|
1576
|
+
const parkOnlyRemoteEnv = suspendableEnv === undefined && ownedEnv !== undefined && isRemoteExecutionEnv(ownedEnv) ? ownedEnv : undefined;
|
|
1577
|
+
const parkOnlyHandle = (env) => {
|
|
1578
|
+
const { snapshotId: _lineage, ...identity } = env.workspaceHandle();
|
|
1579
|
+
return { ...identity, restoreMode: "park_only" };
|
|
1580
|
+
};
|
|
1581
|
+
suspendForResource = resourceSuspendEligible
|
|
1582
|
+
? async (reason, sliceSpend) => {
|
|
1583
|
+
const rs = spec.resourceSuspend;
|
|
1584
|
+
if (!checkpointStore || !rs)
|
|
1585
|
+
return false;
|
|
1586
|
+
if (abortController.signal.aborted)
|
|
1587
|
+
return false;
|
|
1588
|
+
if (suspendLoopCapHit(priorLedger?.sliceCount ?? 0, maxSlices, " (resource slice limit)"))
|
|
1589
|
+
return false;
|
|
1590
|
+
const leafId = await session.getLeafId();
|
|
1591
|
+
if (!leafId)
|
|
1592
|
+
return false;
|
|
1593
|
+
if (abortController.signal.aborted)
|
|
1594
|
+
return false;
|
|
1595
|
+
let remoteHandle;
|
|
1596
|
+
if (suspendableEnv !== undefined) {
|
|
1597
|
+
if (hasBackgroundShell(suspendableEnv))
|
|
1598
|
+
await suspendableEnv.disposeBackgroundShells();
|
|
1599
|
+
const snap = await suspendableEnv.suspendVM({ abortSignal: abortController.signal });
|
|
1600
|
+
if (!snap.ok) {
|
|
1601
|
+
deps.onError?.(new Error(`resource suspendVM failed (${snap.error.code}): ${snap.error.message}`, { cause: snap.error }), { phase: "config", sessionId });
|
|
1602
|
+
return false;
|
|
1603
|
+
}
|
|
1604
|
+
remoteHandle = { ...suspendableEnv.workspaceHandle(), snapshotId: snap.value };
|
|
1605
|
+
}
|
|
1606
|
+
else if (parkOnlyRemoteEnv !== undefined) {
|
|
1607
|
+
if (hasBackgroundShell(parkOnlyRemoteEnv))
|
|
1608
|
+
await parkOnlyRemoteEnv.disposeBackgroundShells();
|
|
1609
|
+
remoteHandle = parkOnlyHandle(parkOnlyRemoteEnv);
|
|
1610
|
+
}
|
|
1611
|
+
const token = mintCheckpointToken();
|
|
1612
|
+
const gate = { kind: "resource_limit", reason };
|
|
1613
|
+
const cp = {
|
|
1614
|
+
token,
|
|
1615
|
+
version: RESOURCE_CHECKPOINT_VERSION,
|
|
1616
|
+
scope: rs.scope,
|
|
1617
|
+
sessionId,
|
|
1618
|
+
leafId,
|
|
1619
|
+
gate,
|
|
1620
|
+
pendingAction: { kind: "resource_limit", reason },
|
|
1621
|
+
state: serializeCheckpointState(remoteHandle),
|
|
1622
|
+
status: "pending",
|
|
1623
|
+
createdAt: Date.now(),
|
|
1624
|
+
deadline: Date.now() + (rs.ttlMs ?? DEFAULT_RESOURCE_TTL_MS),
|
|
1625
|
+
suspendCount: priorSuspendCount,
|
|
1626
|
+
humanReview: humanReviewRef.count > 0
|
|
1627
|
+
? { count: humanReviewRef.count, totalWaitMs: humanReviewRef.totalWaitMs, gates: [...humanReviewRef.gates] }
|
|
1628
|
+
: undefined,
|
|
1629
|
+
resourceLedger: debitLedger(priorLedger, sliceSpend, resourceTotal),
|
|
1630
|
+
};
|
|
1631
|
+
if (!(await commitSuspendSaga(token, cp, suspendableEnv, remoteHandle)))
|
|
1632
|
+
return false;
|
|
1633
|
+
publishCommittedSuspend(token, gate, rs.scope);
|
|
1634
|
+
try {
|
|
1635
|
+
await sessions.pin?.(sessionId);
|
|
1636
|
+
}
|
|
1637
|
+
catch (pinErr) {
|
|
1638
|
+
deps.onError?.(pinErr, { phase: "config", sessionId });
|
|
1639
|
+
}
|
|
1640
|
+
harness.requestStopAfterTurn();
|
|
1641
|
+
return true;
|
|
1642
|
+
}
|
|
1643
|
+
: undefined;
|
|
1644
|
+
suspendForReview = checkpointStore
|
|
1645
|
+
? async (reason) => {
|
|
1646
|
+
if (!checkpointStore)
|
|
1647
|
+
return false;
|
|
1648
|
+
if (abortController.signal.aborted)
|
|
1649
|
+
return false;
|
|
1650
|
+
if (suspendLoopCapHit(priorSuspendCount, maxSuspends, " for a plan_review (likely a resume/restart loop)."))
|
|
1651
|
+
return false;
|
|
1652
|
+
const leafId = await session.getLeafId();
|
|
1653
|
+
if (!leafId) {
|
|
1654
|
+
try {
|
|
1655
|
+
deps.onError?.(new Error("plan_review park skipped: no committed session leaf (the plan-review request was dropped; the run continues without pausing)"), { phase: "config", sessionId });
|
|
1656
|
+
}
|
|
1657
|
+
catch {
|
|
1658
|
+
}
|
|
1659
|
+
return false;
|
|
1660
|
+
}
|
|
1661
|
+
if (abortController.signal.aborted)
|
|
1662
|
+
return false;
|
|
1663
|
+
let remoteHandle;
|
|
1664
|
+
if (suspendableEnv !== undefined) {
|
|
1665
|
+
if (hasBackgroundShell(suspendableEnv))
|
|
1666
|
+
await suspendableEnv.disposeBackgroundShells();
|
|
1667
|
+
const snap = await suspendableEnv.suspendVM({ abortSignal: abortController.signal });
|
|
1668
|
+
if (!snap.ok) {
|
|
1669
|
+
deps.onError?.(new Error(`plan_review suspendVM failed (${snap.error.code}): ${snap.error.message}`, { cause: snap.error }), { phase: "config", sessionId });
|
|
1670
|
+
return false;
|
|
1671
|
+
}
|
|
1672
|
+
remoteHandle = { ...suspendableEnv.workspaceHandle(), snapshotId: snap.value };
|
|
1673
|
+
}
|
|
1674
|
+
else if (parkOnlyRemoteEnv !== undefined) {
|
|
1675
|
+
if (hasBackgroundShell(parkOnlyRemoteEnv))
|
|
1676
|
+
await parkOnlyRemoteEnv.disposeBackgroundShells();
|
|
1677
|
+
remoteHandle = parkOnlyHandle(parkOnlyRemoteEnv);
|
|
1678
|
+
}
|
|
1679
|
+
const token = mintCheckpointToken();
|
|
1680
|
+
const scope = spec.durableApproval?.scope ?? (spec.principal || DEFAULT_IRREVERSIBLE_SCOPE);
|
|
1681
|
+
const gate = { kind: "plan_review", reason: reason ?? `plan review requested` };
|
|
1682
|
+
const cp = {
|
|
1683
|
+
token,
|
|
1684
|
+
version: BINDING_CHECKPOINT_VERSION,
|
|
1685
|
+
scope,
|
|
1686
|
+
sessionId,
|
|
1687
|
+
leafId,
|
|
1688
|
+
gate,
|
|
1689
|
+
pendingAction: { kind: "plan_review" },
|
|
1690
|
+
state: serializeCheckpointState(remoteHandle),
|
|
1691
|
+
status: "pending",
|
|
1692
|
+
createdAt: Date.now(),
|
|
1693
|
+
suspendedAt: now(),
|
|
1694
|
+
deadline: Date.now() + (spec.durableApproval?.ttlMs ?? DEFAULT_RESOURCE_TTL_MS),
|
|
1695
|
+
suspendCount: priorSuspendCount + 1,
|
|
1696
|
+
humanReview: humanReviewRef.count > 0
|
|
1697
|
+
? { count: humanReviewRef.count, totalWaitMs: humanReviewRef.totalWaitMs, gates: [...humanReviewRef.gates] }
|
|
1698
|
+
: undefined,
|
|
1699
|
+
resourceLedger: priorLedger,
|
|
1700
|
+
sourceTaskId: sessionId,
|
|
1701
|
+
...(spec.principal ? { principal: spec.principal } : {}),
|
|
1702
|
+
};
|
|
1703
|
+
if (!(await commitSuspendSaga(token, cp, suspendableEnv, remoteHandle)))
|
|
1704
|
+
return false;
|
|
1705
|
+
publishCommittedSuspend(token, gate, scope);
|
|
1706
|
+
try {
|
|
1707
|
+
await sessions.pin?.(sessionId);
|
|
1708
|
+
}
|
|
1709
|
+
catch (pinErr) {
|
|
1710
|
+
deps.onError?.(pinErr, { phase: "config", sessionId });
|
|
1711
|
+
}
|
|
1712
|
+
abortController.abort();
|
|
1713
|
+
void harness.abort();
|
|
1714
|
+
return true;
|
|
1715
|
+
}
|
|
1716
|
+
: undefined;
|
|
1717
|
+
const suspendAsk = checkpointStore && (durableApproval || irreversibleTools.size > 0 || egressTools.size > 0)
|
|
1718
|
+
? async (req, postHookArgs, safety) => {
|
|
1719
|
+
let token;
|
|
1720
|
+
let gate;
|
|
1721
|
+
let cp;
|
|
1722
|
+
let remoteHandle;
|
|
1723
|
+
const remoteEnv = suspendableEnv;
|
|
1724
|
+
try {
|
|
1725
|
+
if (offloadStore && isVolatileOffloadStore(offloadStore) && !offloadStore.isEmpty()) {
|
|
1726
|
+
throw new Error("durable suspend requires a durable toolResultStore (the default InMemoryToolResultStore " +
|
|
1727
|
+
"holds offloaded results that are lost across a cross-replica resume); inject " +
|
|
1728
|
+
"RunnerDeps.toolResultStore or disable offload.");
|
|
1729
|
+
}
|
|
1730
|
+
if (ownedEnv !== undefined && remoteEnv === undefined && parkOnlyRemoteEnv === undefined) {
|
|
1731
|
+
throw new Error("durable suspend is not supported with a non-remote per-task executionEnvFactory env: the " +
|
|
1732
|
+
"minted env is destroyed on suspend, so a resumed file/shell tool would act on a fresh " +
|
|
1733
|
+
"(empty) env. Use a RemoteExecutionEnv factory (it is paused, not destroyed) or a static, " +
|
|
1734
|
+
"caller-owned RunnerDeps.executionEnv.");
|
|
1735
|
+
}
|
|
1736
|
+
const leafId = await session.getLeafId();
|
|
1737
|
+
if (!leafId) {
|
|
1738
|
+
throw new Error("cannot suspend: session has no committed leaf to resume from");
|
|
1739
|
+
}
|
|
1740
|
+
const { messages } = await session.buildContext();
|
|
1741
|
+
const { batchToolCallIds, completedCallIds } = batchContextAt(messages, req.toolCallId);
|
|
1742
|
+
if (abortController.signal.aborted) {
|
|
1743
|
+
return undefined;
|
|
1744
|
+
}
|
|
1745
|
+
if (suspendLoopCapHit(priorSuspendCount, maxSuspends, ` for tool "${req.toolName}" — likely a resume/restart loop.`))
|
|
1746
|
+
return undefined;
|
|
1747
|
+
if (remoteEnv !== undefined) {
|
|
1748
|
+
if (hasBackgroundShell(remoteEnv))
|
|
1749
|
+
await remoteEnv.disposeBackgroundShells();
|
|
1750
|
+
const snap = await remoteEnv.suspendVM({ abortSignal: abortController.signal });
|
|
1751
|
+
if (!snap.ok) {
|
|
1752
|
+
throw new Error(`suspendVM failed (${snap.error.code}): ${snap.error.message}`, { cause: snap.error });
|
|
1753
|
+
}
|
|
1754
|
+
remoteHandle = { ...remoteEnv.workspaceHandle(), snapshotId: snap.value };
|
|
1755
|
+
}
|
|
1756
|
+
else if (parkOnlyRemoteEnv !== undefined) {
|
|
1757
|
+
if (hasBackgroundShell(parkOnlyRemoteEnv))
|
|
1758
|
+
await parkOnlyRemoteEnv.disposeBackgroundShells();
|
|
1759
|
+
remoteHandle = parkOnlyHandle(parkOnlyRemoteEnv);
|
|
1760
|
+
}
|
|
1761
|
+
token = mintCheckpointToken();
|
|
1762
|
+
const riskDescriptor = buildRiskDescriptor({
|
|
1763
|
+
toolName: req.toolName,
|
|
1764
|
+
args: postHookArgs,
|
|
1765
|
+
safety,
|
|
1766
|
+
shellGated: (req.toolName === "Bash" && shellGatedBash) || (req.toolName === "Monitor" && shellGatedMonitor),
|
|
1767
|
+
});
|
|
1768
|
+
gate =
|
|
1769
|
+
safety !== undefined
|
|
1770
|
+
? {
|
|
1771
|
+
kind: "irreversible_ask",
|
|
1772
|
+
reason: `human approval required before safety-tightened tool "${req.toolName}"`,
|
|
1773
|
+
toolName: req.toolName,
|
|
1774
|
+
safetyAxis: safety,
|
|
1775
|
+
riskDescriptor,
|
|
1776
|
+
}
|
|
1777
|
+
: durableApproval
|
|
1778
|
+
? {
|
|
1779
|
+
kind: "human",
|
|
1780
|
+
reason: `human approval required for tool "${req.toolName}"`,
|
|
1781
|
+
toolName: req.toolName,
|
|
1782
|
+
riskDescriptor,
|
|
1783
|
+
}
|
|
1784
|
+
: {
|
|
1785
|
+
kind: "irreversible_ask",
|
|
1786
|
+
reason: `human approval required before irreversible tool "${req.toolName}"`,
|
|
1787
|
+
toolName: req.toolName,
|
|
1788
|
+
riskDescriptor,
|
|
1789
|
+
};
|
|
1790
|
+
const scope = durableApproval?.scope ?? (spec.principal || DEFAULT_IRREVERSIBLE_SCOPE);
|
|
1791
|
+
const ttlMs = durableApproval?.ttlMs;
|
|
1792
|
+
const checkpointState = serializeCheckpointState(remoteHandle);
|
|
1793
|
+
cp = {
|
|
1794
|
+
token,
|
|
1795
|
+
version: BINDING_CHECKPOINT_VERSION,
|
|
1796
|
+
scope,
|
|
1797
|
+
sessionId,
|
|
1798
|
+
leafId,
|
|
1799
|
+
gate,
|
|
1800
|
+
pendingAction: {
|
|
1801
|
+
kind: "tool_approval",
|
|
1802
|
+
toolCallId: req.toolCallId,
|
|
1803
|
+
toolName: req.toolName,
|
|
1804
|
+
args: postHookArgs,
|
|
1805
|
+
boundInputHash: boundInputHashOf(postHookArgs),
|
|
1806
|
+
batchToolCallIds,
|
|
1807
|
+
completedCallIds,
|
|
1808
|
+
},
|
|
1809
|
+
state: checkpointState,
|
|
1810
|
+
deadline: ttlMs !== undefined
|
|
1811
|
+
? Date.now() + ttlMs
|
|
1812
|
+
: durableApproval !== undefined
|
|
1813
|
+
? undefined
|
|
1814
|
+
: Date.now() + DEFAULT_UNATTENDED_APPROVAL_TTL_MS,
|
|
1815
|
+
status: "pending",
|
|
1816
|
+
createdAt: Date.now(),
|
|
1817
|
+
suspendedAt: now(),
|
|
1818
|
+
humanReview: humanReviewRef.count > 0
|
|
1819
|
+
? { count: humanReviewRef.count, totalWaitMs: humanReviewRef.totalWaitMs, gates: [...humanReviewRef.gates] }
|
|
1820
|
+
: undefined,
|
|
1821
|
+
suspendCount: priorSuspendCount + 1,
|
|
1822
|
+
resourceLedger: debitLedger(priorLedger, liveSpendRef.get?.() ?? { costMicroUsd: 0, tokens: 0, turns: 0 }, resourceTotal, { countSlice: false }),
|
|
1823
|
+
sourceTaskId: sessionId,
|
|
1824
|
+
...(spec.principal ? { principal: spec.principal } : {}),
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
catch (err) {
|
|
1828
|
+
deps.onError?.(err, { phase: "config", sessionId });
|
|
1829
|
+
return undefined;
|
|
1830
|
+
}
|
|
1831
|
+
if (!(await commitSuspendSaga(token, cp, remoteEnv, remoteHandle))) {
|
|
1832
|
+
return undefined;
|
|
1833
|
+
}
|
|
1834
|
+
publishCommittedSuspend(token, gate, cp.scope);
|
|
1835
|
+
try {
|
|
1836
|
+
await sessions.pin?.(sessionId);
|
|
1837
|
+
}
|
|
1838
|
+
catch (pinErr) {
|
|
1839
|
+
deps.onError?.(pinErr, { phase: "config", sessionId });
|
|
1840
|
+
}
|
|
1841
|
+
abortController.abort();
|
|
1842
|
+
void harness.abort();
|
|
1843
|
+
return { token, gate };
|
|
1844
|
+
}
|
|
1845
|
+
: undefined;
|
|
1846
|
+
for (const t of tools) {
|
|
1847
|
+
const eff = t.effect;
|
|
1848
|
+
if (eff !== undefined && !toolEffects.has(t.name))
|
|
1849
|
+
toolEffects.set(t.name, eff);
|
|
1850
|
+
}
|
|
1851
|
+
if (effectivePolicy || hooks?.preToolUse || egressTools.size > 0 || irreversibleTools.size > 0 || spec.enablePlanMode === true) {
|
|
1852
|
+
harness.on("tool_call", async (e) => {
|
|
1853
|
+
blockedToolCalls.delete(e.toolCallId);
|
|
1854
|
+
if (planModeRef.active && (toolEffects.get(e.toolName) ?? "write") !== "read") {
|
|
1855
|
+
if (blockedTracked)
|
|
1856
|
+
blockedToolCalls.add(e.toolCallId);
|
|
1857
|
+
const planDenyReason = `Plan mode is active — "${e.toolName}" is a write/mutating tool and is read-only-blocked. ` +
|
|
1858
|
+
`Research with read-only tools, then call ${PRESENT_PLAN_TOOL_NAME} with your plan to get it approved before acting.`;
|
|
1859
|
+
if (notifyPermissionDenied) {
|
|
1860
|
+
await notifyPermissionDenied({ toolName: e.toolName, input: cloneObserverInput(e.input), toolCallId: e.toolCallId, reason: planDenyReason, source: "planMode" });
|
|
1861
|
+
}
|
|
1862
|
+
return {
|
|
1863
|
+
block: true,
|
|
1864
|
+
reason: formatHookFeedback(planDenyReason),
|
|
1865
|
+
preToolContext: [],
|
|
1866
|
+
};
|
|
1867
|
+
}
|
|
1868
|
+
const result = await runToolGate({
|
|
1869
|
+
event: e,
|
|
1870
|
+
preToolUse: hooks?.preToolUse,
|
|
1871
|
+
adjudicate,
|
|
1872
|
+
resolveAsk: resolveAskBound,
|
|
1873
|
+
suspendAsk,
|
|
1874
|
+
egress: egressTools.has(e.toolName),
|
|
1875
|
+
irreversibility: irreversibilityTier.get(e.toolName),
|
|
1876
|
+
reversibilityProbe: reversibilityProbes.get(e.toolName),
|
|
1877
|
+
abortSignal: abortController.signal,
|
|
1878
|
+
...(notifyPermissionDenied ? { permissionDenied: notifyPermissionDenied } : {}),
|
|
1879
|
+
shellGated: (e.toolName === "Bash" && shellGatedBash) || (e.toolName === "Monitor" && shellGatedMonitor),
|
|
1880
|
+
...(autoModeDecider ? { autoMode: { decider: autoModeDecider } } : {}),
|
|
1881
|
+
});
|
|
1882
|
+
if (!result.block && !result.suspend && result.preToolContext.length > 0) {
|
|
1883
|
+
preToolContexts.set(e.toolCallId, result.preToolContext);
|
|
1884
|
+
}
|
|
1885
|
+
if (blockedTracked && (result.block || result.suspend)) {
|
|
1886
|
+
blockedToolCalls.add(e.toolCallId);
|
|
1887
|
+
}
|
|
1888
|
+
return result.block
|
|
1889
|
+
? { block: true, reason: result.reason }
|
|
1890
|
+
: result.updatedInput !== undefined
|
|
1891
|
+
? { updatedInput: result.updatedInput }
|
|
1892
|
+
: undefined;
|
|
1893
|
+
});
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
if (hooks?.postToolUse || hooks?.preToolUse || hooks?.postToolUseFailure) {
|
|
1897
|
+
harness.on("tool_result", async (e) => {
|
|
1898
|
+
if (blockedToolCalls.delete(e.toolCallId)) {
|
|
1899
|
+
return undefined;
|
|
1900
|
+
}
|
|
1901
|
+
let content = e.content;
|
|
1902
|
+
let changed = false;
|
|
1903
|
+
if (e.isError) {
|
|
1904
|
+
if (hooks?.postToolUseFailure) {
|
|
1905
|
+
let clonedDetails = e.details;
|
|
1906
|
+
try {
|
|
1907
|
+
clonedDetails = structuredClone(e.details);
|
|
1908
|
+
}
|
|
1909
|
+
catch {
|
|
1910
|
+
}
|
|
1911
|
+
const patch = await hooks.postToolUseFailure(e.toolName, e.input, {
|
|
1912
|
+
error: e.content
|
|
1913
|
+
.filter((c) => c.type === "text")
|
|
1914
|
+
.map((c) => c.text)
|
|
1915
|
+
.join("\n"),
|
|
1916
|
+
isInterrupt: abortController.signal.aborted || spec.signal?.aborted === true,
|
|
1917
|
+
content: e.content.map((c) => ({ ...c })),
|
|
1918
|
+
details: clonedDetails,
|
|
1919
|
+
}, { toolCallId: e.toolCallId, toolName: e.toolName });
|
|
1920
|
+
if (patch?.additionalContext) {
|
|
1921
|
+
content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext) }];
|
|
1922
|
+
changed = true;
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
else if (hooks?.postToolUse) {
|
|
1927
|
+
const patch = await hooks.postToolUse(e.toolName, e.input, { content: e.content, details: e.details, isError: e.isError }, { toolCallId: e.toolCallId, toolName: e.toolName });
|
|
1928
|
+
if (patch?.updatedOutput) {
|
|
1929
|
+
content = patch.updatedOutput;
|
|
1930
|
+
changed = true;
|
|
1931
|
+
}
|
|
1932
|
+
if (patch?.additionalContext) {
|
|
1933
|
+
content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext) }];
|
|
1934
|
+
changed = true;
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
const pre = preToolContexts.get(e.toolCallId);
|
|
1938
|
+
if (pre) {
|
|
1939
|
+
preToolContexts.delete(e.toolCallId);
|
|
1940
|
+
content = [...content, ...pre.map((t) => ({ type: "text", text: formatHookFeedback(t) }))];
|
|
1941
|
+
changed = true;
|
|
1942
|
+
}
|
|
1943
|
+
return changed ? { content } : undefined;
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
const editAt = editBudget(model);
|
|
1947
|
+
const guardAt = guardBudget(model);
|
|
1948
|
+
const charsPerToken = model.charsPerToken ?? DEFAULT_CHARS_PER_TOKEN;
|
|
1949
|
+
harness.on("context", async ({ messages }) => {
|
|
1950
|
+
const healed = dropEmptyFailureAssistants(messages);
|
|
1951
|
+
const capped = await capAggregateToolResults(healed, {
|
|
1952
|
+
store: offloadStore,
|
|
1953
|
+
sessionId,
|
|
1954
|
+
onCapped: (info) => emitTrace(deps.tracer, () => ({
|
|
1955
|
+
kind: "tool_result.capped",
|
|
1956
|
+
version: 1,
|
|
1957
|
+
taskId: spec.taskId ?? sessionId,
|
|
1958
|
+
...(info.tool !== undefined ? { tool: info.tool } : {}),
|
|
1959
|
+
sizeChars: info.sizeChars,
|
|
1960
|
+
storeFallback: info.storeFallback,
|
|
1961
|
+
ts: Date.now(),
|
|
1962
|
+
})),
|
|
1963
|
+
});
|
|
1964
|
+
const mediaCapped = capAggregateMediaBytes(capped, {
|
|
1965
|
+
limitBytes: deps.mediaByteCapBytes ?? AGGREGATE_MEDIA_BUDGET_BYTES,
|
|
1966
|
+
onStripped: deps.onMediaStripped,
|
|
1967
|
+
});
|
|
1968
|
+
const edited = clearStaleToolResults(mediaCapped, {
|
|
1969
|
+
budgetTokens: editAt,
|
|
1970
|
+
anchoredTotalTokens: estimateContextTokens(mediaCapped, charsPerToken).tokens,
|
|
1971
|
+
charsPerToken,
|
|
1972
|
+
...(offloadStore
|
|
1973
|
+
? {
|
|
1974
|
+
offload: {
|
|
1975
|
+
persist: (toolCallId, fullText) => {
|
|
1976
|
+
const ref = `tr_${sessionId}_${toolCallId}`;
|
|
1977
|
+
void offloadStore.put(ref, fullText);
|
|
1978
|
+
return ref;
|
|
1979
|
+
},
|
|
1980
|
+
},
|
|
1981
|
+
}
|
|
1982
|
+
: {}),
|
|
1983
|
+
});
|
|
1984
|
+
const trimmed = trimToBudget(edited, guardAt, estimateContextTokens(edited, charsPerToken).tokens, charsPerToken);
|
|
1985
|
+
if (trimmed.length < edited.length) {
|
|
1986
|
+
trimPressureRef.droppedMessages = true;
|
|
1987
|
+
emitTrace(deps.tracer, () => ({
|
|
1988
|
+
kind: "context.trim",
|
|
1989
|
+
version: 1,
|
|
1990
|
+
taskId: spec.taskId ?? sessionId,
|
|
1991
|
+
dropped: edited.length - trimmed.length,
|
|
1992
|
+
ts: Date.now(),
|
|
1993
|
+
}));
|
|
1994
|
+
}
|
|
1995
|
+
const swept = dropOrphanToolResults(trimmed);
|
|
1996
|
+
if (swept.dropped.length > 0) {
|
|
1997
|
+
try {
|
|
1998
|
+
deps.onError?.(new Error(`context belt: dropped ${swept.dropped.length} orphan toolResult(s) whose tool-call assistant was not in the request view — ` +
|
|
1999
|
+
swept.dropped
|
|
2000
|
+
.map((d) => `toolCallId=${d.toolCallId} at index ${d.index} (prev=${d.prevRole}, next=${d.nextRole})`)
|
|
2001
|
+
.join("; ")), { phase: "hook", sessionId });
|
|
2002
|
+
}
|
|
2003
|
+
catch {
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
return { messages: swept.messages };
|
|
2007
|
+
});
|
|
2008
|
+
const cacheBreakDetector = deps.cacheBreakDetection === false ? undefined : new CacheBreakDetector();
|
|
2009
|
+
const cacheFingerprint = cacheBreakDetector
|
|
2010
|
+
? { systemPrompt, tools: toolsToFingerprintInputs(harnessTools) }
|
|
2011
|
+
: undefined;
|
|
2012
|
+
fpRef.current = cacheFingerprint;
|
|
2013
|
+
const promptOverheadTokens = Math.ceil((systemPrompt.length +
|
|
2014
|
+
harnessTools.reduce((a, t) => a + t.name.length + (t.description?.length ?? 0) + JSON.stringify(t.parameters ?? {}).length, 0)) / charsPerToken);
|
|
2015
|
+
const readTaskFile = handsEnabled
|
|
2016
|
+
? async (path) => {
|
|
2017
|
+
try {
|
|
2018
|
+
const r = await executionEnv.readBinaryFile(path);
|
|
2019
|
+
if (!r.ok)
|
|
2020
|
+
return null;
|
|
2021
|
+
const d = decodeTextBytes(r.value);
|
|
2022
|
+
return d.malformed ? null : d.text;
|
|
2023
|
+
}
|
|
2024
|
+
catch {
|
|
2025
|
+
return null;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
: undefined;
|
|
2029
|
+
const recentlyReadFiles = handsEnabled && readFileStateForCheckpoint
|
|
2030
|
+
? () => [...readFileStateForCheckpoint.entries()]
|
|
2031
|
+
.sort((a, b) => (b[1].lastReadAt ?? 0) - (a[1].lastReadAt ?? 0))
|
|
2032
|
+
.map(([path]) => path)
|
|
2033
|
+
: undefined;
|
|
2034
|
+
const detectExternalChanges = handsEnabled && readFileStateForCheckpoint
|
|
2035
|
+
? async (maxFiles) => {
|
|
2036
|
+
const candidates = [...readFileStateForCheckpoint.entries()]
|
|
2037
|
+
.filter(([, e]) => e.lastReadAt !== undefined)
|
|
2038
|
+
.sort((a, b) => (b[1].lastReadAt ?? 0) - (a[1].lastReadAt ?? 0))
|
|
2039
|
+
.slice(0, Math.max(0, maxFiles));
|
|
2040
|
+
const changed = [];
|
|
2041
|
+
const evicted = [];
|
|
2042
|
+
for (const [path, entry] of candidates) {
|
|
2043
|
+
try {
|
|
2044
|
+
const info = await executionEnv.fileInfo(path, abortController.signal);
|
|
2045
|
+
if (!info.ok) {
|
|
2046
|
+
if (info.error.code === "not_found") {
|
|
2047
|
+
readFileStateForCheckpoint.delete(path);
|
|
2048
|
+
evicted.push(path);
|
|
2049
|
+
}
|
|
2050
|
+
continue;
|
|
2051
|
+
}
|
|
2052
|
+
if (info.value.mtimeMs > (entry.lastReadAt ?? 0) + CHANGED_FILES_MTIME_EPS_MS) {
|
|
2053
|
+
changed.push({ path, mtimeMs: info.value.mtimeMs });
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
catch {
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
return { changed, evicted };
|
|
2060
|
+
}
|
|
2061
|
+
: undefined;
|
|
2062
|
+
const listBackgroundTasks = () => defaultTaskRegistry
|
|
2063
|
+
.list({ owner: hostTaskId, scope: taskScope, sessionId })
|
|
2064
|
+
.filter((t) => t.status === "pending" || t.status === "running")
|
|
2065
|
+
.map((t) => ({ id: t.task_id, ...(t.description !== undefined ? { description: t.description } : {}), status: t.status }));
|
|
2066
|
+
return { harness, session, sessionId, taskRootPath, model, thinking, compModel, mcp, blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, nestedStats, cwdRef: handsCwdRef, denyNarrowingPolicy, releaseSignal, cacheBreakDetector, cacheFingerprint, promptManifest, activeTools, ownedEnv, suspendRef, reviewRef, reviewRequestRef, suspendLoopRef, suspendForResource, ...(callCapRef ? { callCapRef } : {}), suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolEffects, promptOverheadTokens, readTaskFile, recentlyReadFiles, compactionReuseRef, trimPressureRef, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit } } : {}), planModeRef, ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), listBackgroundTasks };
|
|
2067
|
+
}
|
|
2068
|
+
catch (prepareErr) {
|
|
2069
|
+
if (mcp) {
|
|
2070
|
+
try {
|
|
2071
|
+
await mcp.dispose();
|
|
2072
|
+
}
|
|
2073
|
+
catch {
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
if (ownedEnv && hasDestroy(ownedEnv)) {
|
|
2077
|
+
try {
|
|
2078
|
+
await ownedEnv.destroy();
|
|
2079
|
+
}
|
|
2080
|
+
catch {
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
await forgetOnThrow();
|
|
2084
|
+
throw prepareErr;
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
//# sourceMappingURL=prepare-task.js.map
|