@namzu/sdk 51.1.0 → 52.1.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/CHANGELOG.md +119 -0
- package/dist/agents/QueryAgent.d.ts.map +1 -1
- package/dist/agents/QueryAgent.js +2 -0
- package/dist/agents/QueryAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts +1 -1
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/examples/SupervisorAgent.d.ts +42 -0
- package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/examples/SupervisorAgent.js +80 -4
- package/dist/agents/examples/SupervisorAgent.js.map +1 -1
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/authorization/protected-paths.d.ts +36 -0
- package/dist/authorization/protected-paths.d.ts.map +1 -0
- package/dist/authorization/protected-paths.js +107 -0
- package/dist/authorization/protected-paths.js.map +1 -0
- package/dist/authorization/readonly-commands.d.ts +39 -0
- package/dist/authorization/readonly-commands.d.ts.map +1 -0
- package/dist/authorization/readonly-commands.js +797 -0
- package/dist/authorization/readonly-commands.js.map +1 -0
- package/dist/authorization/readonly-flags.d.ts +19 -0
- package/dist/authorization/readonly-flags.d.ts.map +1 -0
- package/dist/authorization/readonly-flags.js +178 -0
- package/dist/authorization/readonly-flags.js.map +1 -0
- package/dist/authorization/removal.d.ts +52 -0
- package/dist/authorization/removal.d.ts.map +1 -0
- package/dist/authorization/removal.js +283 -0
- package/dist/authorization/removal.js.map +1 -0
- package/dist/authorization/shell-paths.d.ts +66 -0
- package/dist/authorization/shell-paths.d.ts.map +1 -0
- package/dist/authorization/shell-paths.js +697 -0
- package/dist/authorization/shell-paths.js.map +1 -0
- package/dist/bridge/acp/update.d.ts.map +1 -1
- package/dist/bridge/acp/update.js +1 -0
- package/dist/bridge/acp/update.js.map +1 -1
- package/dist/compaction/context-window.d.ts +24 -0
- package/dist/compaction/context-window.d.ts.map +1 -1
- package/dist/compaction/context-window.js +34 -0
- package/dist/compaction/context-window.js.map +1 -1
- package/dist/compaction/manual.d.ts.map +1 -1
- package/dist/compaction/manual.js +10 -2
- package/dist/compaction/manual.js.map +1 -1
- package/dist/compaction/plan.d.ts +4 -0
- package/dist/compaction/plan.d.ts.map +1 -1
- package/dist/compaction/plan.js +6 -2
- package/dist/compaction/plan.js.map +1 -1
- package/dist/compaction/verifier.d.ts +11 -1
- package/dist/compaction/verifier.d.ts.map +1 -1
- package/dist/compaction/verifier.js +75 -23
- package/dist/compaction/verifier.js.map +1 -1
- package/dist/config/runtime.d.ts +55 -7
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/runtime.js +23 -2
- package/dist/config/runtime.js.map +1 -1
- package/dist/connector/web/guarded-fetch.d.ts.map +1 -1
- package/dist/connector/web/guarded-fetch.js +24 -0
- package/dist/connector/web/guarded-fetch.js.map +1 -1
- package/dist/connector/web/index.d.ts +1 -1
- package/dist/connector/web/index.d.ts.map +1 -1
- package/dist/connector/web/page.d.ts +59 -0
- package/dist/connector/web/page.d.ts.map +1 -0
- package/dist/connector/web/page.js +112 -0
- package/dist/connector/web/page.js.map +1 -0
- package/dist/connector/web/types.d.ts +47 -0
- package/dist/connector/web/types.d.ts.map +1 -1
- package/dist/connector/web/types.js.map +1 -1
- package/dist/constants/continuation.d.ts +8 -0
- package/dist/constants/continuation.d.ts.map +1 -1
- package/dist/constants/continuation.js +8 -0
- package/dist/constants/continuation.js.map +1 -1
- package/dist/constants/plugin/index.d.ts +1 -1
- package/dist/constants/plugin/index.d.ts.map +1 -1
- package/dist/constants/plugin/index.js +1 -1
- package/dist/constants/plugin/index.js.map +1 -1
- package/dist/contracts/a2a.d.ts +2 -2
- package/dist/manager/agent/lifecycle.d.ts +7 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +11 -2
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/session/turn-recorder.d.ts.map +1 -1
- package/dist/manager/session/turn-recorder.js +4 -2
- package/dist/manager/session/turn-recorder.js.map +1 -1
- package/dist/plugin/index.d.ts +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1 -1
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/lifecycle.d.ts +6 -0
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +98 -114
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/plugin/shell-hook.d.ts +90 -22
- package/dist/plugin/shell-hook.d.ts.map +1 -1
- package/dist/plugin/shell-hook.js +434 -41
- package/dist/plugin/shell-hook.js.map +1 -1
- package/dist/provider/capabilities.d.ts +9 -0
- package/dist/provider/capabilities.d.ts.map +1 -1
- package/dist/provider/capabilities.js +15 -0
- package/dist/provider/capabilities.js.map +1 -1
- package/dist/provider/errors.d.ts.map +1 -1
- package/dist/provider/errors.js +13 -0
- package/dist/provider/errors.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +10 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/idle-timeout.d.ts.map +1 -1
- package/dist/provider/idle-timeout.js +5 -0
- package/dist/provider/idle-timeout.js.map +1 -1
- package/dist/provider/image-input-refusal.d.ts +9 -0
- package/dist/provider/image-input-refusal.d.ts.map +1 -0
- package/dist/provider/image-input-refusal.js +54 -0
- package/dist/provider/image-input-refusal.js.map +1 -0
- package/dist/provider/index.d.ts +2 -1
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +2 -1
- package/dist/provider/index.js.map +1 -1
- package/dist/provider/retry.d.ts +7 -2
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +38 -4
- package/dist/provider/retry.js.map +1 -1
- package/dist/public-runtime.d.ts +5 -2
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +5 -2
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-types.d.ts +2 -2
- package/dist/public-types.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.d.ts +21 -0
- package/dist/runtime/jobs/registry.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.js +15 -2
- package/dist/runtime/jobs/registry.js.map +1 -1
- package/dist/runtime/query/deferred-sandbox.d.ts +54 -0
- package/dist/runtime/query/deferred-sandbox.d.ts.map +1 -0
- package/dist/runtime/query/deferred-sandbox.js +75 -0
- package/dist/runtime/query/deferred-sandbox.js.map +1 -0
- package/dist/runtime/query/executor/tool-call-admission.d.ts +10 -0
- package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.js +74 -13
- package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +51 -2
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +214 -9
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/finalize-turn.d.ts +6 -0
- package/dist/runtime/query/finalize-turn.d.ts.map +1 -1
- package/dist/runtime/query/finalize-turn.js +1 -1
- package/dist/runtime/query/finalize-turn.js.map +1 -1
- package/dist/runtime/query/index.d.ts +29 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +108 -28
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +57 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +380 -28
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts +61 -0
- package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/compaction-breaker.js +94 -0
- package/dist/runtime/query/iteration/phases/compaction-breaker.js.map +1 -0
- package/dist/runtime/query/iteration/phases/compaction.d.ts +42 -1
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +203 -23
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +10 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +165 -2
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/provider-rejected-image.d.ts +21 -1
- package/dist/runtime/query/iteration/provider-rejected-image.d.ts.map +1 -1
- package/dist/runtime/query/iteration/provider-rejected-image.js +53 -7
- package/dist/runtime/query/iteration/provider-rejected-image.js.map +1 -1
- package/dist/runtime/query/iteration/request-repair.d.ts +108 -0
- package/dist/runtime/query/iteration/request-repair.d.ts.map +1 -0
- package/dist/runtime/query/iteration/request-repair.js +593 -0
- package/dist/runtime/query/iteration/request-repair.js.map +1 -0
- package/dist/runtime/query/iteration/stream-turn.d.ts +6 -0
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +2 -2
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/path-escalation.d.ts +36 -0
- package/dist/runtime/query/path-escalation.d.ts.map +1 -0
- package/dist/runtime/query/path-escalation.js +184 -0
- package/dist/runtime/query/path-escalation.js.map +1 -0
- package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
- package/dist/runtime/query/plugin-hooks.js +8 -0
- package/dist/runtime/query/plugin-hooks.js.map +1 -1
- package/dist/runtime/query/reminders.d.ts +35 -0
- package/dist/runtime/query/reminders.d.ts.map +1 -0
- package/dist/runtime/query/reminders.js +7 -0
- package/dist/runtime/query/reminders.js.map +1 -0
- package/dist/runtime/query/request-rich-content.d.ts +5 -1
- package/dist/runtime/query/request-rich-content.d.ts.map +1 -1
- package/dist/runtime/query/request-rich-content.js +67 -25
- package/dist/runtime/query/request-rich-content.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +26 -0
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +26 -0
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +79 -5
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/tool-output-budget.d.ts +46 -0
- package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
- package/dist/runtime/query/tool-output-budget.js +85 -1
- package/dist/runtime/query/tool-output-budget.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +1 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +5 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/session/paths.d.ts +5 -1
- package/dist/session/paths.d.ts.map +1 -1
- package/dist/session/paths.js +8 -0
- package/dist/session/paths.js.map +1 -1
- package/dist/store/memory/disk.d.ts.map +1 -1
- package/dist/store/memory/disk.js +2 -2
- package/dist/store/memory/disk.js.map +1 -1
- package/dist/store/memory/markdown.d.ts.map +1 -1
- package/dist/store/memory/markdown.js +2 -2
- package/dist/store/memory/markdown.js.map +1 -1
- package/dist/store/memory/naming.d.ts +9 -0
- package/dist/store/memory/naming.d.ts.map +1 -1
- package/dist/store/memory/naming.js +12 -0
- package/dist/store/memory/naming.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts +30 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +170 -26
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/computer-use.d.ts +1 -1
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +12 -5
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/content-fingerprint.d.ts +2 -0
- package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
- package/dist/tools/builtins/content-fingerprint.js +4 -0
- package/dist/tools/builtins/content-fingerprint.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +60 -18
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/grep.d.ts +8 -1
- package/dist/tools/builtins/grep.d.ts.map +1 -1
- package/dist/tools/builtins/grep.js +152 -33
- package/dist/tools/builtins/grep.js.map +1 -1
- package/dist/tools/builtins/read-file.d.ts +1 -0
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +44 -5
- package/dist/tools/builtins/read-file.js.map +1 -1
- package/dist/tools/builtins/read-render.d.ts +52 -0
- package/dist/tools/builtins/read-render.d.ts.map +1 -1
- package/dist/tools/builtins/read-render.js +143 -0
- package/dist/tools/builtins/read-render.js.map +1 -1
- package/dist/tools/builtins/web.d.ts +13 -2
- package/dist/tools/builtins/web.d.ts.map +1 -1
- package/dist/tools/builtins/web.js +225 -32
- package/dist/tools/builtins/web.js.map +1 -1
- package/dist/tools/coordinator/ask-user-question.d.ts +2 -0
- package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
- package/dist/tools/coordinator/ask-user-question.js +256 -92
- package/dist/tools/coordinator/ask-user-question.js.map +1 -1
- package/dist/tools/coordinator/question-options.d.ts +1 -0
- package/dist/tools/coordinator/question-options.d.ts.map +1 -1
- package/dist/tools/coordinator/question-options.js +6 -1
- package/dist/tools/coordinator/question-options.js.map +1 -1
- package/dist/tools/defineTool.d.ts +4 -1
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +6 -1
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/paths.d.ts +6 -0
- package/dist/tools/paths.d.ts.map +1 -1
- package/dist/tools/paths.js +1 -1
- package/dist/tools/paths.js.map +1 -1
- package/dist/types/agent/query.d.ts +3 -0
- package/dist/types/agent/query.d.ts.map +1 -1
- package/dist/types/errors/catalog.js +1 -1
- package/dist/types/errors/catalog.js.map +1 -1
- package/dist/types/hitl/index.d.ts +104 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/message/index.d.ts +1 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +2 -0
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +93 -19
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/plugin/index.js +3 -0
- package/dist/types/plugin/index.js.map +1 -1
- package/dist/types/provider/errors.d.ts +19 -0
- package/dist/types/provider/errors.d.ts.map +1 -1
- package/dist/types/provider/errors.js +54 -5
- package/dist/types/provider/errors.js.map +1 -1
- package/dist/types/provider/interface.d.ts +12 -0
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/provider/stream.d.ts +1 -1
- package/dist/types/session/config.d.ts +14 -0
- package/dist/types/session/config.d.ts.map +1 -1
- package/dist/types/session/events.d.ts +27 -4
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/session/records.d.ts +9 -9
- package/dist/types/session/records.d.ts.map +1 -1
- package/dist/types/session/records.js +1 -0
- package/dist/types/session/records.js.map +1 -1
- package/dist/types/session/stop-reason.d.ts +5 -0
- package/dist/types/session/stop-reason.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +52 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/package.json +4 -2
- package/src/agents/QueryAgent.ts +5 -1
- package/src/agents/SupervisorAgent.ts +1 -1
- package/src/agents/examples/SupervisorAgent.ts +217 -106
- package/src/agents/index.ts +1 -1
- package/src/authorization/protected-paths.ts +110 -0
- package/src/authorization/readonly-commands.ts +771 -0
- package/src/authorization/readonly-flags.ts +196 -0
- package/src/authorization/removal.ts +326 -0
- package/src/authorization/shell-paths.ts +927 -0
- package/src/bridge/acp/update.ts +1 -0
- package/src/compaction/context-window.ts +41 -0
- package/src/compaction/manual.ts +10 -2
- package/src/compaction/plan.ts +11 -2
- package/src/compaction/verifier.ts +84 -22
- package/src/config/runtime.ts +23 -2
- package/src/connector/web/guarded-fetch.ts +26 -0
- package/src/connector/web/index.ts +3 -0
- package/src/connector/web/page.ts +130 -0
- package/src/connector/web/types.ts +47 -0
- package/src/constants/continuation.ts +10 -0
- package/src/constants/plugin/index.ts +1 -1
- package/src/manager/agent/lifecycle.ts +12 -4
- package/src/manager/session/turn-recorder.ts +10 -2
- package/src/plugin/index.ts +1 -0
- package/src/plugin/lifecycle.ts +107 -119
- package/src/plugin/shell-hook.ts +477 -43
- package/src/provider/capabilities.ts +17 -0
- package/src/provider/errors.ts +13 -0
- package/src/provider/fallback.ts +10 -0
- package/src/provider/idle-timeout.ts +5 -0
- package/src/provider/image-input-refusal.ts +54 -0
- package/src/provider/index.ts +2 -0
- package/src/provider/retry.ts +42 -4
- package/src/public-runtime.ts +11 -0
- package/src/public-types.ts +4 -0
- package/src/runtime/jobs/registry.ts +39 -2
- package/src/runtime/query/deferred-sandbox.ts +110 -0
- package/src/runtime/query/executor/tool-call-admission.ts +79 -13
- package/src/runtime/query/executor.ts +267 -11
- package/src/runtime/query/finalize-turn.ts +7 -1
- package/src/runtime/query/index.ts +169 -52
- package/src/runtime/query/iteration/index.ts +439 -35
- package/src/runtime/query/iteration/phases/compaction-breaker.ts +108 -0
- package/src/runtime/query/iteration/phases/compaction.ts +241 -38
- package/src/runtime/query/iteration/phases/context.ts +11 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +177 -2
- package/src/runtime/query/iteration/provider-rejected-image.ts +71 -5
- package/src/runtime/query/iteration/request-repair.ts +743 -0
- package/src/runtime/query/iteration/stream-turn.ts +11 -1
- package/src/runtime/query/path-escalation.ts +204 -0
- package/src/runtime/query/plugin-hooks.ts +8 -0
- package/src/runtime/query/reminders.ts +45 -0
- package/src/runtime/query/request-rich-content.ts +77 -27
- package/src/runtime/query/resume-pending.ts +27 -0
- package/src/runtime/query/review-policy.ts +106 -5
- package/src/runtime/query/tool-output-budget.ts +115 -1
- package/src/runtime/query/tooling.ts +6 -0
- package/src/session/paths.ts +11 -1
- package/src/store/memory/disk.ts +2 -1
- package/src/store/memory/markdown.ts +2 -1
- package/src/store/memory/naming.ts +13 -0
- package/src/tools/builtins/bash.ts +203 -34
- package/src/tools/builtins/computer-use.ts +13 -4
- package/src/tools/builtins/content-fingerprint.ts +5 -0
- package/src/tools/builtins/edit.ts +69 -19
- package/src/tools/builtins/grep.ts +159 -38
- package/src/tools/builtins/read-file.ts +48 -5
- package/src/tools/builtins/read-render.ts +193 -0
- package/src/tools/builtins/web.ts +258 -33
- package/src/tools/coordinator/ask-user-question.ts +309 -103
- package/src/tools/coordinator/question-options.ts +8 -1
- package/src/tools/defineTool.ts +11 -2
- package/src/tools/paths.ts +1 -1
- package/src/types/agent/query.ts +3 -0
- package/src/types/errors/catalog.ts +1 -1
- package/src/types/hitl/index.ts +104 -0
- package/src/types/message/index.ts +2 -0
- package/src/types/plugin/index.ts +101 -18
- package/src/types/provider/errors.ts +66 -5
- package/src/types/provider/interface.ts +13 -0
- package/src/types/provider/stream.ts +1 -1
- package/src/types/session/config.ts +14 -0
- package/src/types/session/events.ts +32 -4
- package/src/types/session/records.ts +1 -0
- package/src/types/session/stop-reason.ts +5 -0
- package/src/types/tool/index.ts +53 -2
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
createToolMessage,
|
|
33
33
|
} from '../../types/message/index.js'
|
|
34
34
|
import type { PermissionMode } from '../../types/permission/index.js'
|
|
35
|
-
import type { PluginHookResult } from '../../types/plugin/index.js'
|
|
35
|
+
import type { PluginHookPermission, PluginHookResult } from '../../types/plugin/index.js'
|
|
36
36
|
import type { ChatCompletionResponse } from '../../types/provider/index.js'
|
|
37
37
|
import type { Sandbox } from '../../types/sandbox/index.js'
|
|
38
38
|
import type { AuditEventInput } from '../../types/session/audit.js'
|
|
@@ -65,6 +65,7 @@ import { type BackgroundJobRegistry, type JobProcess, bindOwner } from '../jobs/
|
|
|
65
65
|
import {
|
|
66
66
|
type ToolAdmissionHost,
|
|
67
67
|
formatFailedToolOutput,
|
|
68
|
+
hookNote,
|
|
68
69
|
isUnregistered,
|
|
69
70
|
prepareDirectCall,
|
|
70
71
|
runPreToolHook,
|
|
@@ -73,14 +74,17 @@ import {
|
|
|
73
74
|
import { describeVisibleFileEvidence } from './file-evidence-context.js'
|
|
74
75
|
import { seedObservationLedger } from './file-evidence-seed.js'
|
|
75
76
|
import { DEFAULT_TOOL_RESULT_GUARDRAILS } from './guardrail-presets.js'
|
|
77
|
+
import { declaredWriteEscalation, shellEscalations } from './path-escalation.js'
|
|
76
78
|
import type { ToolResultObservation } from './project-instructions.js'
|
|
77
79
|
import { savedPresentation } from './saved-presentation.js'
|
|
78
80
|
import { ToolCallBudget, assertMaxToolCalls } from './tool-call-budget.js'
|
|
79
81
|
import {
|
|
80
82
|
DEFAULT_MAX_TOOL_OUTPUT_CHARS,
|
|
83
|
+
DEFAULT_MAX_TOOL_OUTPUT_CHARS_PER_MESSAGE,
|
|
81
84
|
type ToolOutputBudgetResult,
|
|
82
85
|
applyToolOutputBudget,
|
|
83
86
|
describeDroppedContent,
|
|
87
|
+
fitResultsToMessageBudget,
|
|
84
88
|
measureContentBytes,
|
|
85
89
|
} from './tool-output-budget.js'
|
|
86
90
|
|
|
@@ -94,6 +98,7 @@ export type PreparedDirectCall =
|
|
|
94
98
|
readonly toolName: string
|
|
95
99
|
readonly input: unknown
|
|
96
100
|
readonly prepared: PreparedToolExecution
|
|
101
|
+
readonly hook?: PreToolHookNotes
|
|
97
102
|
}
|
|
98
103
|
| {
|
|
99
104
|
readonly kind: 'legacy'
|
|
@@ -101,6 +106,7 @@ export type PreparedDirectCall =
|
|
|
101
106
|
readonly toolName: string
|
|
102
107
|
readonly input: unknown
|
|
103
108
|
readonly inputFailure?: CompletedToolRecord['inputFailure']
|
|
109
|
+
readonly hook?: PreToolHookNotes
|
|
104
110
|
}
|
|
105
111
|
| {
|
|
106
112
|
readonly kind: 'synthetic'
|
|
@@ -129,6 +135,8 @@ export interface PreparedToolBatch {
|
|
|
129
135
|
readonly input: unknown
|
|
130
136
|
/** What the prepared value reaches past the turn's boundary; see `ToolCallSummary.escalation`. */
|
|
131
137
|
readonly escalation?: ToolCallEscalation
|
|
138
|
+
/** What a `pre_tool_use` hook asked for this call's approval; see `ToolCallSummary.hookPermission`. */
|
|
139
|
+
readonly hookPermission?: PluginHookPermission
|
|
132
140
|
}[]
|
|
133
141
|
}
|
|
134
142
|
|
|
@@ -137,6 +145,16 @@ interface OwnedPreparedToolBatch extends PreparedToolBatch {
|
|
|
137
145
|
readonly escalations: ReadonlyMap<string, ToolCallEscalation>
|
|
138
146
|
}
|
|
139
147
|
|
|
148
|
+
/**
|
|
149
|
+
* A nested call cannot open a review from inside the tool that issued it, so
|
|
150
|
+
* a hook that asked for a person to approve it can only be answered with a
|
|
151
|
+
* refusal. Silence would run the call the hook wanted a person to see.
|
|
152
|
+
*/
|
|
153
|
+
function askedNestedMessage(toolName: string, outcome: PreToolHookOutcome): string | undefined {
|
|
154
|
+
if (outcome.kind !== 'continue' || outcome.permission?.decision !== 'ask') return undefined
|
|
155
|
+
return `Blocked: a hook asked that a person approve "${toolName}", and an approval cannot be requested from inside another tool. Call it directly.`
|
|
156
|
+
}
|
|
157
|
+
|
|
140
158
|
function assertUniqueToolCallIds(toolCalls: readonly ToolCall[]): void {
|
|
141
159
|
const seen = new Set<string>()
|
|
142
160
|
for (const [index, toolCall] of toolCalls.entries()) {
|
|
@@ -420,6 +438,8 @@ export interface ToolExecutorConfig {
|
|
|
420
438
|
* {@link DEFAULT_MAX_TOOL_OUTPUT_CHARS}; set `0` to disable.
|
|
421
439
|
*/
|
|
422
440
|
maxToolOutputChars?: number
|
|
441
|
+
/** See QueryParams.maxToolOutputCharsPerMessage. */
|
|
442
|
+
maxToolOutputCharsPerMessage?: number
|
|
423
443
|
/** See QueryParams.retainedToolPreviewChars; applies to the recorded host output. */
|
|
424
444
|
retainedToolPreviewChars?: number
|
|
425
445
|
|
|
@@ -493,8 +513,16 @@ interface PostToolOverride {
|
|
|
493
513
|
readonly content?: ToolResultContent
|
|
494
514
|
}
|
|
495
515
|
|
|
516
|
+
/** What `pre_tool_use` hooks said about a call beyond running it or not. */
|
|
517
|
+
export interface PreToolHookNotes {
|
|
518
|
+
/** The strictest permission answer among the hooks: `ask` outranks `allow`. */
|
|
519
|
+
readonly permission?: PluginHookPermission
|
|
520
|
+
/** Hook text for the model, appended to what it reads of this call. */
|
|
521
|
+
readonly context?: string
|
|
522
|
+
}
|
|
523
|
+
|
|
496
524
|
export type PreToolHookOutcome =
|
|
497
|
-
| { kind: 'continue'; input: unknown; modified: boolean }
|
|
525
|
+
| ({ kind: 'continue'; input: unknown; modified: boolean } & PreToolHookNotes)
|
|
498
526
|
| { kind: 'skip'; input: unknown; output: string }
|
|
499
527
|
| { kind: 'error'; input: unknown; output: string }
|
|
500
528
|
|
|
@@ -625,6 +653,7 @@ export class ToolExecutor {
|
|
|
625
653
|
/** Set per turn by the orchestrator; see {@link setStepAllowedTools}. */
|
|
626
654
|
private stepAllowedTools?: readonly string[]
|
|
627
655
|
private readonly fileReadTracker: FileReadTracker
|
|
656
|
+
private sandboxGate?: () => Promise<void>
|
|
628
657
|
/** A ledger is rebuilt from history at most once; a second pass would re-append its chains. */
|
|
629
658
|
private fileObservationsSeeded = false
|
|
630
659
|
|
|
@@ -658,6 +687,25 @@ export class ToolExecutor {
|
|
|
658
687
|
|
|
659
688
|
setSandbox(sandbox: Sandbox): void {
|
|
660
689
|
this.config = { ...this.config, sandbox }
|
|
690
|
+
this.sandboxGate = undefined
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Hold tool admission until a sandbox that is still being acquired exists.
|
|
695
|
+
* The gate rejects when none will, and the turn settles that rejection. It
|
|
696
|
+
* is cleared by {@link setSandbox}, so a turn pays the check once.
|
|
697
|
+
*/
|
|
698
|
+
setSandboxGate(gate: () => Promise<void>): void {
|
|
699
|
+
this.sandboxGate = gate
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
private async awaitSandbox(): Promise<void> {
|
|
703
|
+
await this.sandboxGate?.()
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/** True once the turn has a sandbox, or is certain to get one before a tool runs. */
|
|
707
|
+
private get sandboxed(): boolean {
|
|
708
|
+
return this.config.sandbox !== undefined || this.sandboxGate !== undefined
|
|
661
709
|
}
|
|
662
710
|
|
|
663
711
|
/** Classify only the exact successful result executed by this executor. */
|
|
@@ -743,7 +791,7 @@ export class ToolExecutor {
|
|
|
743
791
|
messages,
|
|
744
792
|
this.fileReadTracker,
|
|
745
793
|
this.config.workingDirectory,
|
|
746
|
-
this.
|
|
794
|
+
this.sandboxed,
|
|
747
795
|
)
|
|
748
796
|
}
|
|
749
797
|
|
|
@@ -925,7 +973,7 @@ export class ToolExecutor {
|
|
|
925
973
|
const tool = this.config.tools.get(toolName)
|
|
926
974
|
return (
|
|
927
975
|
tool?.commandDialect?.({
|
|
928
|
-
sandboxed: this.
|
|
976
|
+
sandboxed: this.sandboxed,
|
|
929
977
|
}) ?? 'sh'
|
|
930
978
|
)
|
|
931
979
|
}
|
|
@@ -951,6 +999,7 @@ export class ToolExecutor {
|
|
|
951
999
|
hostModifiedCallIds?: ReadonlySet<string>,
|
|
952
1000
|
): Promise<PreparedToolBatch> {
|
|
953
1001
|
assertUniqueToolCallIds(response.message.toolCalls ?? [])
|
|
1002
|
+
if ((response.message.toolCalls ?? []).length > 0) await this.awaitSandbox()
|
|
954
1003
|
const calls = new Map<string, PreparedDirectCall>()
|
|
955
1004
|
const escalations = new Map<string, ToolCallEscalation>()
|
|
956
1005
|
for (const toolCall of response.message.toolCalls ?? []) {
|
|
@@ -984,7 +1033,7 @@ export class ToolExecutor {
|
|
|
984
1033
|
const tool = this.config.tools.get(call.toolName)
|
|
985
1034
|
if (!tool || call.input === null || typeof call.input !== 'object') return undefined
|
|
986
1035
|
const input = call.input as Record<string, unknown>
|
|
987
|
-
const sandboxed = this.
|
|
1036
|
+
const sandboxed = this.sandboxed
|
|
988
1037
|
let outsidePaths: string[] | undefined
|
|
989
1038
|
if (
|
|
990
1039
|
this.config.outsideRootAccess === 'review' &&
|
|
@@ -1003,11 +1052,80 @@ export class ToolExecutor {
|
|
|
1003
1052
|
tool.sandboxEscapeArgument !== undefined &&
|
|
1004
1053
|
input[tool.sandboxEscapeArgument] === true
|
|
1005
1054
|
const unknownProgram = this.unknownProgramOf(tool, input, sandboxed)
|
|
1006
|
-
|
|
1055
|
+
const reaches = await this.pathEscalationsOf(tool, input, sandboxed)
|
|
1056
|
+
if (reaches.outsidePaths.length > 0) {
|
|
1057
|
+
outsidePaths = [...new Set([...(outsidePaths ?? []), ...reaches.outsidePaths])]
|
|
1058
|
+
}
|
|
1059
|
+
const protectedPaths = reaches.protectedPaths
|
|
1060
|
+
const removal = reaches.dangerousRemoval
|
|
1061
|
+
if (
|
|
1062
|
+
!outsidePaths &&
|
|
1063
|
+
!sandboxEscape &&
|
|
1064
|
+
unknownProgram === undefined &&
|
|
1065
|
+
protectedPaths.length === 0 &&
|
|
1066
|
+
removal === undefined
|
|
1067
|
+
) {
|
|
1068
|
+
return undefined
|
|
1069
|
+
}
|
|
1007
1070
|
return {
|
|
1008
1071
|
...(outsidePaths ? { outsidePaths } : {}),
|
|
1009
1072
|
...(sandboxEscape ? { sandboxEscape: true as const } : {}),
|
|
1010
1073
|
...(unknownProgram !== undefined ? { unknownProgram } : {}),
|
|
1074
|
+
...(protectedPaths.length > 0 ? { protectedPaths } : {}),
|
|
1075
|
+
...(removal !== undefined ? { dangerousRemoval: removal } : {}),
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* What the call's own arguments write or remove that no mode may approve in
|
|
1081
|
+
* advance, and, for a shell line, the paths outside the roots it names.
|
|
1082
|
+
*
|
|
1083
|
+
* The protected-path and removal floors hold whether or not the turn reviews
|
|
1084
|
+
* outside paths and whether or not it is sandboxed: they are about what the
|
|
1085
|
+
* write plants and what the removal destroys, not about where the turn is
|
|
1086
|
+
* allowed to look. The outside-path half follows `outsideRootAccess`, as the
|
|
1087
|
+
* file tools' own does.
|
|
1088
|
+
*/
|
|
1089
|
+
private async pathEscalationsOf(
|
|
1090
|
+
tool: Pick<
|
|
1091
|
+
ToolDefinition,
|
|
1092
|
+
'pathArgument' | 'commandArgument' | 'commandDialect' | 'isReadOnly'
|
|
1093
|
+
>,
|
|
1094
|
+
input: Record<string, unknown>,
|
|
1095
|
+
sandboxed: boolean,
|
|
1096
|
+
): Promise<{
|
|
1097
|
+
outsidePaths: readonly string[]
|
|
1098
|
+
protectedPaths: readonly string[]
|
|
1099
|
+
dangerousRemoval?: string
|
|
1100
|
+
}> {
|
|
1101
|
+
const roots = toolRoots(this.config)
|
|
1102
|
+
const protectedPaths: string[] = []
|
|
1103
|
+
let outsidePaths: readonly string[] = []
|
|
1104
|
+
let removal: string | undefined
|
|
1105
|
+
if (tool.pathArgument !== undefined && tool.isReadOnly?.(input) !== true) {
|
|
1106
|
+
const value = input[tool.pathArgument]
|
|
1107
|
+
if (typeof value === 'string') {
|
|
1108
|
+
const hit = await declaredWriteEscalation(roots, value)
|
|
1109
|
+
if (hit !== undefined) protectedPaths.push(hit)
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
if (tool.commandArgument !== undefined) {
|
|
1113
|
+
const line = input[tool.commandArgument]
|
|
1114
|
+
if (typeof line === 'string') {
|
|
1115
|
+
const dialect = tool.commandDialect?.({ sandboxed }) ?? 'sh'
|
|
1116
|
+
const found = await shellEscalations(line, dialect, {
|
|
1117
|
+
roots,
|
|
1118
|
+
reviewOutside: this.config.outsideRootAccess === 'review' && !sandboxed,
|
|
1119
|
+
})
|
|
1120
|
+
protectedPaths.push(...found.protectedPaths)
|
|
1121
|
+
outsidePaths = found.outsidePaths
|
|
1122
|
+
removal = found.dangerousRemoval
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
return {
|
|
1126
|
+
outsidePaths,
|
|
1127
|
+
protectedPaths: [...new Set(protectedPaths)],
|
|
1128
|
+
...(removal !== undefined ? { dangerousRemoval: removal } : {}),
|
|
1011
1129
|
}
|
|
1012
1130
|
}
|
|
1013
1131
|
|
|
@@ -1022,7 +1140,10 @@ export class ToolExecutor {
|
|
|
1022
1140
|
* outside one.
|
|
1023
1141
|
*/
|
|
1024
1142
|
private unknownProgramOf(
|
|
1025
|
-
tool: {
|
|
1143
|
+
tool: {
|
|
1144
|
+
commandArgument?: string
|
|
1145
|
+
commandDialect?: ToolDefinition['commandDialect']
|
|
1146
|
+
},
|
|
1026
1147
|
input: Record<string, unknown>,
|
|
1027
1148
|
sandboxed: boolean,
|
|
1028
1149
|
): string | undefined {
|
|
@@ -1069,11 +1190,13 @@ export class ToolExecutor {
|
|
|
1069
1190
|
)
|
|
1070
1191
|
.map((call) => {
|
|
1071
1192
|
const escalation = escalations.get(call.toolCall.id)
|
|
1193
|
+
const hookPermission = call.hook?.permission
|
|
1072
1194
|
return {
|
|
1073
1195
|
id: call.toolCall.id,
|
|
1074
1196
|
name: call.toolName,
|
|
1075
1197
|
input: call.input,
|
|
1076
1198
|
...(escalation ? { escalation } : {}),
|
|
1199
|
+
...(hookPermission ? { hookPermission } : {}),
|
|
1077
1200
|
}
|
|
1078
1201
|
})
|
|
1079
1202
|
const batch: OwnedPreparedToolBatch = Object.freeze({
|
|
@@ -1097,6 +1220,7 @@ export class ToolExecutor {
|
|
|
1097
1220
|
return { messages: [], results: [], observations: [] }
|
|
1098
1221
|
}
|
|
1099
1222
|
assertUniqueToolCallIds(toolCalls)
|
|
1223
|
+
if (toolCalls.length > 0) await this.awaitSandbox()
|
|
1100
1224
|
|
|
1101
1225
|
// Sampled here, once, and held for every call below. See the note on
|
|
1102
1226
|
// `permissionMode` in the config type.
|
|
@@ -1327,6 +1451,8 @@ export class ToolExecutor {
|
|
|
1327
1451
|
})
|
|
1328
1452
|
}
|
|
1329
1453
|
|
|
1454
|
+
this.fitBatchToMessageBudget(results)
|
|
1455
|
+
|
|
1330
1456
|
// isError and rich content were computed and then discarded here: the
|
|
1331
1457
|
// tuple narrowed to {toolCallId, output} BEFORE the message was built,
|
|
1332
1458
|
// so the failure signal and any image block were structurally lost at
|
|
@@ -1338,6 +1464,51 @@ export class ToolExecutor {
|
|
|
1338
1464
|
return { messages, results, observations }
|
|
1339
1465
|
}
|
|
1340
1466
|
|
|
1467
|
+
/**
|
|
1468
|
+
* Hold the batch's combined result text under the per-message cap.
|
|
1469
|
+
*
|
|
1470
|
+
* Runs once, on the settled batch and before the results become history
|
|
1471
|
+
* messages, so what it writes is what every later request replays.
|
|
1472
|
+
*/
|
|
1473
|
+
private fitBatchToMessageBudget(results: ToolCallOutcome[]): void {
|
|
1474
|
+
const maxChars =
|
|
1475
|
+
this.config.maxToolOutputCharsPerMessage ?? DEFAULT_MAX_TOOL_OUTPUT_CHARS_PER_MESSAGE
|
|
1476
|
+
const replacements = fitResultsToMessageBudget(
|
|
1477
|
+
results.map((r) => ({
|
|
1478
|
+
toolCallId: r.toolCallId,
|
|
1479
|
+
toolName: r.toolName,
|
|
1480
|
+
output: r.output,
|
|
1481
|
+
// A result carrying rich content or a structured-output copy is
|
|
1482
|
+
// not text the model reads alone, and a self-limiting tool has
|
|
1483
|
+
// already decided its own size.
|
|
1484
|
+
replaceable:
|
|
1485
|
+
r.content === undefined &&
|
|
1486
|
+
r.structuredResultJson === undefined &&
|
|
1487
|
+
this.config.tools.get(r.toolName)?.selfLimitingOutput !== true,
|
|
1488
|
+
})),
|
|
1489
|
+
{
|
|
1490
|
+
maxChars,
|
|
1491
|
+
spillDir: this.outputDirectory(),
|
|
1492
|
+
onError: (message) =>
|
|
1493
|
+
this.log.warn('Failed to retain a tool output replaced for the message budget', {
|
|
1494
|
+
[NAMZU.TURN_ID]: this.config.turnId,
|
|
1495
|
+
'exception.message': message,
|
|
1496
|
+
}),
|
|
1497
|
+
},
|
|
1498
|
+
)
|
|
1499
|
+
if (replacements.size === 0) return
|
|
1500
|
+
for (const [i, r] of results.entries()) {
|
|
1501
|
+
const replacement = replacements.get(r.toolCallId)
|
|
1502
|
+
if (replacement === undefined) continue
|
|
1503
|
+
results[i] = { ...r, output: replacement.output }
|
|
1504
|
+
}
|
|
1505
|
+
this.log.warn("Tool results exceeded the message's combined budget", {
|
|
1506
|
+
[NAMZU.TURN_ID]: this.config.turnId,
|
|
1507
|
+
'namzu.runtime.replaced_count': replacements.size,
|
|
1508
|
+
'namzu.runtime.message_budget_chars': maxChars,
|
|
1509
|
+
})
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1341
1512
|
/**
|
|
1342
1513
|
* Run a tool on behalf of another tool, and put it on the record.
|
|
1343
1514
|
*
|
|
@@ -1802,8 +1973,10 @@ export class ToolExecutor {
|
|
|
1802
1973
|
let input: unknown
|
|
1803
1974
|
let prepared: PreparedToolExecution | undefined
|
|
1804
1975
|
let inputFailure: ToolCallOutcome['inputFailure']
|
|
1976
|
+
let preparedHookContext: string | undefined
|
|
1805
1977
|
|
|
1806
1978
|
if (preparedCall?.kind === 'ready' || preparedCall?.kind === 'legacy') {
|
|
1979
|
+
preparedHookContext = preparedCall.hook?.context
|
|
1807
1980
|
input = preparedCall.input
|
|
1808
1981
|
prepared = preparedCall.kind === 'ready' ? preparedCall.prepared : undefined
|
|
1809
1982
|
if (preparedCall.kind === 'legacy') inputFailure = preparedCall.inputFailure
|
|
@@ -1824,6 +1997,7 @@ export class ToolExecutor {
|
|
|
1824
1997
|
if (admitted.kind === 'synthetic') return this.recordSyntheticPreparation(admitted)
|
|
1825
1998
|
toolName = admitted.toolName
|
|
1826
1999
|
input = admitted.input
|
|
2000
|
+
preparedHookContext = admitted.hook?.context
|
|
1827
2001
|
prepared = admitted.kind === 'ready' ? admitted.prepared : undefined
|
|
1828
2002
|
if (admitted.kind === 'legacy') inputFailure = admitted.inputFailure
|
|
1829
2003
|
}
|
|
@@ -2029,7 +2203,11 @@ export class ToolExecutor {
|
|
|
2029
2203
|
]
|
|
2030
2204
|
}
|
|
2031
2205
|
}
|
|
2032
|
-
|
|
2206
|
+
// A tool that bounds its own output is exempt from the DEFAULT per-result
|
|
2207
|
+
// cap only; a host that set the cap explicitly still gets it.
|
|
2208
|
+
const maxToolOutputChars =
|
|
2209
|
+
this.config.maxToolOutputChars ??
|
|
2210
|
+
(executedDefinition?.selfLimitingOutput === true ? 0 : DEFAULT_MAX_TOOL_OUTPUT_CHARS)
|
|
2033
2211
|
const sourceOutput = output
|
|
2034
2212
|
// This owner-bound channel follows the selected receipt after both result
|
|
2035
2213
|
// screening and post-tool replacement. ToolResult.data and raw input can
|
|
@@ -2085,13 +2263,26 @@ export class ToolExecutor {
|
|
|
2085
2263
|
})
|
|
2086
2264
|
}
|
|
2087
2265
|
output = budgeted.output
|
|
2088
|
-
|
|
2266
|
+
let modelContent =
|
|
2089
2267
|
selectedContent === undefined
|
|
2090
2268
|
? undefined
|
|
2091
2269
|
: this.budgetContent(selectedContent, toolName, toolCall.id, {
|
|
2092
2270
|
sourceOutput,
|
|
2093
2271
|
budgeted,
|
|
2094
2272
|
})
|
|
2273
|
+
// What hooks said about this call rides with its result, in the model's
|
|
2274
|
+
// receipt and the host's alike, framed as a hook's words. Added after
|
|
2275
|
+
// the output budget so a bounded result is never trimmed to make room
|
|
2276
|
+
// for it; the note has its own bound (`hookNote`).
|
|
2277
|
+
const hookTexts = [preparedHookContext, post.context].filter(
|
|
2278
|
+
(text): text is string => text !== undefined && text.length > 0,
|
|
2279
|
+
)
|
|
2280
|
+
if (hookTexts.length > 0) {
|
|
2281
|
+
const note = hookNote(hookTexts)
|
|
2282
|
+
output = `${output}\n\n${note}`
|
|
2283
|
+
if (typeof modelContent === 'string') modelContent = `${modelContent}\n\n${note}`
|
|
2284
|
+
else if (modelContent) modelContent = [...modelContent, { type: 'text', text: note }]
|
|
2285
|
+
}
|
|
2095
2286
|
|
|
2096
2287
|
// A failed call, or an override that says the call failed. A `replace`
|
|
2097
2288
|
// says the opposite, and reading it as a failure is what made redaction
|
|
@@ -2438,9 +2629,25 @@ export class ToolExecutor {
|
|
|
2438
2629
|
emitEvent: this.emitEvent,
|
|
2439
2630
|
log: this.log,
|
|
2440
2631
|
allowedTools: this.effectiveAllowedTools(),
|
|
2632
|
+
requestHalt: (reason) => this.requestHalt(reason),
|
|
2441
2633
|
}
|
|
2442
2634
|
}
|
|
2443
2635
|
|
|
2636
|
+
/** Why a hook asked for the turn to stop, until the iteration loop reads it. */
|
|
2637
|
+
private haltReason: string | undefined
|
|
2638
|
+
|
|
2639
|
+
/** The first request wins: a later hook does not rewrite why the turn stopped. */
|
|
2640
|
+
requestHalt(reason: string): void {
|
|
2641
|
+
this.haltReason ??= reason
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
/** Read and clear a hook's request to stop the turn. */
|
|
2645
|
+
takeHalt(): string | undefined {
|
|
2646
|
+
const reason = this.haltReason
|
|
2647
|
+
this.haltReason = undefined
|
|
2648
|
+
return reason
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2444
2651
|
private async prepareNestedCall(
|
|
2445
2652
|
toolName: string,
|
|
2446
2653
|
input: unknown,
|
|
@@ -2468,6 +2675,14 @@ export class ToolExecutor {
|
|
|
2468
2675
|
...(preOutcome.kind === 'skip' ? { skipped: true as const } : {}),
|
|
2469
2676
|
}
|
|
2470
2677
|
}
|
|
2678
|
+
const nestedAsk = askedNestedMessage(toolName, preOutcome)
|
|
2679
|
+
if (nestedAsk)
|
|
2680
|
+
return {
|
|
2681
|
+
kind: 'synthetic',
|
|
2682
|
+
input: preOutcome.input,
|
|
2683
|
+
message: nestedAsk,
|
|
2684
|
+
isError: true,
|
|
2685
|
+
}
|
|
2471
2686
|
return { kind: 'legacy', input: preOutcome.input }
|
|
2472
2687
|
}
|
|
2473
2688
|
|
|
@@ -2513,6 +2728,15 @@ export class ToolExecutor {
|
|
|
2513
2728
|
...(preOutcome.kind === 'skip' ? { skipped: true as const } : {}),
|
|
2514
2729
|
}
|
|
2515
2730
|
}
|
|
2731
|
+
const nestedAsk = askedNestedMessage(toolName, preOutcome)
|
|
2732
|
+
if (nestedAsk) {
|
|
2733
|
+
return {
|
|
2734
|
+
kind: 'synthetic',
|
|
2735
|
+
input: preOutcome.input,
|
|
2736
|
+
message: nestedAsk,
|
|
2737
|
+
isError: true,
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2516
2740
|
if (!preOutcome.modified) {
|
|
2517
2741
|
return {
|
|
2518
2742
|
kind: 'ready',
|
|
@@ -2571,12 +2795,17 @@ export class ToolExecutor {
|
|
|
2571
2795
|
/**
|
|
2572
2796
|
* @returns `override` — text replacing the tool's output, or `null`.
|
|
2573
2797
|
* `retry` — the hook asked for the tool to run again.
|
|
2798
|
+
* `context` — what the hooks want the model to read beside the result.
|
|
2574
2799
|
*/
|
|
2575
2800
|
private async runPostToolHook(
|
|
2576
2801
|
toolName: string,
|
|
2577
2802
|
input: unknown,
|
|
2578
2803
|
toolResult: ToolResult,
|
|
2579
|
-
): Promise<{
|
|
2804
|
+
): Promise<{
|
|
2805
|
+
override: PostToolOverride | null
|
|
2806
|
+
retry: boolean
|
|
2807
|
+
context?: string
|
|
2808
|
+
}> {
|
|
2580
2809
|
if (!this.config.pluginManager) return { override: null, retry: false }
|
|
2581
2810
|
let results: PluginHookResult[]
|
|
2582
2811
|
try {
|
|
@@ -2592,6 +2821,26 @@ export class ToolExecutor {
|
|
|
2592
2821
|
},
|
|
2593
2822
|
this.emitEvent,
|
|
2594
2823
|
)
|
|
2824
|
+
// A failed call is announced a second time, by name, so a hook that
|
|
2825
|
+
// only cares about failures need not read every result. After
|
|
2826
|
+
// `post_tool_use`, so the existing hooks see exactly what they saw.
|
|
2827
|
+
if (!toolResult.success) {
|
|
2828
|
+
results = [
|
|
2829
|
+
...results,
|
|
2830
|
+
...(await this.config.pluginManager.executeHooks(
|
|
2831
|
+
'post_tool_use_failure',
|
|
2832
|
+
{
|
|
2833
|
+
sessionId: this.config.sessionId,
|
|
2834
|
+
turnId: this.config.turnId,
|
|
2835
|
+
toolName,
|
|
2836
|
+
toolInput: input,
|
|
2837
|
+
toolResult,
|
|
2838
|
+
signal: this.config.abortSignal,
|
|
2839
|
+
},
|
|
2840
|
+
this.emitEvent,
|
|
2841
|
+
)),
|
|
2842
|
+
]
|
|
2843
|
+
}
|
|
2595
2844
|
} catch (error) {
|
|
2596
2845
|
if (!this.config.abortSignal.aborted) throw error
|
|
2597
2846
|
// The tool has already returned. Cancellation of a later redaction
|
|
@@ -2608,9 +2857,12 @@ export class ToolExecutor {
|
|
|
2608
2857
|
}
|
|
2609
2858
|
let override: PostToolOverride | null = null
|
|
2610
2859
|
let retry = false
|
|
2860
|
+
const contexts: string[] = []
|
|
2611
2861
|
for (const result of results) {
|
|
2612
2862
|
switch (result.action) {
|
|
2613
2863
|
case 'continue':
|
|
2864
|
+
if (result.context) contexts.push(result.context)
|
|
2865
|
+
if (result.halt) this.requestHalt(result.halt.reason)
|
|
2614
2866
|
continue
|
|
2615
2867
|
case 'error':
|
|
2616
2868
|
override = { output: `Error: ${result.message}`, isError: true }
|
|
@@ -2646,7 +2898,11 @@ export class ToolExecutor {
|
|
|
2646
2898
|
}
|
|
2647
2899
|
}
|
|
2648
2900
|
}
|
|
2649
|
-
return {
|
|
2901
|
+
return {
|
|
2902
|
+
override,
|
|
2903
|
+
retry,
|
|
2904
|
+
...(contexts.length > 0 ? { context: contexts.join('\n') } : {}),
|
|
2905
|
+
}
|
|
2650
2906
|
}
|
|
2651
2907
|
|
|
2652
2908
|
/**
|
|
@@ -53,6 +53,12 @@ export interface TurnFinalization {
|
|
|
53
53
|
* immediately before the record is written.
|
|
54
54
|
*/
|
|
55
55
|
readonly takeSteps: () => readonly StepResult[]
|
|
56
|
+
/**
|
|
57
|
+
* Whether the loop already fired `turn_end` (and `subagent_stop`) when the
|
|
58
|
+
* model finished, so a hook could keep the turn going. Fired there, it is
|
|
59
|
+
* not fired again here.
|
|
60
|
+
*/
|
|
61
|
+
readonly turnEndHooksFired?: () => boolean
|
|
56
62
|
readonly workingStateManager: WorkingStateManager | undefined
|
|
57
63
|
readonly resultAssembler: ResultAssembler
|
|
58
64
|
readonly rootSpan: Span
|
|
@@ -71,7 +77,7 @@ export async function* finalizeTurn(
|
|
|
71
77
|
rootSpan,
|
|
72
78
|
} = finalization
|
|
73
79
|
|
|
74
|
-
if (params.pluginManager) {
|
|
80
|
+
if (params.pluginManager && finalization.turnEndHooksFired?.() !== true) {
|
|
75
81
|
const hookResults = await params.pluginManager.executeHooks(
|
|
76
82
|
'turn_end',
|
|
77
83
|
{ sessionId: ctx.sessionId, turnId: ctx.turnId, signal: ctx.abortController.signal },
|