@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
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
replaceProjectInstructionSnapshot,
|
|
13
13
|
} from '../../project-instructions.js'
|
|
14
14
|
import { attachRepeatNotice } from '../../repeat-call.js'
|
|
15
|
+
import { isReviewExempt } from '../../review-policy.js'
|
|
15
16
|
import { attachNotice, attachSteering, formatJobNote } from '../../steering.js'
|
|
16
17
|
import { type IterationContext, awaitDecisionDurably } from './context.js'
|
|
17
18
|
|
|
@@ -25,11 +26,23 @@ function escalationReason(escalation: ToolCallSummary['escalation']): string {
|
|
|
25
26
|
return `this call's program cannot be verified ahead of time (${escalation.unknownProgram})`
|
|
26
27
|
}
|
|
27
28
|
if (escalation?.sandboxEscape) return "this call asks to run outside the turn's sandbox"
|
|
29
|
+
if (escalation?.dangerousRemoval !== undefined) {
|
|
30
|
+
return `this call removes something catastrophic (${escalation.dangerousRemoval})`
|
|
31
|
+
}
|
|
32
|
+
if (escalation?.protectedPaths?.length) {
|
|
33
|
+
return `this call writes a protected ${escalation.protectedPaths.length === 1 ? 'path' : 'paths'} (${escalation.protectedPaths.join(', ')})`
|
|
34
|
+
}
|
|
28
35
|
if (escalation?.outsidePaths?.length)
|
|
29
36
|
return `this call reaches ${escalation.outsidePaths.length === 1 ? 'a path' : 'paths'} outside the turn's boundary`
|
|
30
37
|
return "this call reaches past the turn's boundary, which a rule cannot approve on its own"
|
|
31
38
|
}
|
|
32
39
|
|
|
40
|
+
function hookAskedReason(reason: string | undefined): string {
|
|
41
|
+
return reason
|
|
42
|
+
? `a hook asked that a person approve this call: ${reason}`
|
|
43
|
+
: 'a hook asked that a person approve this call'
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
export type ToolReviewDecision = 'executed' | 'rejected' | 'stop'
|
|
34
47
|
|
|
35
48
|
/**
|
|
@@ -124,15 +137,27 @@ export async function* runToolReview(
|
|
|
124
137
|
const isDestructive = tool?.isDestructive ? tool.isDestructive(tc.input) : false
|
|
125
138
|
const requiresApproval = tool?.requiresApproval ? tool.requiresApproval(tc.input) : false
|
|
126
139
|
const escalation = 'escalation' in tc ? tc.escalation : undefined
|
|
140
|
+
const hookPermission = 'hookPermission' in tc ? tc.hookPermission : undefined
|
|
127
141
|
|
|
128
142
|
return {
|
|
129
143
|
id: tc.id,
|
|
130
144
|
name: tc.name,
|
|
131
145
|
input: tc.input,
|
|
132
146
|
isDestructive,
|
|
133
|
-
|
|
147
|
+
// A hook that asked for a person is an explicit review: a call the
|
|
148
|
+
// tool declares read-only, or one a rule would allow, is still put
|
|
149
|
+
// to one.
|
|
150
|
+
authorization:
|
|
151
|
+
hookPermission?.decision === 'ask'
|
|
152
|
+
? {
|
|
153
|
+
decision: 'review' as const,
|
|
154
|
+
reason: hookAskedReason(hookPermission.reason),
|
|
155
|
+
explicitReview: true as const,
|
|
156
|
+
}
|
|
157
|
+
: { decision: 'review' as const },
|
|
134
158
|
...(requiresApproval ? { requiresApproval: true as const } : {}),
|
|
135
159
|
...(escalation ? { escalation } : {}),
|
|
160
|
+
...(hookPermission ? { hookPermission } : {}),
|
|
136
161
|
}
|
|
137
162
|
})
|
|
138
163
|
}
|
|
@@ -355,6 +380,24 @@ export async function* runToolReview(
|
|
|
355
380
|
reason,
|
|
356
381
|
})
|
|
357
382
|
}
|
|
383
|
+
for (const path of tc.escalation?.protectedPaths ?? []) {
|
|
384
|
+
await ctx.recorder.recordAudit({
|
|
385
|
+
what: { action: 'protected_path_write', tool: tc.name, resource: path },
|
|
386
|
+
outcome: 'refused',
|
|
387
|
+
reason,
|
|
388
|
+
})
|
|
389
|
+
}
|
|
390
|
+
if (tc.escalation?.dangerousRemoval !== undefined) {
|
|
391
|
+
await ctx.recorder.recordAudit({
|
|
392
|
+
what: {
|
|
393
|
+
action: 'dangerous_removal',
|
|
394
|
+
tool: tc.name,
|
|
395
|
+
resource: tc.escalation.dangerousRemoval,
|
|
396
|
+
},
|
|
397
|
+
outcome: 'refused',
|
|
398
|
+
reason,
|
|
399
|
+
})
|
|
400
|
+
}
|
|
358
401
|
}
|
|
359
402
|
|
|
360
403
|
// Gate-denied ids survive the whole function: a later human approval
|
|
@@ -419,11 +462,21 @@ export async function* runToolReview(
|
|
|
419
462
|
reason: `${gr.gateResult.reason}; but the tool itself declares this call always needs a person's approval, which a rule cannot waive`,
|
|
420
463
|
}
|
|
421
464
|
}
|
|
465
|
+
// A hook that asked for a person can only ADD a review, like the two
|
|
466
|
+
// overrides above: a `deny` stays a denial.
|
|
467
|
+
const hookAsked = gr.toolCall.hookPermission?.decision === 'ask'
|
|
468
|
+
if (hookAsked && gr.gateResult.decision === 'allow') {
|
|
469
|
+
gr.gateResult = {
|
|
470
|
+
decision: 'review',
|
|
471
|
+
matchedRule: gr.gateResult.matchedRule,
|
|
472
|
+
reason: `${gr.gateResult.reason}; but ${hookAskedReason(gr.toolCall.hookPermission?.reason)}`,
|
|
473
|
+
}
|
|
474
|
+
}
|
|
422
475
|
const { toolCall, gateResult } = gr
|
|
423
476
|
toolCall.authorization = {
|
|
424
477
|
decision: gateResult.decision,
|
|
425
478
|
...(gateResult.reason ? { reason: gateResult.reason } : {}),
|
|
426
|
-
...(gateResult.decision === 'review' && gateResult.matchedRule
|
|
479
|
+
...(gateResult.decision === 'review' && (gateResult.matchedRule || hookAsked)
|
|
427
480
|
? { explicitReview: true as const }
|
|
428
481
|
: {}),
|
|
429
482
|
}
|
|
@@ -498,6 +551,27 @@ export async function* runToolReview(
|
|
|
498
551
|
}
|
|
499
552
|
}
|
|
500
553
|
|
|
554
|
+
// A `pre_tool_use` hook's `allow`, marked on the calls it covers on the
|
|
555
|
+
// same terms as a skill's grant above and honoured by the review policy,
|
|
556
|
+
// never decided here. A deny, an explicit review (a rule's, or a hook's own
|
|
557
|
+
// `ask`), a destructive call, a path outside the roots, a sandbox escape and
|
|
558
|
+
// a tool's own `requiresApproval` all leave the call unmarked, so it is
|
|
559
|
+
// reviewed as though no hook had spoken.
|
|
560
|
+
/** Whether a hook's `allow` may stand in for a person on this call. */
|
|
561
|
+
const hookMayAllow = (tc: ToolCallSummary): boolean =>
|
|
562
|
+
!gateDenied.has(tc.id) &&
|
|
563
|
+
tc.authorization?.decision !== 'deny' &&
|
|
564
|
+
!tc.authorization?.explicitReview &&
|
|
565
|
+
!tc.isDestructive &&
|
|
566
|
+
tc.escalation === undefined &&
|
|
567
|
+
!tc.requiresApproval
|
|
568
|
+
for (const tc of toolCallSummaries) {
|
|
569
|
+
if (tc.hookPermission?.decision !== 'allow' || !hookMayAllow(tc)) continue
|
|
570
|
+
tc.hookGrant = {
|
|
571
|
+
...(tc.hookPermission.reason ? { reason: tc.hookPermission.reason } : {}),
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
501
575
|
// Already approved, at a scope the approver chose — and nothing the
|
|
502
576
|
// operator's policy denied, because `gateDenied` is checked first.
|
|
503
577
|
// Re-asking about a call somebody has already said yes to is how an
|
|
@@ -525,6 +599,76 @@ export async function* runToolReview(
|
|
|
525
599
|
return finish('executed')
|
|
526
600
|
}
|
|
527
601
|
|
|
602
|
+
// A person is about to be asked. `permission_request` hooks may answer
|
|
603
|
+
// first, per call: `skip` refuses it (and always wins), `allow` approves it
|
|
604
|
+
// on the same terms as a `pre_tool_use` allow. A read the review policy
|
|
605
|
+
// would not have asked about is not a question and is not offered.
|
|
606
|
+
if (ctx.pluginManager) {
|
|
607
|
+
const questions = toolCallSummaries.filter(
|
|
608
|
+
(tc) =>
|
|
609
|
+
!gateDenied.has(tc.id) &&
|
|
610
|
+
tc.authorization?.decision !== 'deny' &&
|
|
611
|
+
tc.authorization?.decision !== 'allow' &&
|
|
612
|
+
(tc.authorization?.explicitReview === true ||
|
|
613
|
+
tc.escalation !== undefined ||
|
|
614
|
+
tc.requiresApproval === true ||
|
|
615
|
+
tc.isDestructive ||
|
|
616
|
+
!isReviewExempt(ctx.tools, tc.name, tc.input)),
|
|
617
|
+
)
|
|
618
|
+
for (const tc of questions) {
|
|
619
|
+
const answers = await ctx.pluginManager.executeHooks(
|
|
620
|
+
'permission_request',
|
|
621
|
+
{
|
|
622
|
+
sessionId: ctx.recorder.sessionId,
|
|
623
|
+
turnId: ctx.recorder.turnId,
|
|
624
|
+
toolName: tc.name,
|
|
625
|
+
toolInput: tc.input,
|
|
626
|
+
signal: ctx.abortController.signal,
|
|
627
|
+
},
|
|
628
|
+
ctx.emitEvent,
|
|
629
|
+
)
|
|
630
|
+
// The hooks answered side by side: a refusal from any of them stands,
|
|
631
|
+
// whatever the others allowed.
|
|
632
|
+
const refusal = answers.find((answer) => answer.action === 'skip')
|
|
633
|
+
for (const answer of answers) {
|
|
634
|
+
if ((answer.action === 'continue' || answer.action === 'skip') && answer.halt) {
|
|
635
|
+
ctx.toolExecutor.requestHalt?.(answer.halt.reason)
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (refusal?.action === 'skip') {
|
|
639
|
+
const reason = `Blocked by a permission_request hook: ${refusal.reason}`
|
|
640
|
+
gateDenied.set(tc.id, reason)
|
|
641
|
+
tc.authorization = { decision: 'deny', reason }
|
|
642
|
+
await ctx.recorder.recordAudit({
|
|
643
|
+
what: { action: 'tool_call', tool: tc.name },
|
|
644
|
+
outcome: 'refused',
|
|
645
|
+
reason,
|
|
646
|
+
})
|
|
647
|
+
continue
|
|
648
|
+
}
|
|
649
|
+
for (const answer of answers) {
|
|
650
|
+
if (
|
|
651
|
+
answer.action === 'continue' &&
|
|
652
|
+
answer.permission?.decision === 'allow' &&
|
|
653
|
+
hookMayAllow(tc)
|
|
654
|
+
) {
|
|
655
|
+
tc.hookGrant = {
|
|
656
|
+
...(answer.permission.reason ? { reason: answer.permission.reason } : {}),
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (toolCallSummaries.every((tc) => gateDenied.has(tc.id))) {
|
|
662
|
+
for (const tc of escalated()) {
|
|
663
|
+
const reason = gateDenied.get(tc.id)
|
|
664
|
+
if (reason !== undefined) await recordRefusedEscalation(tc, reason)
|
|
665
|
+
}
|
|
666
|
+
yield* settle(gateDenied)
|
|
667
|
+
yield* ctx.drainPending()
|
|
668
|
+
return finish('rejected')
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
528
672
|
const reviewCheckpoint = await ctx.checkpointMgr.create(ctx.recorder, iterationNum)
|
|
529
673
|
|
|
530
674
|
await ctx.emitEvent({
|
|
@@ -607,6 +751,24 @@ export async function* runToolReview(
|
|
|
607
751
|
reason: "the turn's review approved this call",
|
|
608
752
|
})
|
|
609
753
|
}
|
|
754
|
+
for (const path of tc.escalation?.protectedPaths ?? []) {
|
|
755
|
+
await ctx.recorder.recordAudit({
|
|
756
|
+
what: { action: 'protected_path_write', tool: tc.name, resource: path },
|
|
757
|
+
outcome: 'approved',
|
|
758
|
+
reason: "the turn's review approved this call",
|
|
759
|
+
})
|
|
760
|
+
}
|
|
761
|
+
if (tc.escalation?.dangerousRemoval !== undefined) {
|
|
762
|
+
await ctx.recorder.recordAudit({
|
|
763
|
+
what: {
|
|
764
|
+
action: 'dangerous_removal',
|
|
765
|
+
tool: tc.name,
|
|
766
|
+
resource: tc.escalation.dangerousRemoval,
|
|
767
|
+
},
|
|
768
|
+
outcome: 'approved',
|
|
769
|
+
reason: "the turn's review approved this call",
|
|
770
|
+
})
|
|
771
|
+
}
|
|
610
772
|
}
|
|
611
773
|
}
|
|
612
774
|
|
|
@@ -762,6 +924,19 @@ export async function* runToolReview(
|
|
|
762
924
|
}
|
|
763
925
|
}
|
|
764
926
|
|
|
927
|
+
// The same for a call a hook's `allow` approved.
|
|
928
|
+
if (reviewDecision.action === 'approve_tools' && reviewDecision.hookGranted) {
|
|
929
|
+
const listed = new Set(reviewDecision.hookGranted)
|
|
930
|
+
for (const tc of toolCallSummaries) {
|
|
931
|
+
if (!listed.has(tc.id) || !tc.hookGrant || gateDenied.has(tc.id)) continue
|
|
932
|
+
await ctx.recorder.recordAudit({
|
|
933
|
+
what: { action: 'tool_call', tool: tc.name },
|
|
934
|
+
outcome: 'approved',
|
|
935
|
+
reason: `pre-approved by a pre_tool_use hook${tc.hookGrant.reason ? ` (${tc.hookGrant.reason})` : ''}; nobody was asked`,
|
|
936
|
+
})
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
|
|
765
940
|
await ctx.emitEvent({
|
|
766
941
|
type: 'tool_review_completed',
|
|
767
942
|
turnId: ctx.recorder.turnId,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isProviderRequestError } from '../../../provider/errors.js'
|
|
2
|
+
import { isImageInputRefusal } from '../../../provider/image-input-refusal.js'
|
|
2
3
|
import type { Message } from '../../../types/message/index.js'
|
|
3
4
|
import type {
|
|
4
5
|
ChatCompletionParams,
|
|
@@ -8,8 +9,11 @@ import type {
|
|
|
8
9
|
import {
|
|
9
10
|
type RequestImageIdentity,
|
|
10
11
|
findSingleRequestImage,
|
|
12
|
+
projectRequestRichContent,
|
|
11
13
|
projectRequestWithoutImage,
|
|
14
|
+
requestHasImages,
|
|
12
15
|
} from '../request-rich-content.js'
|
|
16
|
+
import type { RequestRepair } from './request-repair.js'
|
|
13
17
|
|
|
14
18
|
const IMAGE_REJECTION_PATTERNS: readonly RegExp[] = [
|
|
15
19
|
/\binvalid[_ -]?image\b/i,
|
|
@@ -52,6 +56,24 @@ function throwIfAborted(signal: AbortSignal | undefined): void {
|
|
|
52
56
|
if (signal?.aborted) throw signal.reason
|
|
53
57
|
}
|
|
54
58
|
|
|
59
|
+
/** The provider and model that refused a request for holding an image. */
|
|
60
|
+
export interface TextOnlyModelRefusal {
|
|
61
|
+
readonly providerId: string
|
|
62
|
+
readonly model: string | undefined
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** See {@link streamWithProviderRejectedImageRecovery}. */
|
|
66
|
+
export interface TextOnlyModelRecovery {
|
|
67
|
+
/**
|
|
68
|
+
* Who is serving the request. A fallback chain reports its head's id and
|
|
69
|
+
* moves between members, so without this the refusal would be filed against
|
|
70
|
+
* a model that never saw the request. Read when the refusal arrives.
|
|
71
|
+
*/
|
|
72
|
+
readonly servedBy?: () => { readonly providerId: string; readonly model?: string }
|
|
73
|
+
/** The retry without images was accepted: `refused` cannot read images. */
|
|
74
|
+
readonly onAccepted: (refused: TextOnlyModelRefusal) => void | Promise<void>
|
|
75
|
+
}
|
|
76
|
+
|
|
55
77
|
/**
|
|
56
78
|
* Retry one provider-invalid request without its only distinct image.
|
|
57
79
|
*
|
|
@@ -65,29 +87,73 @@ export async function* streamWithProviderRejectedImageRecovery(
|
|
|
65
87
|
params: ChatCompletionParams,
|
|
66
88
|
onAccepted: (identity: RequestImageIdentity) => Promise<void>,
|
|
67
89
|
onRequest?: (messages: readonly Message[]) => void,
|
|
90
|
+
textOnly?: TextOnlyModelRecovery,
|
|
91
|
+
repair?: RequestRepair,
|
|
68
92
|
): AsyncIterable<StreamChunk> {
|
|
93
|
+
// Every send, including the retries below, goes through the request repair.
|
|
94
|
+
// They share one repair budget: the original request and its retries are
|
|
95
|
+
// one request to the person, and each resend is a paid call.
|
|
96
|
+
const session = repair?.session()
|
|
97
|
+
const send = (request: ChatCompletionParams): AsyncIterable<StreamChunk> =>
|
|
98
|
+
repair ? repair.stream(provider, request, session) : provider.chatStream(request)
|
|
69
99
|
const candidate = findSingleRequestImage(params.messages)
|
|
70
100
|
onRequest?.(params.messages)
|
|
71
|
-
if (candidate === null) {
|
|
72
|
-
yield*
|
|
101
|
+
if (candidate === null && !requestHasImages(params.messages)) {
|
|
102
|
+
yield* send(params)
|
|
73
103
|
return
|
|
74
104
|
}
|
|
75
105
|
|
|
76
106
|
let produced = false
|
|
77
107
|
let confidence: ImageRejectionConfidence | null = null
|
|
108
|
+
let refused: TextOnlyModelRefusal | null = null
|
|
78
109
|
try {
|
|
79
|
-
for await (const chunk of
|
|
110
|
+
for await (const chunk of send(params)) {
|
|
80
111
|
if (isAcceptedChunk(chunk)) produced = true
|
|
81
112
|
yield chunk
|
|
82
113
|
}
|
|
83
114
|
return
|
|
84
115
|
} catch (error) {
|
|
85
116
|
throwIfAborted(params.signal)
|
|
117
|
+
if (produced) throw error
|
|
118
|
+
// A fault in one image (the server's own `invalid_image`, or wording that
|
|
119
|
+
// says an image could not be decoded) is about that image, not about the
|
|
120
|
+
// model, and it wins: the model reads images, so it keeps the others.
|
|
86
121
|
confidence = classifyProviderRejectedImageError(error)
|
|
87
|
-
if (
|
|
122
|
+
if (confidence === null && isImageInputRefusal(error)) {
|
|
123
|
+
// A model that reads text only refuses the request however many images
|
|
124
|
+
// it holds, so every image goes. Named now, while the member that
|
|
125
|
+
// refused is still the one serving.
|
|
126
|
+
const served = textOnly?.servedBy?.()
|
|
127
|
+
refused = {
|
|
128
|
+
providerId: served?.providerId ?? provider.id,
|
|
129
|
+
model: served?.model ?? params.model,
|
|
130
|
+
}
|
|
131
|
+
} else if (confidence === null || candidate === null) {
|
|
132
|
+
throw error
|
|
133
|
+
}
|
|
88
134
|
}
|
|
89
135
|
|
|
90
136
|
throwIfAborted(params.signal)
|
|
137
|
+
if (refused !== null) {
|
|
138
|
+
// One retry, without any image. The stored conversation is untouched, so
|
|
139
|
+
// a model that does read images gets them again.
|
|
140
|
+
const messages = projectRequestRichContent(params.messages, 0, { imagesReadable: false })
|
|
141
|
+
onRequest?.(messages)
|
|
142
|
+
let accepted = false
|
|
143
|
+
let reportedError = false
|
|
144
|
+
for await (const chunk of send({ ...params, messages })) {
|
|
145
|
+
if (chunk.error !== undefined) reportedError = true
|
|
146
|
+
if (!accepted && isAcceptedChunk(chunk)) {
|
|
147
|
+
throwIfAborted(params.signal)
|
|
148
|
+
await textOnly?.onAccepted(refused)
|
|
149
|
+
accepted = true
|
|
150
|
+
}
|
|
151
|
+
yield chunk
|
|
152
|
+
}
|
|
153
|
+
if (!accepted && !reportedError) await textOnly?.onAccepted(refused)
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
if (candidate === null) return
|
|
91
157
|
const retryParams: ChatCompletionParams = {
|
|
92
158
|
...params,
|
|
93
159
|
messages: projectRequestWithoutImage(params.messages, candidate),
|
|
@@ -95,7 +161,7 @@ export async function* streamWithProviderRejectedImageRecovery(
|
|
|
95
161
|
let accepted = false
|
|
96
162
|
let retryReportedError = false
|
|
97
163
|
onRequest?.(retryParams.messages)
|
|
98
|
-
for await (const chunk of
|
|
164
|
+
for await (const chunk of send(retryParams)) {
|
|
99
165
|
if (chunk.error !== undefined) retryReportedError = true
|
|
100
166
|
if (!accepted && isAcceptedChunk(chunk)) {
|
|
101
167
|
throwIfAborted(params.signal)
|