@sema-agent/core 7.48.0 → 7.49.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 +418 -0
- package/README.md +2 -2
- package/dist/agents/cascade.d.ts +2 -5
- package/dist/agents/child-failure.d.ts +20 -0
- package/dist/agents/child-failure.js +28 -0
- package/dist/agents/cross-session-ref.d.ts +11 -3
- package/dist/agents/cross-session-ref.js +6 -0
- package/dist/agents/cumulative-stats.d.ts +12 -15
- package/dist/agents/cumulative-stats.js +1 -1
- package/dist/agents/extra-tool-names.js +1 -1
- package/dist/agents/inherited-tool-pool.d.ts +17 -13
- package/dist/agents/inherited-tool-pool.js +4 -3
- package/dist/agents/peer-session-drain.d.ts +3 -2
- package/dist/agents/peer-session-drain.js +5 -4
- package/dist/agents/send-message-tool.js +2 -9
- package/dist/agents/subagent.d.ts +10 -29
- package/dist/agents/subagent.js +65 -53
- package/dist/agents/suspend-guard.d.ts +1 -1
- package/dist/agents/tool-filter.d.ts +76 -65
- package/dist/agents/tool-filter.js +122 -92
- package/dist/agents/verify.d.ts +4 -7
- package/dist/agents/verify.js +6 -7
- package/dist/bench/metrics.d.ts +1 -2
- package/dist/brain/anthropic.js +133 -79
- package/dist/brain/errors.d.ts +53 -6
- package/dist/brain/errors.js +22 -2
- package/dist/brain/input-too-long.d.ts +40 -19
- package/dist/brain/input-too-long.js +3 -16
- package/dist/brain/open-responses.js +19 -10
- package/dist/brain/openai.js +123 -32
- package/dist/brain/provider-dialect.d.ts +214 -0
- package/dist/brain/provider-dialect.js +186 -0
- package/dist/brain/request-params.d.ts +27 -8
- package/dist/brain/request-params.js +7 -12
- package/dist/brain/request-route.d.ts +84 -0
- package/dist/brain/request-route.js +41 -0
- package/dist/brain/retry.d.ts +8 -0
- package/dist/brain/retry.js +10 -4
- package/dist/brain/route-adjudicator.d.ts +7 -0
- package/dist/brain/route-adjudicator.js +5 -1
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +11 -0
- package/dist/brain/stream-engine.d.ts +52 -1
- package/dist/brain/stream-engine.js +81 -24
- package/dist/brain/stream-shared.d.ts +57 -11
- package/dist/brain/stream-shared.js +28 -2
- package/dist/core/a2a.d.ts +1 -0
- package/dist/core/agent-config-dir.js +3 -2
- package/dist/core/allow-entry.d.ts +21 -12
- package/dist/core/allow-entry.js +38 -31
- package/dist/core/arg-summary.d.ts +17 -24
- package/dist/core/arg-summary.js +169 -68
- package/dist/core/ask-origin.d.ts +42 -24
- package/dist/core/ask-origin.js +18 -13
- package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
- package/dist/core/auto-mode-prompt-assets.js +1 -1
- package/dist/core/auto-mode-prompt.d.ts +11 -1
- package/dist/core/auto-mode-prompt.js +13 -10
- package/dist/core/auto-mode-rebuild.d.ts +7 -0
- package/dist/core/auto-mode-rebuild.js +4 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.js +2 -1
- package/dist/core/checkpoint-requirements.d.ts +892 -0
- package/dist/core/checkpoint-requirements.js +333 -0
- package/dist/core/checkpoint-store.d.ts +94 -65
- package/dist/core/checkpoint-store.js +14 -26
- package/dist/core/child-clamp-seats.d.ts +228 -69
- package/dist/core/child-clamp-seats.js +211 -17
- package/dist/core/classifier-unavailable-arm.d.ts +5 -1
- package/dist/core/classifier-unavailable-arm.js +3 -3
- package/dist/core/compliance.d.ts +3 -0
- package/dist/core/compliance.js +9 -4
- package/dist/core/credential-vocabulary.d.ts +140 -0
- package/dist/core/credential-vocabulary.js +131 -0
- package/dist/core/decision-receipt.js +1 -1
- package/dist/core/effective-path-target.d.ts +73 -16
- package/dist/core/effective-path-target.js +63 -33
- package/dist/core/engine-notice.d.ts +32 -7
- package/dist/core/file-history-store.js +2 -2
- package/dist/core/fs-write-gate-policy.d.ts +4 -0
- package/dist/core/fs-write-gate-policy.js +22 -5
- package/dist/core/gate-bounded-await.d.ts +28 -13
- package/dist/core/gate-bounded-await.js +41 -4
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +24 -25
- package/dist/core/gate-lanes.js +16 -15
- package/dist/core/gate-outcome.d.ts +20 -5
- package/dist/core/gate-outcome.js +5 -0
- package/dist/core/governance-codes.d.ts +11 -4
- package/dist/core/governance-codes.js +14 -3
- package/dist/core/hooks.d.ts +4 -0
- package/dist/core/locked-config.d.ts +8 -0
- package/dist/core/locked-config.js +14 -2
- package/dist/core/lsp.js +3 -5
- package/dist/core/mailbox-store.d.ts +3 -4
- package/dist/core/mcp-connection-pool.d.ts +75 -0
- package/dist/core/mcp-connection-pool.js +128 -0
- package/dist/core/mcp-failure.d.ts +2 -1
- package/dist/core/mcp-failure.js +13 -2
- package/dist/core/mcp.d.ts +4 -0
- package/dist/core/mcp.js +70 -43
- package/dist/core/memory-engine/content-origin.js +2 -14
- package/dist/core/memory-engine/engine.d.ts +32 -22
- package/dist/core/memory-engine/engine.js +103 -55
- package/dist/core/memory-engine/file-backend.d.ts +13 -30
- package/dist/core/memory-engine/file-backend.js +37 -252
- package/dist/core/memory-engine/index.d.ts +1 -1
- package/dist/core/memory-engine/index.js +1 -1
- package/dist/core/memory-engine/layout.d.ts +139 -9
- package/dist/core/memory-engine/layout.js +350 -7
- package/dist/core/memory-engine/scope-contract.d.ts +10 -0
- package/dist/core/memory-engine/scope-contract.js +8 -0
- package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
- package/dist/core/memory-engine/session-incarnation.js +5 -2
- package/dist/core/memory-engine/types.d.ts +10 -1
- package/dist/core/memory.js +5 -17
- package/dist/core/model-seat.d.ts +4 -4
- package/dist/core/model-seat.js +1 -1
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +19 -0
- package/dist/core/namespaced-rule-name.d.ts +29 -0
- package/dist/core/namespaced-rule-name.js +52 -0
- package/dist/core/park-selfcheck.d.ts +1 -1
- package/dist/core/park-selfcheck.js +16 -6
- package/dist/core/path-guard-rows.d.ts +99 -0
- package/dist/core/path-guard-rows.js +45 -0
- package/dist/core/path-identity.d.ts +22 -16
- package/dist/core/path-identity.js +10 -10
- package/dist/core/path-rule-binding.d.ts +2 -1
- package/dist/core/path-rule-binding.js +3 -1
- package/dist/core/pause-registry.d.ts +16 -2
- package/dist/core/pause-registry.js +6 -0
- package/dist/core/permission-rule-consent.js +0 -7
- package/dist/core/permission-rule-model.d.ts +68 -24
- package/dist/core/permission-rule-model.js +105 -24
- package/dist/core/permission-rule-store.js +2 -2
- package/dist/core/permission-rules.d.ts +3 -30
- package/dist/core/permission-rules.js +4 -54
- package/dist/core/read-root-candidate.d.ts +1 -3
- package/dist/core/read-root-candidate.js +4 -15
- package/dist/core/real-approval.d.ts +4 -3
- package/dist/core/retired-keys.d.ts +13 -0
- package/dist/core/retired-keys.js +14 -0
- package/dist/core/roles.d.ts +2 -3
- package/dist/core/roles.js +15 -6
- package/dist/core/runner/assemble-result.d.ts +0 -7
- package/dist/core/runner/assemble-result.js +19 -31
- package/dist/core/runner/caller-roster.d.ts +78 -0
- package/dist/core/runner/caller-roster.js +219 -0
- package/dist/core/runner/checkpoint-scope.d.ts +16 -16
- package/dist/core/runner/checkpoint-scope.js +2 -2
- package/dist/core/runner/child-tree.js +2 -2
- package/dist/core/runner/contracts.d.ts +68 -35
- package/dist/core/runner/decide-continuation.d.ts +51 -3
- package/dist/core/runner/decide-continuation.js +76 -21
- package/dist/core/runner/denial-limit-arms.d.ts +17 -5
- package/dist/core/runner/denial-limit-arms.js +11 -9
- package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
- package/dist/core/runner/extra-body-dropped-seat.js +22 -0
- package/dist/core/runner/finish-reason-seat.d.ts +9 -0
- package/dist/core/runner/finish-reason-seat.js +40 -0
- package/dist/core/runner/gate-exit.d.ts +44 -32
- package/dist/core/runner/gate-exit.js +112 -25
- package/dist/core/runner/inherited-ask-grants.js +6 -4
- package/dist/core/runner/mcp-redial.d.ts +3 -3
- package/dist/core/runner/mcp-redial.js +3 -4
- package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
- package/dist/core/runner/permission-rule-lanes.js +5 -4
- package/dist/core/runner/prepare-artifact.d.ts +4 -0
- package/dist/core/runner/prepare-artifact.js +2 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
- package/dist/core/runner/prepare-ask-lane.js +12 -6
- package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
- package/dist/core/runner/prepare-boundary-parks.js +4 -7
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
- package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
- package/dist/core/runner/prepare-config-doors.d.ts +9 -9
- package/dist/core/runner/prepare-config-doors.js +10 -5
- package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
- package/dist/core/runner/prepare-defer-classify.js +5 -3
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
- package/dist/core/runner/prepare-delegation-surface.js +3 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
- package/dist/core/runner/prepare-gate-stations.js +9 -7
- package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
- package/dist/core/runner/prepare-hands-readface.js +7 -7
- package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
- package/dist/core/runner/prepare-inherited-gate.js +14 -15
- package/dist/core/runner/prepare-listings.d.ts +7 -24
- package/dist/core/runner/prepare-listings.js +4 -5
- package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
- package/dist/core/runner/prepare-memory-engine-session.js +4 -3
- package/dist/core/runner/prepare-memory.d.ts +6 -0
- package/dist/core/runner/prepare-memory.js +13 -13
- package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
- package/dist/core/runner/prepare-offload-wrappers.js +3 -3
- package/dist/core/runner/prepare-park-ask.d.ts +7 -8
- package/dist/core/runner/prepare-park-ask.js +17 -10
- package/dist/core/runner/prepare-policy-chain.js +24 -44
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +3 -4
- package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
- package/dist/core/runner/prepare-protocol-tools.js +3 -4
- package/dist/core/runner/prepare-run-refs.d.ts +3 -0
- package/dist/core/runner/prepare-run-refs.js +2 -1
- package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
- package/dist/core/runner/prepare-safety-scan.js +1 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
- package/dist/core/runner/prepare-suspend-saga.js +28 -12
- package/dist/core/runner/prepare-task.d.ts +1 -1
- package/dist/core/runner/prepare-task.js +67 -56
- package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
- package/dist/core/runner/prepare-wiring-manifest.js +5 -8
- package/dist/core/runner/resume-apply.js +7 -14
- package/dist/core/runner/resume-checkpoint-screen.js +11 -4
- package/dist/core/runner/resume-internals-and-config.js +2 -2
- package/dist/core/runner/resume-policy-outcome.js +5 -32
- package/dist/core/runner/resume-review-outcome.js +4 -1
- package/dist/core/runner/retired-runner-deps.d.ts +6 -0
- package/dist/core/runner/retired-runner-deps.js +10 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -0
- package/dist/core/runner/run-brain-sinks.js +5 -2
- package/dist/core/runner/run-harness-handlers.js +27 -34
- package/dist/core/runner/run-leg.d.ts +0 -2
- package/dist/core/runner/run-leg.js +32 -33
- package/dist/core/runner/run-terminal-adoption.js +4 -3
- package/dist/core/runner/runtask.js +8 -8
- package/dist/core/runner/session-rule-policy.js +5 -5
- package/dist/core/runner/stream-settle-backstop.js +7 -4
- package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
- package/dist/core/runner/sub-agent-deny-lists.js +111 -80
- package/dist/core/runner/terminal-account.d.ts +48 -0
- package/dist/core/runner/terminal-account.js +186 -0
- package/dist/core/runner/tool-end-body.d.ts +54 -17
- package/dist/core/runner/tool-end-body.js +27 -2
- package/dist/core/runner/tool-face-overlay.d.ts +3 -1
- package/dist/core/runner/tool-face-overlay.js +6 -4
- package/dist/core/runner/tool-occurrence.d.ts +106 -0
- package/dist/core/runner/tool-occurrence.js +123 -0
- package/dist/core/runner/tool-progress-lane.d.ts +16 -8
- package/dist/core/runner/tool-progress-lane.js +25 -34
- package/dist/core/runner/turn-attachments.d.ts +1 -1
- package/dist/core/runner/write-protection-station.d.ts +21 -9
- package/dist/core/runner/write-protection-station.js +20 -17
- package/dist/core/runner-deps.d.ts +12 -22
- package/dist/core/secret-env.d.ts +16 -5
- package/dist/core/secret-env.js +23 -63
- package/dist/core/sensitive-path-policy.d.ts +19 -18
- package/dist/core/sensitive-path-policy.js +73 -49
- package/dist/core/session-reconcile.d.ts +3 -0
- package/dist/core/session-reconcile.js +5 -4
- package/dist/core/session-store.d.ts +5 -0
- package/dist/core/session-store.js +12 -0
- package/dist/core/session.d.ts +13 -0
- package/dist/core/shared-memory/normalize.d.ts +17 -4
- package/dist/core/shared-memory/normalize.js +7 -7
- package/dist/core/shell-lexer.js +5 -4
- package/dist/core/skill-grant.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +2 -2
- package/dist/core/task-event.d.ts +59 -5
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +42 -9
- package/dist/core/terminal-cause.d.ts +94 -11
- package/dist/core/tighten-task-spec.d.ts +5 -4
- package/dist/core/tighten-task-spec.js +20 -25
- package/dist/core/tool-catalog-entries.d.ts +5 -7
- package/dist/core/tool-catalog-entries.js +14 -15
- package/dist/core/tool-face.d.ts +47 -0
- package/dist/core/tool-face.js +5 -0
- package/dist/core/tool-model-gate.d.ts +5 -5
- package/dist/core/tool-name-aliases.d.ts +26 -2
- package/dist/core/tool-name-aliases.js +13 -0
- package/dist/core/tool-name-list.d.ts +30 -0
- package/dist/core/tool-name-list.js +55 -0
- package/dist/core/tool-name-readings.d.ts +1 -9
- package/dist/core/tool-name-readings.js +1 -3
- package/dist/core/tool-policy.d.ts +195 -85
- package/dist/core/tool-policy.js +165 -380
- package/dist/core/tool-registry.d.ts +44 -1
- package/dist/core/tool-registry.js +26 -0
- package/dist/core/tool-roster.d.ts +19 -1
- package/dist/core/tool-roster.js +21 -2
- package/dist/core/tool-spec-members.d.ts +45 -0
- package/dist/core/tool-spec-members.js +169 -0
- package/dist/core/tool-spec.d.ts +46 -8
- package/dist/core/tools.d.ts +6 -2
- package/dist/core/tools.js +8 -4
- package/dist/core/untrusted-egress.js +29 -26
- package/dist/core/untrusted-text.d.ts +13 -10
- package/dist/core/untrusted-text.js +6 -44
- package/dist/core/workflow-journal-store.d.ts +4 -1
- package/dist/core/write-protect.d.ts +65 -29
- package/dist/core/write-protect.js +235 -177
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
- package/dist/engine/execution-env/node-execution-env.js +16 -38
- package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
- package/dist/engine/execution-env/symlink-chain.js +32 -0
- package/dist/engine/harness/types.d.ts +7 -0
- package/dist/engine/llm/tool-turns.d.ts +3 -0
- package/dist/engine/llm/tool-turns.js +1 -0
- package/dist/engine/llm/types.d.ts +59 -23
- package/dist/engine/loop/agent-loop.js +16 -2
- package/dist/engine/session/memory-repo.js +11 -3
- package/dist/engine/session/repo-utils.d.ts +8 -0
- package/dist/engine/session/repo-utils.js +13 -0
- package/dist/index.d.ts +20 -23
- package/dist/index.js +17 -20
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/internal/llm.d.ts +2 -2
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/governance-baseline-validity.js +1 -1
- package/dist/orchestration/run-spec.js +3 -3
- package/dist/orchestration/run-workflow-tool.d.ts +16 -35
- package/dist/orchestration/run-workflow-tool.js +38 -78
- package/dist/orchestration/workflow-governance.d.ts +21 -25
- package/dist/orchestration/workflow-governance.js +38 -78
- package/dist/orchestration/workflow-primitives.d.ts +7 -22
- package/dist/orchestration/workflow-primitives.js +5 -12
- package/dist/orchestration/workflow-types.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +61 -11
- package/dist/orchestration/workflow.js +189 -117
- package/dist/scenarios/full-body.d.ts +1 -1
- package/dist/shell/lex.d.ts +0 -21
- package/dist/shell/lex.js +250 -68
- package/dist/shell/shell-words.d.ts +35 -0
- package/dist/shell/shell-words.js +65 -0
- package/dist/stores/file/checkpoint-store.d.ts +5 -5
- package/dist/stores/file/checkpoint-store.js +5 -2
- package/dist/stores/file/index.d.ts +0 -8
- package/dist/stores/file/index.js +0 -12
- package/dist/stores/file/session-store.d.ts +3 -0
- package/dist/stores/file/session-store.js +44 -19
- package/dist/tools/artifact/artifact-tool.js +2 -0
- package/dist/tools/fs/bash-program-position.d.ts +10 -3
- package/dist/tools/fs/bash-program-position.js +21 -9
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/bash-readonly-classifier.js +8 -7
- package/dist/tools/fs/containment-face.d.ts +4 -0
- package/dist/tools/fs/containment-face.js +3 -0
- package/dist/tools/fs/fs-shared.d.ts +10 -0
- package/dist/tools/fs/fs-shared.js +18 -0
- package/dist/tools/fs/fs-write.js +4 -2
- package/dist/tools/fs/index.d.ts +1 -1
- package/dist/tools/fs/program-read-model.d.ts +39 -18
- package/dist/tools/fs/program-read-model.js +29 -19
- package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
- package/dist/tools/fs/program-read-model.rows.js +5 -5
- package/dist/tools/fs/read-deny-home.d.ts +33 -47
- package/dist/tools/fs/read-deny-home.js +35 -49
- package/dist/tools/fs/read-deny.d.ts +23 -22
- package/dist/tools/fs/read-deny.js +114 -89
- package/dist/tools/fs/removal-targets.d.ts +56 -23
- package/dist/tools/fs/removal-targets.js +65 -87
- package/dist/tools/fs/safety.d.ts +29 -22
- package/dist/tools/fs/safety.js +17 -11
- package/dist/tools/fs/search.js +10 -8
- package/dist/tools/fs/shell-read-argv.js +1 -1
- package/dist/tools/fs/shell-read-bindings.d.ts +169 -37
- package/dist/tools/fs/shell-read-bindings.js +324 -86
- package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
- package/dist/tools/fs/shell-read-builtins.js +43 -0
- package/dist/tools/fs/shell-read-check.d.ts +15 -1
- package/dist/tools/fs/shell-read-check.js +51 -42
- package/dist/tools/fs/shell-read-establish.js +6 -6
- package/dist/tools/fs/shell-read-functions.d.ts +22 -0
- package/dist/tools/fs/shell-read-functions.js +29 -0
- package/dist/tools/fs/shell-read-judge.d.ts +48 -18
- package/dist/tools/fs/shell-read-judge.js +33 -4
- package/dist/tools/fs/shell-read-plan.d.ts +12 -6
- package/dist/tools/fs/shell-read-plan.js +118 -113
- package/dist/tools/fs/shell-read-start.d.ts +29 -6
- package/dist/tools/fs/shell-read-start.js +16 -9
- package/dist/tools/fs/shell-read-word.js +4 -0
- package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
- package/dist/tools/fs/shell-read-workdir.js +281 -0
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
- package/dist/tools/fs/shell-read-write-targets.js +14 -5
- package/dist/tools/fs/shell-reentry-text.d.ts +4 -6
- package/dist/tools/fs/shell-reentry-text.js +3 -11
- package/dist/tools/task-list.d.ts +1 -2
- package/dist/tools/web.js +1 -1
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +107 -143
- package/wire-changes/core@7.49.0.json +4765 -0
- package/dist/agents/teacher.d.ts +0 -159
- package/dist/agents/teacher.js +0 -577
- package/dist/agents/team.d.ts +0 -226
- package/dist/agents/team.js +0 -257
- package/dist/core/strategy-store.d.ts +0 -238
- package/dist/core/strategy-store.js +0 -253
- package/dist/orchestration/builtin-workflows.d.ts +0 -133
- package/dist/orchestration/builtin-workflows.js +0 -159
- package/dist/scenarios/env.d.ts +0 -40
- package/dist/scenarios/env.js +0 -39
- package/dist/scenarios/scenario-registry.d.ts +0 -110
- package/dist/scenarios/scenario-registry.js +0 -140
- package/dist/scenarios/teacher-quickstart.d.ts +0 -40
- package/dist/scenarios/teacher-quickstart.js +0 -12
- package/dist/stores/cc/lockfile.d.ts +0 -10
- package/dist/stores/cc/lockfile.js +0 -98
- package/dist/stores/cc/mailbox-store.d.ts +0 -20
- package/dist/stores/cc/mailbox-store.js +0 -255
- package/dist/stores/cc/roster-adapter.d.ts +0 -12
- package/dist/stores/cc/roster-adapter.js +0 -117
- package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
- package/dist/stores/cc/sidecar-transcript.js +0 -264
- package/dist/stores/cc/task-list-store.d.ts +0 -2
- package/dist/stores/cc/task-list-store.js +0 -125
- package/dist/stores/file/strategy-store.d.ts +0 -97
- package/dist/stores/file/strategy-store.js +0 -341
package/dist/core/tool-policy.js
CHANGED
|
@@ -16,104 +16,93 @@ import { boundInputHashOf } from "./canonical-json.js";
|
|
|
16
16
|
import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY } from "./untrusted-text.js";
|
|
17
17
|
import { describeRejectedValue } from "./tool-search-setting.js";
|
|
18
18
|
import { thrownText } from "./thrown-value.js";
|
|
19
|
+
import { assertNoRetiredToolPolicyKeys } from "./retired-keys.js";
|
|
19
20
|
import { isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
|
|
20
21
|
export { isEngineRefusal } from "./decision-receipt.js";
|
|
21
22
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers, parsePermissionRule } from "./permission-rules.js";
|
|
22
23
|
import { protocolOf } from "./protocol-table.js";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { removalReadingOf } from "../tools/fs/removal-targets.js";
|
|
24
|
+
import { anchorSpelling, isAbsoluteForFamily, normalizeAbsPathLexically, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
|
|
25
|
+
import { KNOWN_SAFE_ROOTS, removalReadingOf } from "../tools/fs/removal-targets.js";
|
|
26
26
|
const nameListHolds = (set, req) => heldBy("policy.nameLists", set, req);
|
|
27
27
|
const shellToolsListHolds = (set, req) => heldBy("policy.shellToolsList", set, req);
|
|
28
28
|
export function advertisedWritableRootsSeat(seat) {
|
|
29
29
|
return seat === undefined ? {} : { advertisedWritableRoots: Object.freeze([...seat.roots]) };
|
|
30
30
|
}
|
|
31
|
+
export function exemptRootsSeat(exemptRoots) {
|
|
32
|
+
return { exemptRoots };
|
|
33
|
+
}
|
|
31
34
|
function settledByNobody(kind) {
|
|
32
35
|
return { kind, who: { party: "none" }, when: Date.now() };
|
|
33
36
|
}
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
export function
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return d;
|
|
69
|
-
}
|
|
70
|
-
export function classifierDenyCauseOf(d, call) {
|
|
71
|
-
if (typeof d !== "object" || d === null)
|
|
72
|
-
return undefined;
|
|
73
|
-
const v = CLASSIFIER_DENY_CAUSES_SEAT.get(d);
|
|
74
|
-
if (v === undefined || v.toolCallId !== call.toolCallId || v.toolName !== call.toolName)
|
|
75
|
-
return undefined;
|
|
76
|
-
return v.cause;
|
|
77
|
-
}
|
|
78
|
-
const CLASSIFIER_ROUNDS_SEAT = new WeakMap();
|
|
79
|
-
export function attestClassifierRound(d, round, call) {
|
|
80
|
-
CLASSIFIER_ROUNDS_SEAT.set(d, { round, toolCallId: call.toolCallId, toolName: call.toolName });
|
|
81
|
-
return d;
|
|
82
|
-
}
|
|
83
|
-
export function classifierRoundOf(d, call) {
|
|
37
|
+
const ATTESTATION_GROUP_OF = {
|
|
38
|
+
settlement: "answer",
|
|
39
|
+
origin: "answer",
|
|
40
|
+
classes: "answer",
|
|
41
|
+
inputDigest: "answer",
|
|
42
|
+
classifierCause: "classifierCause",
|
|
43
|
+
classifierRound: "classifierRound",
|
|
44
|
+
unresolvableCause: "unresolvableCause",
|
|
45
|
+
foldedClasses: "foldedClasses",
|
|
46
|
+
};
|
|
47
|
+
const ATTESTATION_MEMBERS = Object.keys(ATTESTATION_GROUP_OF);
|
|
48
|
+
const groupLead = (g) => ATTESTATION_MEMBERS.find((k) => ATTESTATION_GROUP_OF[k] === g);
|
|
49
|
+
const ENGINE_ATTESTATIONS = new WeakSet();
|
|
50
|
+
function detachedMember(v) {
|
|
51
|
+
if (Array.isArray(v))
|
|
52
|
+
return Object.freeze([...v]);
|
|
53
|
+
if (typeof v !== "object" || v === null)
|
|
54
|
+
return v;
|
|
55
|
+
return Object.freeze(Object.fromEntries(Object.entries(v).map(([k, x]) => [k, typeof x === "object" && x !== null ? Object.freeze(Array.isArray(x) ? [...x] : { ...x }) : x])));
|
|
56
|
+
}
|
|
57
|
+
export function mintAttestation(call, members) {
|
|
58
|
+
const record = { toolCallId: call.toolCallId, toolName: call.toolName };
|
|
59
|
+
for (const k of ATTESTATION_MEMBERS)
|
|
60
|
+
if (members[k] !== undefined)
|
|
61
|
+
record[k] = detachedMember(members[k]);
|
|
62
|
+
const minted = Object.freeze(record);
|
|
63
|
+
ENGINE_ATTESTATIONS.add(minted);
|
|
64
|
+
return minted;
|
|
65
|
+
}
|
|
66
|
+
export function isEngineAttestation(v) {
|
|
67
|
+
return typeof v === "object" && v !== null && ENGINE_ATTESTATIONS.has(v);
|
|
68
|
+
}
|
|
69
|
+
const boundTo = (r, call) => isEngineAttestation(r) && r.toolCallId === call.toolCallId && r.toolName === call.toolName ? r : undefined;
|
|
70
|
+
export function attestationOf(d, call) {
|
|
84
71
|
if (typeof d !== "object" || d === null)
|
|
85
72
|
return undefined;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
return boundTo(Object.getOwnPropertyDescriptor(d, "attestation")?.value, call);
|
|
74
|
+
}
|
|
75
|
+
export function mergeAttestation(call, earlier, later, scope = "all") {
|
|
76
|
+
const a = boundTo(earlier, call);
|
|
77
|
+
const b = boundTo(later, call);
|
|
78
|
+
if (a === undefined)
|
|
79
|
+
return b;
|
|
80
|
+
const members = {};
|
|
81
|
+
if (b !== undefined)
|
|
82
|
+
for (const k of ATTESTATION_MEMBERS)
|
|
83
|
+
if (b[k] !== undefined)
|
|
84
|
+
members[k] = b[k];
|
|
85
|
+
let filled = false;
|
|
86
|
+
for (const g of new Set(Object.values(ATTESTATION_GROUP_OF))) {
|
|
87
|
+
if ((scope === "answer" && g !== "answer") || members[groupLead(g)] !== undefined || a[groupLead(g)] === undefined)
|
|
88
|
+
continue;
|
|
89
|
+
for (const k of ATTESTATION_MEMBERS)
|
|
90
|
+
if (ATTESTATION_GROUP_OF[k] === g && a[k] !== undefined)
|
|
91
|
+
members[k] = a[k];
|
|
92
|
+
filled = true;
|
|
93
|
+
}
|
|
94
|
+
if (!filled)
|
|
95
|
+
return b;
|
|
96
|
+
return mintAttestation(call, members);
|
|
90
97
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
ASK_UNRESOLVABLE_CAUSES_SEAT.set(d, { cause, toolCallId: call.toolCallId, toolName: call.toolName });
|
|
94
|
-
return d;
|
|
98
|
+
export function attest(d, call, members) {
|
|
99
|
+
return withAttestation(d, mergeAttestation(call, attestationOf(d, call), mintAttestation(call, members)));
|
|
95
100
|
}
|
|
96
|
-
export function
|
|
97
|
-
|
|
98
|
-
return undefined;
|
|
99
|
-
const v = ASK_UNRESOLVABLE_CAUSES_SEAT.get(d);
|
|
100
|
-
if (v === undefined || v.toolCallId !== call.toolCallId || v.toolName !== call.toolName)
|
|
101
|
-
return undefined;
|
|
102
|
-
return v.cause;
|
|
103
|
-
}
|
|
104
|
-
const FOLDED_CLASSES_SEAT = new WeakMap();
|
|
105
|
-
function foldedAskClassesAttested(d, held) {
|
|
106
|
-
const signed = FOLDED_CLASSES_SEAT.get(d);
|
|
107
|
-
return signed !== undefined && Array.isArray(held) && signed.length === held.length && signed.every((c, i) => c === held[i]);
|
|
101
|
+
export function withAttestation(d, record) {
|
|
102
|
+
return record === undefined ? d : { ...d, attestation: record };
|
|
108
103
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (typeof d !== "object" || d === null)
|
|
112
|
-
return undefined;
|
|
113
|
-
const v = ENGINE_SETTLEMENTS.get(d);
|
|
114
|
-
if (v === undefined || v.toolCallId !== call.toolCallId || v.toolName !== call.toolName)
|
|
115
|
-
return undefined;
|
|
116
|
-
return { settlement: v.settlement, origin: v.origin };
|
|
104
|
+
export function abortedSeatDeny(req, message, origin) {
|
|
105
|
+
return attest({ action: "deny", message }, req, { settlement: settledByNobody("task_aborted"), origin });
|
|
117
106
|
}
|
|
118
107
|
export const APPROVER_ATTRIBUTION_MAX_CHARS = 256;
|
|
119
108
|
const APPROVER_REFUSED_CHARS_RE = /[\u0000-\u001f\u007f-\u009f\u061c\u200e\u200f\u2028\u2029\u202a-\u202e\u2066-\u2069]/u;
|
|
@@ -138,8 +127,9 @@ export const ASK_EVIDENCE_ABSENCE_VALUES = ["not_wired", "not_adjudicated", "una
|
|
|
138
127
|
export function decisionText(d) {
|
|
139
128
|
return d.message;
|
|
140
129
|
}
|
|
141
|
-
const TOOL_POLICY_CARRIED_MEMBERS = ["projection", "pathRules", "
|
|
130
|
+
const TOOL_POLICY_CARRIED_MEMBERS = ["projection", "pathRules", "writeGuardRows", "nameSets"];
|
|
142
131
|
export function carriedMembersOf(p) {
|
|
132
|
+
assertNoRetiredToolPolicyKeys(p);
|
|
143
133
|
const out = {};
|
|
144
134
|
const carry = (k) => {
|
|
145
135
|
const v = p[k];
|
|
@@ -156,22 +146,11 @@ export function wrapToolPolicy(inner, check) {
|
|
|
156
146
|
export function toolPolicyPathRules(policies, anchors) {
|
|
157
147
|
return policies.flatMap((p) => (typeof p?.pathRules === "function" ? p.pathRules(anchors) : []));
|
|
158
148
|
}
|
|
159
|
-
export function
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
149
|
+
export function toolPolicyWriteGuardRows(policies) {
|
|
150
|
+
const sources = policies.flatMap((p) => (typeof p?.writeGuardRows === "function" ? [p.writeGuardRows] : []));
|
|
151
|
+
if (sources.length === 0)
|
|
162
152
|
return undefined;
|
|
163
|
-
return async (
|
|
164
|
-
for (const guard of guards) {
|
|
165
|
-
try {
|
|
166
|
-
if ((await guard(target, signal)) !== false)
|
|
167
|
-
return true;
|
|
168
|
-
}
|
|
169
|
-
catch {
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return false;
|
|
174
|
-
};
|
|
153
|
+
return async (at) => (await Promise.all(sources.map((rowsOf) => rowsOf(at)))).flat();
|
|
175
154
|
}
|
|
176
155
|
export function namespacedCoveringEntries(entries) {
|
|
177
156
|
return (entries ?? []).filter(isNamespacedCoveringRuleName);
|
|
@@ -263,7 +242,7 @@ const RETIRED_TEXT_FIELD = "reason";
|
|
|
263
242
|
export const DECISION_MEMBERS = Object.keys({
|
|
264
243
|
action: 0, updatedInput: 0, message: 0, decisionReason: 0, requiresRealApproval: 0, denialLimitFallback: 0, classifierNoRuling: 0, allowRuleShadowed: 0, probeReason: 0,
|
|
265
244
|
probeCause: 0, probeMandated: 0, mandated: 0, mandate: 0, probeReadRootCandidate: 0, matchedAskRule: 0, ruleEvidence: 0, segmentCoverage: 0,
|
|
266
|
-
origin: 0, askClass: 0, classes: 0, guard: 0, ruleUnreadable: 0, authoredBy: 0, foldedAskClasses: 0,
|
|
245
|
+
origin: 0, askClass: 0, classes: 0, guard: 0, ruleUnreadable: 0, authoredBy: 0, foldedAskClasses: 0, attestation: 0,
|
|
267
246
|
});
|
|
268
247
|
const HOOK_RESULT_MEMBERS = [...DECISION_MEMBERS, "additionalContext"];
|
|
269
248
|
const HOOK_SEAM_UNREAD = new Set(["decisionReason"]);
|
|
@@ -290,20 +269,30 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
290
269
|
const refused = receiveNestedRecords(contract) ?? screenContractValues(contract, hookSeam ? { skip: HOOK_SEAM_UNREAD, optional: HOOK_SEAM_OPTIONAL } : undefined);
|
|
291
270
|
if (refused !== undefined)
|
|
292
271
|
return refused;
|
|
293
|
-
|
|
294
|
-
|
|
272
|
+
const attestation = contract.attestation;
|
|
273
|
+
if (attestation !== undefined && (hookSeam || !isEngineAttestation(attestation))) {
|
|
274
|
+
return refusedOutOfContract(hookSeam
|
|
275
|
+
? `a PreToolUse hook result carries an "attestation" — the member is an engine-minted record and a hook result carries none; denied fail-closed`
|
|
276
|
+
: `a permission decision carries an "attestation" the engine did not mint — the member is an engine record (who settled the call, ` +
|
|
277
|
+
`which question it answered); denied fail-closed rather than reading a caller's value as a settlement`);
|
|
278
|
+
}
|
|
279
|
+
const folded = contract.foldedAskClasses;
|
|
280
|
+
const signed = attestation?.foldedClasses;
|
|
281
|
+
if (folded !== undefined && !(signed !== undefined && Array.isArray(folded) && signed.length === folded.length && signed.every((c, i) => c === folded[i]))) {
|
|
282
|
+
return refusedOutOfContract(`a permission decision carries "foldedAskClasses" that no policy fold of the engine attested on it — the member is ` +
|
|
295
283
|
`engine-written (combinePolicies records the classes of the asks it collapsed); denied fail-closed rather than letting a ` +
|
|
296
284
|
`class no station judged reach the class derivation`);
|
|
297
285
|
}
|
|
298
286
|
if (hookSeam && contract.additionalContext !== undefined && typeof contract.additionalContext !== "string") {
|
|
299
287
|
return refusedOutOfContract(`a PreToolUse hook result's "additionalContext" is not a string — the member is the text appended for the model; denied fail-closed rather than rendering a value this layer cannot classify`);
|
|
300
288
|
}
|
|
301
|
-
const
|
|
289
|
+
const { attestation: _record, ...members } = contract;
|
|
290
|
+
const detached = tryCloneArgs(members);
|
|
302
291
|
if (!detached.ok) {
|
|
303
292
|
return refusedOutOfContract(`a permission decision's members could not be detached from the layer that returned them (${detached.reason}) — ` +
|
|
304
293
|
`the engine keeps its own copy of what it read; denied fail-closed`);
|
|
305
294
|
}
|
|
306
|
-
const receipt = Object.freeze(detached.value);
|
|
295
|
+
const receipt = Object.freeze(attestation !== undefined ? { ...detached.value, attestation } : detached.value);
|
|
307
296
|
for (const k of ["classes", "foldedAskClasses"])
|
|
308
297
|
if (Object.hasOwn(receipt, k) && Array.isArray(receipt[k]))
|
|
309
298
|
Object.freeze(receipt[k]);
|
|
@@ -313,7 +302,6 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
313
302
|
Object.freeze(v);
|
|
314
303
|
Object.freeze(record);
|
|
315
304
|
}
|
|
316
|
-
carryEngineAttestations(d, receipt);
|
|
317
305
|
(hookSeam ? HOOK_RECEIPTS : ENGINE_RECEIPTS).add(receipt);
|
|
318
306
|
return receipt;
|
|
319
307
|
}
|
|
@@ -457,12 +445,24 @@ export function createApprovalPolicy(opts) {
|
|
|
457
445
|
return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
|
|
458
446
|
}
|
|
459
447
|
if (nameListHolds(need, req) || namespacedCoveringHit(needCovering, req)) {
|
|
460
|
-
const
|
|
448
|
+
const attestOver = (inputDigest) => (d, settlement) => ({ ...d, attestation: mintAttestation(req, { settlement, origin: "policy", inputDigest }) });
|
|
461
449
|
if (signal?.aborted)
|
|
462
450
|
return abortedSeatDeny(req, `approval aborted for "${req.toolName}" (run or turn interrupted)`, "policy");
|
|
451
|
+
const shown = tryCloneArgs(req.args);
|
|
452
|
+
if (!shown.ok) {
|
|
453
|
+
return attestOver(boundInputHashOf(req.args))({ action: "deny", message: `approval for "${req.toolName}" could not present the args safely (unclonable value: ${shown.reason}) — denied fail-closed` }, settledByNobody("presentation_failed"));
|
|
454
|
+
}
|
|
455
|
+
const askedDigest = boundInputHashOf(shown.value);
|
|
456
|
+
const attest = attestOver(askedDigest);
|
|
457
|
+
const heldWhileWaiting = () => boundInputHashOf(req.args) === askedDigest;
|
|
458
|
+
const changedWhilePending = () => attest({
|
|
459
|
+
action: "deny",
|
|
460
|
+
message: `the arguments of "${req.toolName}" changed while its approval was pending — denied fail-closed ` +
|
|
461
|
+
`(an approval answers the arguments it was shown; ask again over the arguments that will run)`,
|
|
462
|
+
}, settledByNobody("approver_contract"));
|
|
463
463
|
let ok;
|
|
464
464
|
try {
|
|
465
|
-
ok = await withTimeout(Promise.resolve(opts.approve(req, signal)), opts.approvalTimeoutMs, () => DEADLINE_ELAPSED);
|
|
465
|
+
ok = await withTimeout(Promise.resolve(opts.approve({ ...req, args: shown.value }, signal)), opts.approvalTimeoutMs, () => DEADLINE_ELAPSED);
|
|
466
466
|
}
|
|
467
467
|
catch (err) {
|
|
468
468
|
return attest({ action: "deny", message: `approval errored for "${req.toolName}": ${describeThrown(err)}` }, settledByNobody("approver_error"));
|
|
@@ -490,11 +490,13 @@ export function createApprovalPolicy(opts) {
|
|
|
490
490
|
: `approval denied for "${req.toolName}"${reading.note !== undefined ? `\nReviewer note:\n${delimitUntrusted("reviewer note", reading.note, REVIEWER_NOTE_MAX_BODY)}` : ""}`,
|
|
491
491
|
}, reading.settlement);
|
|
492
492
|
}
|
|
493
|
+
if (!heldWhileWaiting())
|
|
494
|
+
return changedWhilePending();
|
|
493
495
|
return attest({ action: "allow", decisionReason: "mode" }, reading.settlement);
|
|
494
496
|
}
|
|
495
497
|
const okRaw = ok;
|
|
496
498
|
if (okRaw === true)
|
|
497
|
-
return attest({ action: "allow", decisionReason: "mode" }, settledByDecider("person", "allowed", undefined));
|
|
499
|
+
return heldWhileWaiting() ? attest({ action: "allow", decisionReason: "mode" }, settledByDecider("person", "allowed", undefined)) : changedWhilePending();
|
|
498
500
|
if (okRaw !== false) {
|
|
499
501
|
return attest({
|
|
500
502
|
action: "deny",
|
|
@@ -514,9 +516,11 @@ export function createApprovalPolicy(opts) {
|
|
|
514
516
|
};
|
|
515
517
|
}
|
|
516
518
|
export function combinePolicies(...policies) {
|
|
519
|
+
for (const member of policies)
|
|
520
|
+
assertNoRetiredToolPolicyKeys(member);
|
|
517
521
|
const nameSets = policies.flatMap(toolPolicyNameSets);
|
|
518
522
|
const pathRuled = policies.filter((p) => typeof p?.pathRules === "function");
|
|
519
|
-
const
|
|
523
|
+
const writeGuardRows = toolPolicyWriteGuardRows(policies);
|
|
520
524
|
const childProjections = policies.map((p) => p.projection);
|
|
521
525
|
const projectedComponents = [];
|
|
522
526
|
let combinedRemainder = false;
|
|
@@ -538,7 +542,7 @@ export function combinePolicies(...policies) {
|
|
|
538
542
|
projection: combinedProjection,
|
|
539
543
|
nameSets: nameSets.length > 0 ? nameSets : undefined,
|
|
540
544
|
pathRules: pathRuled.length > 0 ? (anchors) => toolPolicyPathRules(pathRuled, anchors) : undefined,
|
|
541
|
-
|
|
545
|
+
writeGuardRows,
|
|
542
546
|
};
|
|
543
547
|
return {
|
|
544
548
|
...carriedMembersOf(folded),
|
|
@@ -547,8 +551,7 @@ export function combinePolicies(...policies) {
|
|
|
547
551
|
let current = req;
|
|
548
552
|
let rewrite;
|
|
549
553
|
let stated;
|
|
550
|
-
|
|
551
|
-
let anyRecord = false;
|
|
554
|
+
let records;
|
|
552
555
|
let ruleAskText;
|
|
553
556
|
let probeMandateSeen = false;
|
|
554
557
|
let mandateSeen = false;
|
|
@@ -558,20 +561,15 @@ export function combinePolicies(...policies) {
|
|
|
558
561
|
const contributors = [];
|
|
559
562
|
const settleDeny = (d) => {
|
|
560
563
|
const out = rewrite?.updatedInput !== undefined ? { ...d, updatedInput: rewrite.updatedInput } : d;
|
|
561
|
-
if (
|
|
562
|
-
transferEngineAttestations(d, out);
|
|
563
|
-
if (!anyRecord)
|
|
564
|
+
if (records === undefined)
|
|
564
565
|
return out;
|
|
565
|
-
|
|
566
|
-
transferEngineAttestations(records, owned);
|
|
567
|
-
transferEngineAttestations(d, owned);
|
|
568
|
-
return owned;
|
|
566
|
+
return { ...out, attestation: mergeAttestation(req, records, d.attestation) };
|
|
569
567
|
};
|
|
570
568
|
let seatDeny;
|
|
571
569
|
for (const p of policies) {
|
|
572
570
|
const d = refuseOutOfContractDecision(await p.check(current, signal));
|
|
573
571
|
if (d.action === "deny") {
|
|
574
|
-
if (
|
|
572
|
+
if (attestationOf(d, current)?.settlement?.kind !== "task_aborted")
|
|
575
573
|
return settleDeny(d);
|
|
576
574
|
seatDeny ??= settleDeny(d);
|
|
577
575
|
continue;
|
|
@@ -585,10 +583,8 @@ export function combinePolicies(...policies) {
|
|
|
585
583
|
else if (d.action === "allow" && stated === undefined && d.decisionReason !== undefined) {
|
|
586
584
|
stated = d.decisionReason;
|
|
587
585
|
}
|
|
588
|
-
if (d.action === "allow" &&
|
|
589
|
-
|
|
590
|
-
anyRecord = true;
|
|
591
|
-
}
|
|
586
|
+
if (d.action === "allow" && d.attestation !== undefined)
|
|
587
|
+
records = mergeAttestation(req, records, d.attestation);
|
|
592
588
|
if (d.action === "ask" && (asked === undefined || (d.requiresRealApproval === true && asked.requiresRealApproval !== true))) {
|
|
593
589
|
asked = d;
|
|
594
590
|
}
|
|
@@ -628,17 +624,11 @@ export function combinePolicies(...policies) {
|
|
|
628
624
|
folded.add(k);
|
|
629
625
|
const withClasses = folded.size > 0 ? { ...withAuthor, foldedAskClasses: [...folded] } : withAuthor;
|
|
630
626
|
const out = merged !== undefined ? { ...withClasses, updatedInput: merged } : withClasses;
|
|
631
|
-
|
|
632
|
-
FOLDED_CLASSES_SEAT.set(out, Object.freeze([...folded]));
|
|
633
|
-
return out;
|
|
627
|
+
return folded.size > 0 ? attest(out, req, { foldedClasses: [...folded] }) : out;
|
|
634
628
|
}
|
|
635
629
|
const base = rewrite ?? ALLOW;
|
|
636
630
|
const allowed = stated !== undefined && base.decisionReason !== stated ? { ...base, decisionReason: stated } : base;
|
|
637
|
-
|
|
638
|
-
return allowed;
|
|
639
|
-
const out = { ...allowed };
|
|
640
|
-
transferEngineAttestations(records, out);
|
|
641
|
-
return out;
|
|
631
|
+
return records === undefined ? allowed : { ...allowed, attestation: records };
|
|
642
632
|
},
|
|
643
633
|
};
|
|
644
634
|
}
|
|
@@ -691,238 +681,18 @@ export function createCoarseCommandNamePolicy(opts) {
|
|
|
691
681
|
},
|
|
692
682
|
}, "sandbox_local");
|
|
693
683
|
}
|
|
694
|
-
|
|
695
|
-
const
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
const stripTokenEdges = (t) => t.replace(/^[("'{]+|[)"'}]+$/g, "");
|
|
703
|
-
function restOfAssignment(tokens, i, eq) {
|
|
704
|
-
const first = tokens[i].slice(eq + 1);
|
|
705
|
-
const q = first.startsWith('"') ? '"' : first.startsWith("'") ? "'" : undefined;
|
|
706
|
-
if (q === undefined || (first.length > 1 && first.endsWith(q)))
|
|
707
|
-
return first;
|
|
708
|
-
const parts = [first];
|
|
709
|
-
for (let k = i + 1; k < tokens.length; k++) {
|
|
710
|
-
parts.push(tokens[k]);
|
|
711
|
-
if (tokens[k].endsWith(q))
|
|
712
|
-
break;
|
|
713
|
-
}
|
|
714
|
-
return parts.join(" ");
|
|
715
|
-
}
|
|
716
|
-
function assignmentTokenSpan(tokens, i) {
|
|
717
|
-
const eq = tokens[i].indexOf("=");
|
|
718
|
-
const first = tokens[i].slice(eq + 1);
|
|
719
|
-
const q = first.startsWith('"') ? '"' : first.startsWith("'") ? "'" : undefined;
|
|
720
|
-
if (q === undefined || (first.length > 1 && first.endsWith(q)))
|
|
721
|
-
return 1;
|
|
722
|
-
for (let k = i + 1; k < tokens.length; k++)
|
|
723
|
-
if (tokens[k].endsWith(q))
|
|
724
|
-
return k - i + 1;
|
|
725
|
-
return 1;
|
|
726
|
-
}
|
|
727
|
-
function valueIsOpaque(value, assigned, safeVars) {
|
|
728
|
-
const v = value.replace(/["']/g, "").replace(/\\(.)/g, "$1");
|
|
729
|
-
if (v.includes("$(") || v.includes("`"))
|
|
730
|
-
return true;
|
|
731
|
-
if (/\$[@*#!?0-9-]/.test(v))
|
|
732
|
-
return true;
|
|
733
|
-
if (/\$\{[!#]/.test(v))
|
|
734
|
-
return true;
|
|
735
|
-
for (const vm of v.matchAll(/\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g)) {
|
|
736
|
-
const ref = vm[1];
|
|
737
|
-
if (!assigned.has(ref) && !(safeVars.has(ref) && safeRootBelow(v.slice((vm.index ?? 0) + vm[0].length))))
|
|
738
|
-
return true;
|
|
739
|
-
}
|
|
740
|
-
return false;
|
|
741
|
-
}
|
|
742
|
-
const safeRootBelow = (after) => /^\/[^*?[\]]+$/.test(after) && !after.split("/").includes("..");
|
|
743
|
-
export function findUnverifiableRecursiveDelete(command, safeVars = new Set(UNVERIFIABLE_DELETE_SAFE_VARS)) {
|
|
744
|
-
const assigned = new Set();
|
|
745
|
-
const assignedEscapesRoot = new Set();
|
|
746
|
-
const valueEscapesRoot = (value, safe) => {
|
|
747
|
-
const v = value.replace(/\\(.)/g, "$1").replace(/["']/g, "");
|
|
748
|
-
for (const vm of v.matchAll(/\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g)) {
|
|
749
|
-
if (!safe.has(vm[1]))
|
|
750
|
-
continue;
|
|
751
|
-
if (v.slice((vm.index ?? 0) + vm[0].length).split("/").includes(".."))
|
|
752
|
-
return true;
|
|
753
|
-
}
|
|
754
|
-
return false;
|
|
755
|
-
};
|
|
756
|
-
const applyAssignmentWord = (words, at) => {
|
|
757
|
-
const written = writtenAssignmentPrefix(words[at]);
|
|
758
|
-
if (written === undefined) {
|
|
759
|
-
assigned.delete(words[at].replace(/\[.*$/, ""));
|
|
760
|
-
return;
|
|
761
|
-
}
|
|
762
|
-
const value = restOfAssignment(words, at, written.prefix.length - 1);
|
|
763
|
-
if ((!written.settlesWholeName && !assigned.has(written.name)) || valueIsOpaque(value, assigned, safeVars))
|
|
764
|
-
assigned.delete(written.name);
|
|
765
|
-
else
|
|
766
|
-
assigned.add(written.name);
|
|
767
|
-
if (valueEscapesRoot(value, safeVars))
|
|
768
|
-
assignedEscapesRoot.add(written.name);
|
|
769
|
-
else if (written.settlesWholeName)
|
|
770
|
-
assignedEscapesRoot.delete(written.name);
|
|
771
|
-
};
|
|
772
|
-
const statements = command.replace(/\\\r?\n/g, " ").split(STATEMENT_SPLIT);
|
|
773
|
-
for (const stmt of statements) {
|
|
774
|
-
const tokens = stmt.trim().split(/\s+/).filter(Boolean);
|
|
775
|
-
let i = 0;
|
|
776
|
-
while (i < tokens.length && ASSIGNMENT_PREFIX.test(tokens[i])) {
|
|
777
|
-
applyAssignmentWord(tokens, i);
|
|
778
|
-
i += assignmentTokenSpan(tokens, i);
|
|
779
|
-
}
|
|
780
|
-
let sawWrapper = false;
|
|
781
|
-
while (i < tokens.length) {
|
|
782
|
-
const t = stripTokenEdges(tokens[i]).replace(/^\\/, "");
|
|
783
|
-
if (t === "") {
|
|
784
|
-
i++;
|
|
785
|
-
continue;
|
|
786
|
-
}
|
|
787
|
-
if (DELETE_WRAPPERS.has(t)) {
|
|
788
|
-
sawWrapper = true;
|
|
789
|
-
i++;
|
|
790
|
-
while (i < tokens.length && (/^-/.test(tokens[i]) || ASSIGNMENT_PREFIX.test(tokens[i])))
|
|
791
|
-
i++;
|
|
792
|
-
continue;
|
|
793
|
-
}
|
|
794
|
-
if (/\)$/.test(tokens[i]) && !DELETE_HEADS.has(t)) {
|
|
795
|
-
sawWrapper = true;
|
|
796
|
-
i++;
|
|
797
|
-
continue;
|
|
798
|
-
}
|
|
799
|
-
break;
|
|
800
|
-
}
|
|
801
|
-
if (i >= tokens.length)
|
|
802
|
-
continue;
|
|
803
|
-
const norm = (tok) => {
|
|
804
|
-
const t = stripTokenEdges(tok).replace(/^\\/, "");
|
|
805
|
-
return t.split("/").pop() ?? t;
|
|
806
|
-
};
|
|
807
|
-
let headIdx = i;
|
|
808
|
-
if (sawWrapper && !DELETE_HEADS.has(norm(tokens[headIdx]))) {
|
|
809
|
-
const found = tokens.findIndex((t, k) => k > headIdx && DELETE_HEADS.has(norm(t)));
|
|
810
|
-
if (found !== -1)
|
|
811
|
-
headIdx = found;
|
|
812
|
-
}
|
|
813
|
-
i = headIdx;
|
|
814
|
-
const head = stripTokenEdges(tokens[i]).replace(/^\\/, "");
|
|
815
|
-
const headName = head.split("/").pop() ?? head;
|
|
816
|
-
const declStmt = stmt.trim();
|
|
817
|
-
const declaredWords = /^(?:export|declare|typeset|local|readonly)\b/.test(declStmt) ? declStmt.split(/\s+/).filter(Boolean).slice(1) : ASSIGNMENT_PREFIX.test(declStmt) ? [declStmt] : [];
|
|
818
|
-
for (let d = 0; d < declaredWords.length;) {
|
|
819
|
-
if (/^[-+]/.test(declaredWords[d])) {
|
|
820
|
-
d += 1;
|
|
821
|
-
continue;
|
|
822
|
-
}
|
|
823
|
-
declaredWords[d] = stripTokenEdges(declaredWords[d]);
|
|
824
|
-
applyAssignmentWord(declaredWords, d);
|
|
825
|
-
d += assignmentTokenSpan(declaredWords, d);
|
|
826
|
-
}
|
|
827
|
-
if (headName === "read") {
|
|
828
|
-
void 0;
|
|
829
|
-
}
|
|
830
|
-
if (headName === "for" && tokens[i + 1] && tokens[i + 2] === "in") {
|
|
831
|
-
const list = tokens.slice(i + 3).join(" ");
|
|
832
|
-
if (!valueIsOpaque(list, assigned, safeVars))
|
|
833
|
-
assigned.add(tokens[i + 1]);
|
|
834
|
-
if (valueEscapesRoot(list, safeVars))
|
|
835
|
-
assignedEscapesRoot.add(tokens[i + 1]);
|
|
836
|
-
}
|
|
837
|
-
if (headName === "xargs") {
|
|
838
|
-
const rest = tokens.slice(i + 1).map(stripTokenEdges);
|
|
839
|
-
const rmAt = rest.findIndex((t) => (t.split("/").pop() ?? t) === "rm");
|
|
840
|
-
if (rmAt >= 0 && hasRecursiveForce(rest.slice(rmAt + 1))) {
|
|
841
|
-
return "`xargs rm` with recursive+force flags — the delete targets come from pipe output that cannot be verified";
|
|
842
|
-
}
|
|
843
|
-
continue;
|
|
844
|
-
}
|
|
845
|
-
if (/^remove-item$/i.test(headName) || /^ri$/i.test(headName)) {
|
|
846
|
-
const rest = tokens.slice(i + 1);
|
|
847
|
-
const recurse = rest.some((t) => /^-recurse$/i.test(t));
|
|
848
|
-
const force = rest.some((t) => /^-force$/i.test(t));
|
|
849
|
-
const varTarget = rest.find((t) => !t.startsWith("-") && t.includes("$"));
|
|
850
|
-
if (recurse && force && varTarget !== undefined) {
|
|
851
|
-
return `\`Remove-Item -Recurse -Force\` target ${varTarget} is a variable that cannot be verified from this command`;
|
|
852
|
-
}
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
if (headName !== "rm")
|
|
856
|
-
continue;
|
|
857
|
-
const rest = tokens.slice(i + 1);
|
|
858
|
-
if (!hasRecursiveForce(rest))
|
|
859
|
-
continue;
|
|
860
|
-
let optionsEnded = false;
|
|
861
|
-
for (const raw of rest) {
|
|
862
|
-
if (!optionsEnded && raw === "--") {
|
|
863
|
-
optionsEnded = true;
|
|
864
|
-
continue;
|
|
865
|
-
}
|
|
866
|
-
if (!optionsEnded && raw.startsWith("-"))
|
|
867
|
-
continue;
|
|
868
|
-
const target = raw.replace(/["']/g, "");
|
|
869
|
-
if (target.includes("$(") || target.includes("`")) {
|
|
870
|
-
return `\`rm\` recursive+force target ${raw} uses command substitution — the deleted path cannot be verified from this command`;
|
|
871
|
-
}
|
|
872
|
-
if (/\$[@*#!?0-9-]/.test(target)) {
|
|
873
|
-
return `\`rm\` recursive+force target ${raw} uses a positional/special shell parameter that cannot be verified from this command`;
|
|
874
|
-
}
|
|
875
|
-
if (/\$\{[!#]/.test(target)) {
|
|
876
|
-
return `\`rm\` recursive+force target ${raw} uses indirect/length expansion (\`\${!…}\`/\`\${#…}\`) — the deleted path cannot be verified from this command`;
|
|
877
|
-
}
|
|
878
|
-
const targetNorm = target.replace(/\\(.)/g, "$1");
|
|
879
|
-
for (const vm of targetNorm.matchAll(/\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g)) {
|
|
880
|
-
const name = vm[1];
|
|
881
|
-
if (assigned.has(name)) {
|
|
882
|
-
const afterName = targetNorm.slice((vm.index ?? 0) + vm[0].length);
|
|
883
|
-
if (afterName.split("/").includes("..")) {
|
|
884
|
-
return `\`rm\` recursive+force target ${raw} climbs above its in-window root via \`..\` — the deleted path cannot be verified from this command`;
|
|
885
|
-
}
|
|
886
|
-
if (!assignedEscapesRoot.has(name))
|
|
887
|
-
continue;
|
|
888
|
-
return `\`rm\` recursive+force target ${raw} resolves through ${name}, whose in-window value climbs above a known-safe root (\`..\`) — the deleted path cannot be verified from this command`;
|
|
889
|
-
}
|
|
890
|
-
if (safeVars.has(name)) {
|
|
891
|
-
if (safeRootBelow(targetNorm.slice((vm.index ?? 0) + vm[0].length)))
|
|
892
|
-
continue;
|
|
893
|
-
}
|
|
894
|
-
return `\`rm\` recursive+force target ${raw} references $${name}, which has no assignment in this command — an empty or unexpected value could make this a home-directory or filesystem-root wipe`;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
return undefined;
|
|
899
|
-
}
|
|
900
|
-
function hasRecursiveForce(argvTail) {
|
|
901
|
-
let recursive = false;
|
|
902
|
-
let force = false;
|
|
903
|
-
for (const raw of argvTail) {
|
|
904
|
-
const t = raw.replace(/^["']|["']$/g, "");
|
|
905
|
-
if (t === "--")
|
|
906
|
-
break;
|
|
907
|
-
if (!t.startsWith("-"))
|
|
908
|
-
continue;
|
|
909
|
-
if (t === "--recursive")
|
|
910
|
-
recursive = true;
|
|
911
|
-
else if (t === "--force")
|
|
912
|
-
force = true;
|
|
913
|
-
else if (/^-[A-Za-z]+$/.test(t)) {
|
|
914
|
-
if (/[rR]/.test(t))
|
|
915
|
-
recursive = true;
|
|
916
|
-
if (t.includes("f"))
|
|
917
|
-
force = true;
|
|
684
|
+
export function createUnverifiableDeletePolicy(opts) {
|
|
685
|
+
for (const name of opts?.safeVars ?? []) {
|
|
686
|
+
if (typeof name !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name))
|
|
687
|
+
throw new TypeError(`createUnverifiableDeletePolicy: safeVars entry ${JSON.stringify(name)} is not a shell variable name`);
|
|
688
|
+
if (name === "PWD" || name === "OLDPWD") {
|
|
689
|
+
const e = new Error(`createUnverifiableDeletePolicy: safeVars entry "${name}" is a reserved name — it is where the command stands, which the removal guard reads off the working-directory thread, not a root the shell provides. Drop the entry; to treat a fixed directory as a safe root, export it under a name of your own and list that name.`);
|
|
690
|
+
e.code = "config.safe_vars_reserved_name";
|
|
691
|
+
throw e;
|
|
918
692
|
}
|
|
919
693
|
}
|
|
920
|
-
|
|
921
|
-
}
|
|
922
|
-
export function createUnverifiableDeletePolicy(opts) {
|
|
923
|
-
const safeVars = new Set([...UNVERIFIABLE_DELETE_SAFE_VARS, ...(opts?.safeVars ?? [])]);
|
|
694
|
+
const safeRoots = [...new Set([...KNOWN_SAFE_ROOTS, ...(opts?.safeVars ?? [])])];
|
|
924
695
|
const shellTools = canonicalToolNameSet(opts?.tools);
|
|
925
|
-
const unverifiable = (command, finding = findUnverifiableRecursiveDelete(command, safeVars)) => (finding === undefined ? ALLOW : removalAsk("unverifiable_delete", finding));
|
|
926
696
|
return brandPolicyAskClass({
|
|
927
697
|
check(req, signal) {
|
|
928
698
|
if (!shellToolsListHolds(shellTools, req))
|
|
@@ -930,14 +700,18 @@ export function createUnverifiableDeletePolicy(opts) {
|
|
|
930
700
|
const command = req.args?.command;
|
|
931
701
|
if (typeof command !== "string")
|
|
932
702
|
return ALLOW;
|
|
933
|
-
const removal = removalReadingOf(command, req, opts?.removalSeat);
|
|
934
|
-
return removal === undefined ?
|
|
703
|
+
const removal = removalReadingOf(command, req, opts?.removalSeat, safeRoots);
|
|
704
|
+
return removal === undefined ? ALLOW : removal.judge(signal).then((found) => (found === undefined ? ALLOW : removalAsk(found.guard, found.text)));
|
|
935
705
|
},
|
|
936
706
|
}, "external_authority");
|
|
937
707
|
}
|
|
938
708
|
function removalAsk(guard, text) {
|
|
939
|
-
const
|
|
940
|
-
|
|
709
|
+
const messages = {
|
|
710
|
+
dangerous_delete: `Dangerous removal: ${text}. No permission mode, allow rule or classifier clears this — only a person confirming this call does.`,
|
|
711
|
+
unverifiable_delete: `Unverifiable recursive delete (fail-closed unless cleared): ${text}. Re-run the delete with the resolved literal path written into the command itself (or assign the variable a literal path in the same command, e.g. \`DIR=/exact/path; rm -rf "$DIR"\`) so the target can be verified.`,
|
|
712
|
+
unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}. Write the text into the command itself (a \`-c\` string, a here-document or a here-string) and the engine reads it as it reads any command.`,
|
|
713
|
+
};
|
|
714
|
+
return { action: "ask", decisionReason: "safety", requiresRealApproval: true, guard, message: messages[guard] };
|
|
941
715
|
}
|
|
942
716
|
function pathSegments(p) {
|
|
943
717
|
return p.split(/[\\/]/).filter(Boolean);
|
|
@@ -975,10 +749,12 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
975
749
|
const shellTools = canonicalToolNameSet(opts?.tools);
|
|
976
750
|
const dirSegs = dirs.map((d) => pathSegments(d).map(foldPathCase));
|
|
977
751
|
const inProtectedDir = (p, liveCwd) => {
|
|
978
|
-
const
|
|
979
|
-
const
|
|
752
|
+
const tree = liveCwd === undefined ? undefined : pathFamilyOf({ root: liveCwd });
|
|
753
|
+
const family = tree ?? "own";
|
|
754
|
+
const rawRelative = !isAbsoluteForFamily(family, p);
|
|
755
|
+
const abs = liveCwd !== undefined && tree !== undefined && rawRelative ? lexicalPath(normalizeAbsPathLexically(anchorSpelling(tree, liveCwd, p)), home) : lexicalPath(p, home);
|
|
980
756
|
const segs = pathSegments(abs).map(foldPathCase);
|
|
981
|
-
if (
|
|
757
|
+
if (isAbsoluteForFamily(family, abs) && dirSegs.some((d) => d.length <= segs.length && d.every((s, i) => s === segs[i])))
|
|
982
758
|
return true;
|
|
983
759
|
if (!rawRelative)
|
|
984
760
|
return false;
|
|
@@ -1118,16 +894,22 @@ function containsSharedMemory(v, seen = new Set()) {
|
|
|
1118
894
|
return true;
|
|
1119
895
|
return false;
|
|
1120
896
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
897
|
+
const USER_NOTE_AUTHORITY = "(user authority only: it cannot grant permissions or override system rules)";
|
|
898
|
+
export function humanRefusalSentence(subject, reason, delegatedChild) {
|
|
899
|
+
const note = decidersNote(reason);
|
|
900
|
+
if (delegatedChild) {
|
|
901
|
+
const fact = subject === "plan" ? "Your proposed plan was rejected; it was not executed." : "Permission for this tool use was denied; the call did NOT run.";
|
|
902
|
+
return note === undefined
|
|
903
|
+
? `${fact} Try a different approach or report the limitation to complete your task.`
|
|
904
|
+
: `${fact} The user's note on this rejection follows — treat it as the decider's guidance ${USER_NOTE_AUTHORITY}:\n${delimitUntrusted("reviewer note", note, REVIEWER_NOTE_MAX_BODY)}\nAdjust to the note if you can; otherwise try a different approach or report the limitation to complete your task.`;
|
|
1127
905
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
906
|
+
const fact = subject === "plan" ? "Your proposed plan was rejected by the user; it was not executed." : "The user doesn't want to proceed with this tool use; the call did NOT run.";
|
|
907
|
+
return note === undefined
|
|
908
|
+
? `${fact} STOP what you are doing and wait for the user to tell you how to proceed.`
|
|
909
|
+
: `${fact} The user's note on this rejection follows — treat it as the user's guidance ${USER_NOTE_AUTHORITY}:\n${delimitUntrusted("reviewer note", note, REVIEWER_NOTE_MAX_BODY)}\nIf the note does not tell you how to proceed, STOP what you are doing and wait for the user.`;
|
|
910
|
+
}
|
|
911
|
+
function humanRefusalMessage(req, reason) {
|
|
912
|
+
return `approval denied for "${req.toolName}": ${req.message}\n${humanRefusalSentence("tool use", reason, req.isDelegatedChild === true)}`;
|
|
1131
913
|
}
|
|
1132
914
|
export function policyRefusalMessage(toolName, askMessage, note) {
|
|
1133
915
|
const head = `approval required for "${toolName}" but this run has no interactive approval channel${askMessage !== undefined ? `: ${askMessage}` : ""}`;
|
|
@@ -1136,7 +918,8 @@ export function policyRefusalMessage(toolName, askMessage, note) {
|
|
|
1136
918
|
`was blocked and why you needed it, then continue with the parts of the task that do not require approval.`;
|
|
1137
919
|
return note === undefined ? body : `${body}\nPolicy note:\n${delimitUntrusted("policy note", note, REVIEWER_NOTE_MAX_BODY)}`;
|
|
1138
920
|
}
|
|
1139
|
-
const
|
|
921
|
+
export const BIDI_CONTROL_CHARS = "\\u061C\\u200E\\u200F\\u202A-\\u202E\\u2066-\\u2069";
|
|
922
|
+
const BIDI_CONTROL_RE = new RegExp(`[${BIDI_CONTROL_CHARS}]`, "u");
|
|
1140
923
|
const BIDI_SCAN_MAX_NODES = 5_000;
|
|
1141
924
|
const BIDI_SCAN_MAX_CHARS = 1_000_000;
|
|
1142
925
|
export function carriesBidiControls(value, limits) {
|
|
@@ -1209,10 +992,12 @@ export function carriesBidiControls(value, limits) {
|
|
|
1209
992
|
}
|
|
1210
993
|
}
|
|
1211
994
|
export async function resolveAsk(req, onAsk, signal, onLateSettlement) {
|
|
1212
|
-
const
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
995
|
+
const askedDigest = boundInputHashOf(req.args);
|
|
996
|
+
const { settlement, ...r } = await resolveAskArms(req, onAsk, signal, onLateSettlement);
|
|
997
|
+
if (settlement === undefined)
|
|
998
|
+
return r;
|
|
999
|
+
const licensedDigest = r.action === "allow" && r.updatedInput !== undefined ? boundInputHashOf(r.updatedInput) : r.presentedInput !== undefined ? boundInputHashOf(r.presentedInput) : askedDigest;
|
|
1000
|
+
return attest(r, req, { settlement, ...(req.origin !== undefined ? { origin: req.origin } : {}), ...(req.classes !== undefined ? { classes: req.classes } : {}), inputDigest: licensedDigest });
|
|
1216
1001
|
}
|
|
1217
1002
|
function raceAskWaitAgainstSignal(wait, signal) {
|
|
1218
1003
|
const settledWait = wait.then((value) => ({ tag: "value", value }), (error) => ({ tag: "threw", error }));
|