@sema-agent/core 7.55.0 → 7.57.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 +1054 -0
- package/LICENSE +1 -1
- package/dist/agents/cascade.js +1 -1
- package/dist/agents/cc-peer-directory.js +1 -0
- package/dist/agents/child-model-seat.d.ts +0 -11
- package/dist/agents/child-model-seat.js +0 -3
- package/dist/agents/list-agents-tool.d.ts +3 -1
- package/dist/agents/list-agents-tool.js +7 -7
- package/dist/agents/org-delivery-gate.js +3 -4
- package/dist/agents/peer-directory.d.ts +22 -4
- package/dist/agents/peer-directory.js +24 -2
- package/dist/agents/peer-held-queue.d.ts +69 -49
- package/dist/agents/peer-held-queue.js +255 -106
- package/dist/agents/peer-session-drain.js +65 -45
- package/dist/agents/repair-loop.js +2 -2
- package/dist/agents/send-message-tool.js +7 -6
- package/dist/agents/subagent.d.ts +6 -4
- package/dist/agents/subagent.js +72 -68
- package/dist/agents/tool-filter.d.ts +7 -5
- package/dist/agents/tool-filter.js +12 -9
- package/dist/agents/verify.d.ts +3 -2
- package/dist/agents/verify.js +3 -3
- package/dist/brain/anthropic.js +45 -80
- package/dist/brain/media-degrade.d.ts +18 -7
- package/dist/brain/media-degrade.js +13 -2
- package/dist/brain/model-capability.d.ts +37 -0
- package/dist/brain/model-capability.js +34 -0
- package/dist/brain/model-presets.d.ts +2 -8
- package/dist/brain/model-presets.js +1 -6
- package/dist/brain/open-responses.js +23 -34
- package/dist/brain/openai.js +25 -96
- package/dist/brain/provider-dialect.d.ts +3 -2
- package/dist/brain/provider-dialect.js +2 -2
- package/dist/brain/reasoning-request.d.ts +96 -0
- package/dist/brain/reasoning-request.js +174 -0
- package/dist/brain/reasoning.d.ts +11 -11
- package/dist/brain/reasoning.js +4 -3
- package/dist/brain/request-params.d.ts +13 -4
- package/dist/brain/request-params.js +21 -5
- package/dist/brain/status-sink.d.ts +20 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/brain/stream-engine.d.ts +9 -0
- package/dist/brain/stream-engine.js +24 -10
- package/dist/brain/stream-shared.d.ts +5 -4
- package/dist/brain/stream-shared.js +4 -4
- package/dist/core/a2a.d.ts +2 -1
- package/dist/core/a2a.js +19 -13
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/allow-entry.d.ts +23 -23
- package/dist/core/allow-entry.js +42 -46
- package/dist/core/allow-rule-shadow.d.ts +3 -3
- package/dist/core/approval-object.d.ts +21 -5
- package/dist/core/approval-object.js +44 -17
- package/dist/core/ask-origin.d.ts +66 -20
- package/dist/core/ask-origin.js +63 -23
- package/dist/core/ask-question.d.ts +51 -8
- package/dist/core/ask-question.js +3 -4
- package/dist/core/ask-unresolvable-notice.d.ts +8 -3
- package/dist/core/ask-unresolvable-notice.js +16 -2
- package/dist/core/auto-compaction.d.ts +71 -6
- package/dist/core/auto-compaction.js +42 -26
- package/dist/core/background-agent-store.d.ts +6 -2
- package/dist/core/background-agent-store.js +1 -1
- package/dist/core/checkpoint-generation.d.ts +53 -0
- package/dist/core/checkpoint-generation.js +35 -0
- package/dist/core/checkpoint-queries.d.ts +180 -0
- package/dist/core/checkpoint-queries.js +272 -0
- package/dist/core/checkpoint-requirements.d.ts +19 -1
- package/dist/core/checkpoint-requirements.js +6 -0
- package/dist/core/checkpoint-store.d.ts +105 -53
- package/dist/core/checkpoint-store.js +43 -20
- package/dist/core/cross-boundary-taint.d.ts +6 -5
- package/dist/core/cross-boundary-taint.js +5 -5
- package/dist/core/decision-receipt.d.ts +37 -3
- package/dist/core/decision-receipt.js +17 -17
- package/dist/core/delegation-not-started.d.ts +6 -0
- package/dist/core/delegation-not-started.js +17 -0
- package/dist/core/engine-attestation.d.ts +93 -0
- package/dist/core/engine-attestation.js +70 -0
- package/dist/core/engine-capabilities.d.ts +4 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +32 -12
- package/dist/core/engine-notice.js +6 -0
- package/dist/core/file-history-store.d.ts +104 -22
- package/dist/core/file-history-store.js +37 -19
- package/dist/core/gate-fold.d.ts +1 -1
- package/dist/core/gate-fold.js +22 -10
- package/dist/core/gate-lanes.js +73 -65
- package/dist/core/gate-outcome.d.ts +26 -5
- package/dist/core/gate-outcome.js +26 -0
- package/dist/core/governance-codes.d.ts +5 -1
- package/dist/core/governance-codes.js +6 -0
- package/dist/core/hooks.d.ts +19 -18
- package/dist/core/hooks.js +3 -1
- package/dist/core/host-floor.d.ts +128 -0
- package/dist/core/host-floor.js +206 -0
- package/dist/core/host-target.d.ts +38 -3
- package/dist/core/host-target.js +38 -5
- package/dist/core/mailbox-store.d.ts +62 -1
- package/dist/core/mailbox-store.js +59 -0
- package/dist/core/mcp-name-judge.d.ts +46 -0
- package/dist/core/mcp-name-judge.js +61 -0
- package/dist/core/mcp-probe.d.ts +1 -1
- package/dist/core/mcp-probe.js +2 -5
- package/dist/core/mcp.d.ts +5 -1
- package/dist/core/mcp.js +70 -64
- package/dist/core/memory-engine/consolidation-driver.js +4 -3
- package/dist/core/memory-engine/delegation-settlement.js +15 -24
- package/dist/core/memory-engine/distiller.js +26 -17
- package/dist/core/memory-engine/engine.js +4 -4
- package/dist/core/memory-engine/layout.d.ts +60 -8
- package/dist/core/memory-engine/layout.js +70 -8
- package/dist/core/model-seat.d.ts +10 -3
- package/dist/core/mods/classic-events.d.ts +67 -0
- package/dist/core/mods/classic-events.js +1 -0
- package/dist/core/mods/dollar.d.ts +13 -0
- package/dist/core/mods/extension-call.d.ts +31 -0
- package/dist/core/mods/extension-call.js +43 -0
- package/dist/core/mods/kernel/dispatch.d.ts +20 -3
- package/dist/core/mods/kernel/dispatch.js +140 -69
- package/dist/core/mods/kernel/events.d.ts +47 -11
- package/dist/core/mods/kernel/events.js +66 -42
- package/dist/core/mods/kernel/index.d.ts +4 -4
- package/dist/core/mods/kernel/index.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +39 -5
- package/dist/core/mods/kernel/receive.js +290 -17
- package/dist/core/mods/kernel/registration.d.ts +33 -2
- package/dist/core/mods/kernel/registration.js +6 -7
- package/dist/core/mods/kernel/site-rules.d.ts +44 -16
- package/dist/core/mods/kernel/site-rules.js +24 -42
- package/dist/core/mods/spec-seats.d.ts +69 -0
- package/dist/core/mods/spec-seats.js +114 -0
- package/dist/core/mods/stations.d.ts +28 -8
- package/dist/core/mods/stations.js +29 -13
- package/dist/core/mods/tool-call.d.ts +79 -0
- package/dist/core/mods/tool-call.js +152 -0
- package/dist/core/namespaced-rule-name.d.ts +32 -38
- package/dist/core/namespaced-rule-name.js +29 -36
- package/dist/core/parent-spec-seat.d.ts +6 -1
- package/dist/core/parent-spec-seat.js +2 -0
- package/dist/core/park-selfcheck.js +3 -0
- package/dist/core/permission-rule-consent.d.ts +24 -3
- package/dist/core/permission-rule-consent.js +136 -41
- package/dist/core/permission-rule-model.d.ts +57 -5
- package/dist/core/permission-rule-model.js +90 -31
- package/dist/core/permission-rule-org.d.ts +6 -2
- package/dist/core/permission-rule-org.js +8 -4
- package/dist/core/permission-rule-provider.d.ts +5 -2
- package/dist/core/permission-rule-provider.js +41 -11
- package/dist/core/permission-rule-store.d.ts +3 -2
- package/dist/core/permission-rule-store.js +11 -2
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rule-syntax.d.ts +5 -4
- package/dist/core/permission-rule-syntax.js +2 -2
- package/dist/core/permission-rules.d.ts +4 -4
- package/dist/core/permission-rules.js +11 -20
- package/dist/core/persisted-rule-arms.d.ts +2 -2
- package/dist/core/persisted-rule-arms.js +10 -12
- package/dist/core/principal-name.d.ts +20 -0
- package/dist/core/principal-name.js +22 -0
- package/dist/core/prompt-section-seat.js +4 -6
- package/dist/core/protocol-http-auth.d.ts +40 -5
- package/dist/core/protocol-http-auth.js +168 -4
- package/dist/core/protocol-naming.d.ts +20 -0
- package/dist/core/protocol-naming.js +20 -3
- package/dist/core/read-only-shell.d.ts +20 -5
- package/dist/core/read-only-shell.js +29 -14
- package/dist/core/remote-env.d.ts +37 -1
- package/dist/core/remote-env.js +11 -0
- package/dist/core/resume-startup-cause.d.ts +24 -2
- package/dist/core/resume-startup-cause.js +20 -1
- package/dist/core/retired-keys.d.ts +16 -0
- package/dist/core/retired-keys.js +16 -4
- package/dist/core/rewrite-rejudge.d.ts +60 -0
- package/dist/core/rewrite-rejudge.js +36 -0
- package/dist/core/roles.d.ts +28 -1
- package/dist/core/roles.js +81 -26
- package/dist/core/rule-lane-reads.d.ts +20 -15
- package/dist/core/rule-lane-reads.js +45 -17
- package/dist/core/rule-owner.d.ts +3 -3
- package/dist/core/rule-owner.js +3 -2
- package/dist/core/runner/announce-once-ledger.d.ts +14 -0
- package/dist/core/runner/announce-once-ledger.js +5 -0
- package/dist/core/runner/assemble-result.d.ts +1 -0
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/call-hook-stations.d.ts +3 -2
- package/dist/core/runner/caller-roster.d.ts +16 -4
- package/dist/core/runner/caller-roster.js +33 -6
- package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
- package/dist/core/runner/capability-withheld-seat.js +24 -0
- package/dist/core/runner/classifier-ladder.d.ts +7 -9
- package/dist/core/runner/classifier-ladder.js +3 -3
- package/dist/core/runner/compact-session.d.ts +10 -0
- package/dist/core/runner/compact-session.js +202 -0
- package/dist/core/runner/compaction-call-options.d.ts +2 -2
- package/dist/core/runner/compaction-seams.d.ts +21 -1
- package/dist/core/runner/compaction-seams.js +11 -8
- package/dist/core/runner/construction-doors.js +3 -0
- package/dist/core/runner/contracts.d.ts +50 -40
- package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
- package/dist/core/runner/cross-boundary-lane.js +40 -27
- package/dist/core/runner/denial-limit-arms.d.ts +2 -2
- package/dist/core/runner/denial-limit-arms.js +1 -1
- package/dist/core/runner/derived-route-fallback.d.ts +13 -0
- package/dist/core/runner/derived-route-fallback.js +6 -0
- package/dist/core/runner/env-capability-census.d.ts +3 -2
- package/dist/core/runner/env-capability-census.js +9 -3
- package/dist/core/runner/file-history-request.d.ts +18 -0
- package/dist/core/runner/file-history-request.js +21 -13
- package/dist/core/runner/file-history-restore.d.ts +45 -0
- package/dist/core/runner/file-history-restore.js +46 -0
- package/dist/core/runner/gate-exit.d.ts +3 -3
- package/dist/core/runner/gate-exit.js +4 -3
- package/dist/core/runner/image.d.ts +7 -17
- package/dist/core/runner/image.js +9 -60
- package/dist/core/runner/permission-rule-lanes.d.ts +11 -11
- package/dist/core/runner/permission-rule-lanes.js +39 -17
- package/dist/core/runner/person-path-rows.d.ts +12 -9
- package/dist/core/runner/person-path-rows.js +18 -7
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -0
- package/dist/core/runner/prepare-acquire-reconcile.js +2 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
- package/dist/core/runner/prepare-ask-lane.js +5 -2
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
- package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
- package/dist/core/runner/prepare-config-doors.d.ts +35 -38
- package/dist/core/runner/prepare-config-doors.js +46 -28
- package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
- package/dist/core/runner/prepare-defer-classify.js +7 -8
- package/dist/core/runner/prepare-file-history.d.ts +48 -8
- package/dist/core/runner/prepare-file-history.js +7 -39
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
- package/dist/core/runner/prepare-gate-stations.js +10 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +5 -9
- package/dist/core/runner/prepare-hands-readface.js +17 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
- package/dist/core/runner/prepare-inherited-gate.js +5 -3
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.d.ts +2 -0
- package/dist/core/runner/prepare-park-ask.js +7 -7
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
- package/dist/core/runner/prepare-policy-chain.js +67 -76
- package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
- package/dist/core/runner/prepare-prompt-assembly.js +10 -8
- package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
- package/dist/core/runner/prepare-prompt-inputs.js +3 -5
- package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
- package/dist/core/runner/prepare-protocol-tools.js +3 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
- package/dist/core/runner/prepare-safety-scan.js +0 -17
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -6
- package/dist/core/runner/prepare-task.d.ts +5 -2
- package/dist/core/runner/prepare-task.js +48 -43
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +20 -4
- package/dist/core/runner/prepare-tool-disclosure-mount.js +33 -23
- package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
- package/dist/core/runner/prepare-turn-wiring.js +2 -7
- package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
- package/dist/core/runner/prepare-wiring-manifest.js +3 -3
- package/dist/core/runner/resume-admission.js +1 -1
- package/dist/core/runner/resume-apply.js +11 -12
- package/dist/core/runner/resume-checkpoint-screen.js +3 -0
- package/dist/core/runner/resume-claim.d.ts +4 -2
- package/dist/core/runner/resume-claim.js +15 -8
- package/dist/core/runner/retired-runner-deps.js +1 -0
- package/dist/core/runner/rewind-files.d.ts +12 -0
- package/dist/core/runner/rewind-files.js +90 -0
- package/dist/core/runner/run-attachment-seats.js +2 -1
- package/dist/core/runner/run-brain-sinks.d.ts +4 -1
- package/dist/core/runner/run-brain-sinks.js +4 -2
- package/dist/core/runner/run-harness-handlers.js +12 -4
- package/dist/core/runner/run-leg.d.ts +1 -1
- package/dist/core/runner/run-leg.js +40 -39
- package/dist/core/runner/run-notification-lane.d.ts +2 -0
- package/dist/core/runner/run-notification-lane.js +2 -2
- package/dist/core/runner/run-recovery-lanes.js +3 -4
- package/dist/core/runner/run-settle-and-teardown.js +7 -12
- package/dist/core/runner/run-terminal-adoption.js +3 -4
- package/dist/core/runner/run-turn-boundary.js +4 -15
- package/dist/core/runner/runtask.d.ts +10 -0
- package/dist/core/runner/runtask.js +35 -42
- package/dist/core/runner/send-message-continuation.js +1 -1
- package/dist/core/runner/session-read-file-states.d.ts +15 -0
- package/dist/core/runner/session-read-file-states.js +28 -0
- package/dist/core/runner/session-rule-policy.js +4 -3
- package/dist/core/runner/session-verb-doors.d.ts +28 -0
- package/dist/core/runner/session-verb-doors.js +48 -0
- package/dist/core/runner/session-write-ledger.d.ts +30 -0
- package/dist/core/runner/session-write-ledger.js +101 -0
- package/dist/core/runner/shell-env-withheld.d.ts +33 -0
- package/dist/core/runner/shell-env-withheld.js +51 -0
- package/dist/core/runner/skills-seat.js +6 -2
- package/dist/core/runner/stream-settle-backstop.js +12 -15
- package/dist/core/runner/sub-agent-deny-lists.d.ts +25 -3
- package/dist/core/runner/sub-agent-deny-lists.js +25 -17
- package/dist/core/runner/synthetic-tools.d.ts +6 -0
- package/dist/core/runner/synthetic-tools.js +4 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -0
- package/dist/core/runner/teardown-bounded.js +1 -0
- package/dist/core/runner/tool-disclosure.d.ts +10 -12
- package/dist/core/runner/tool-disclosure.js +1 -3
- package/dist/core/runner/tool-end-body.d.ts +1 -1
- package/dist/core/runner/tool-end-body.js +10 -9
- package/dist/core/runner/tool-not-executed.d.ts +5 -0
- package/dist/core/runner/tool-not-executed.js +11 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -0
- package/dist/core/runner/tool-occurrence.js +7 -0
- package/dist/core/runner/turn-attachments.d.ts +33 -15
- package/dist/core/runner/turn-attachments.js +62 -37
- package/dist/core/runner-deps.d.ts +7 -7
- package/dist/core/safety-axis-vocab.d.ts +6 -4
- package/dist/core/safety-axis-vocab.js +6 -5
- package/dist/core/safety-merge-corpus.js +11 -3
- package/dist/core/secret-env.d.ts +30 -3
- package/dist/core/secret-env.js +47 -8
- package/dist/core/select-model.js +3 -3
- package/dist/core/session-policy-store.d.ts +32 -15
- package/dist/core/session-policy-store.js +156 -36
- package/dist/core/session-store.d.ts +29 -10
- package/dist/core/session-store.js +51 -19
- package/dist/core/session.d.ts +82 -16
- package/dist/core/session.js +53 -0
- package/dist/core/shell-read-silence.d.ts +11 -12
- package/dist/core/shell-read-silence.js +9 -5
- package/dist/core/shell-run-candidates.js +3 -1
- package/dist/core/shell-wrapper-projection.d.ts +1 -1
- package/dist/core/shell-wrapper-projection.js +1 -1
- package/dist/core/shell-wrapper-table.d.ts +14 -7
- package/dist/core/shell-wrapper-table.js +5 -4
- package/dist/core/side-query.js +10 -1
- package/dist/core/skill-grant.d.ts +7 -2
- package/dist/core/skill-grant.js +5 -0
- package/dist/core/skills-directory.js +6 -2
- package/dist/core/store-contracts/background-agent-store-contract.js +1 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +141 -2
- package/dist/core/store-contracts/file-history-store-contract.js +40 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +49 -1
- package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
- package/dist/core/store-contracts/peer-directory-contract.js +14 -2
- package/dist/core/store-contracts/session-repo-contract.js +51 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
- package/dist/core/store-contracts/session-store-contract.js +150 -14
- package/dist/core/stub-env.d.ts +2 -0
- package/dist/core/stub-env.js +1 -0
- package/dist/core/synthetic-read-verdict.js +3 -3
- package/dist/core/task-event.d.ts +32 -4
- package/dist/core/task-notification.d.ts +16 -12
- package/dist/core/task-registry-agent.d.ts +8 -4
- package/dist/core/task-registry-agent.js +14 -8
- package/dist/core/task-registry-shared.d.ts +35 -6
- package/dist/core/task-registry-shared.js +11 -0
- package/dist/core/task-registry.d.ts +10 -1
- package/dist/core/task-registry.js +12 -2
- package/dist/core/task-result.d.ts +18 -0
- package/dist/core/task-spec.d.ts +18 -13
- package/dist/core/tighten-task-spec.js +2 -1
- package/dist/core/tool-catalog-entries.d.ts +23 -0
- package/dist/core/tool-catalog-entries.js +14 -2
- package/dist/core/tool-check-reading.d.ts +11 -0
- package/dist/core/tool-check-reading.js +11 -6
- package/dist/core/tool-model-gate.d.ts +2 -2
- package/dist/core/tool-name-aliases.d.ts +48 -18
- package/dist/core/tool-name-aliases.js +36 -19
- package/dist/core/tool-name-readings.d.ts +6 -32
- package/dist/core/tool-name-readings.js +2 -9
- package/dist/core/tool-policy.d.ts +78 -204
- package/dist/core/tool-policy.js +152 -204
- package/dist/core/tool-result-store.js +3 -0
- package/dist/core/tool-roster.d.ts +14 -19
- package/dist/core/tool-roster.js +11 -44
- package/dist/core/tool-spec-members.js +7 -2
- package/dist/core/tool-spec.d.ts +19 -11
- package/dist/core/tools.js +49 -9
- package/dist/core/trace.d.ts +6 -3
- package/dist/core/trace.js +2 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/untrusted-egress.d.ts +20 -0
- package/dist/core/untrusted-egress.js +77 -3
- package/dist/core/user-attachment.d.ts +8 -1
- package/dist/core/user-attachment.js +64 -4
- package/dist/core/wiring-manifest.d.ts +9 -0
- package/dist/core/wiring-manifest.js +1 -0
- package/dist/core/workflow-journal-store.js +1 -1
- package/dist/engine/compaction/compaction.js +3 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
- package/dist/engine/execution-env/node-execution-env.js +11 -2
- package/dist/engine/harness/agent-harness.d.ts +32 -6
- package/dist/engine/harness/agent-harness.js +65 -9
- package/dist/engine/harness/types.d.ts +29 -2
- package/dist/engine/llm/types.d.ts +28 -11
- package/dist/engine/loop/agent-loop.d.ts +23 -4
- package/dist/engine/loop/agent-loop.js +42 -30
- package/dist/engine/loop/types.d.ts +16 -6
- package/dist/engine/session/memory-repo.d.ts +9 -2
- package/dist/engine/session/memory-repo.js +11 -1
- package/dist/engine/session/repo-utils.d.ts +6 -5
- package/dist/engine/session/repo-utils.js +14 -6
- package/dist/index.d.ts +34 -17
- package/dist/index.js +22 -11
- package/dist/internal/harness-types.d.ts +1 -1
- package/dist/internal/harness.d.ts +2 -1
- package/dist/internal/harness.js +1 -0
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +6 -4
- package/dist/orchestration/run-workflow-tool.js +5 -3
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +36 -18
- package/dist/primitives/credential-ref.d.ts +89 -0
- package/dist/primitives/credential-ref.js +125 -0
- package/dist/primitives/index.d.ts +2 -0
- package/dist/primitives/index.js +1 -0
- package/dist/prompt-assembly/artifact.d.ts +2 -2
- package/dist/prompt-assembly/artifact.js +5 -3
- package/dist/prompt-assembly/assemble.d.ts +3 -2
- package/dist/prompt-assembly/assemble.js +1 -1
- package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
- package/dist/prompt-assembly/catalog/schema.js +34 -2
- package/dist/prompt-assembly/catalog/sections.js +0 -1
- package/dist/prompt-assembly/composer.d.ts +3 -1
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/event-registry.js +1 -0
- package/dist/prompt-assembly/overlay.js +3 -3
- package/dist/prompt-assembly/renderers.d.ts +1 -1
- package/dist/prompt-assembly/renderers.js +0 -3
- package/dist/prompt-assembly/role-base.d.ts +15 -0
- package/dist/prompt-assembly/role-base.js +9 -0
- package/dist/prompt-assembly/select.d.ts +39 -14
- package/dist/prompt-assembly/select.js +47 -16
- package/dist/prompt-assembly/sugar.d.ts +17 -11
- package/dist/prompt-assembly/sugar.js +8 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
- package/dist/prompt-assembly/tool-catalog.js +114 -4
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
- package/dist/prompt-assembly/turn-snapshot.js +0 -3
- package/dist/prompt-assembly/types.d.ts +0 -7
- package/dist/scenarios/full-body.d.ts +11 -11
- package/dist/scenarios/full-body.js +4 -3
- package/dist/shell/lex.js +10 -1
- package/dist/stores/file/adoption/adopt.js +4 -3
- package/dist/stores/file/adoption/marker.js +3 -2
- package/dist/stores/file/checkpoint-store.d.ts +21 -4
- package/dist/stores/file/checkpoint-store.js +38 -7
- package/dist/stores/file/file-history-store.js +18 -11
- package/dist/stores/file/index.js +2 -1
- package/dist/stores/file/mailbox-store.d.ts +2 -1
- package/dist/stores/file/mailbox-store.js +26 -1
- package/dist/stores/file/permission-rule-adopt.js +4 -3
- package/dist/stores/file/permission-rule-store.js +11 -5
- package/dist/stores/file/session-store.d.ts +29 -6
- package/dist/stores/file/session-store.js +42 -50
- package/dist/tools/artifact/artifact-tool.js +3 -2
- package/dist/tools/fs/bash-program-position.d.ts +19 -2
- package/dist/tools/fs/bash-program-position.js +56 -9
- package/dist/tools/fs/bash-readonly-classifier.d.ts +15 -19
- package/dist/tools/fs/bash-readonly-classifier.js +5 -10
- package/dist/tools/fs/fs-bash.js +15 -8
- package/dist/tools/fs/fs-glob.d.ts +86 -0
- package/dist/tools/fs/fs-glob.js +226 -0
- package/dist/tools/fs/fs-read.js +14 -14
- package/dist/tools/fs/fs-search-tools.js +7 -7
- package/dist/tools/fs/pattern-kill-guard.d.ts +23 -0
- package/dist/tools/fs/pattern-kill-guard.js +429 -0
- package/dist/tools/fs/pdf.d.ts +9 -6
- package/dist/tools/fs/pdf.js +3 -3
- package/dist/tools/fs/program-read-model.d.ts +57 -7
- package/dist/tools/fs/program-read-model.js +11 -1
- package/dist/tools/fs/program-read-model.rows.js +78 -21
- package/dist/tools/fs/read-deny-home.js +3 -2
- package/dist/tools/fs/removal-targets.d.ts +17 -7
- package/dist/tools/fs/removal-targets.js +47 -20
- package/dist/tools/fs/search.d.ts +10 -0
- package/dist/tools/fs/search.js +20 -26
- package/dist/tools/fs/shell-read-argv.js +89 -12
- package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
- package/dist/tools/fs/shell-read-bindings.js +41 -0
- package/dist/tools/fs/shell-read-check.d.ts +10 -0
- package/dist/tools/fs/shell-read-check.js +13 -20
- package/dist/tools/fs/shell-read-environment.d.ts +5 -1
- package/dist/tools/fs/shell-read-environment.js +3 -2
- package/dist/tools/fs/shell-read-establish.d.ts +15 -0
- package/dist/tools/fs/shell-read-establish.js +19 -20
- package/dist/tools/fs/shell-read-identity.d.ts +12 -9
- package/dist/tools/fs/shell-read-identity.js +9 -4
- package/dist/tools/fs/shell-read-plan.js +24 -16
- package/dist/tools/fs/shell-read-start.d.ts +6 -1
- package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
- package/dist/tools/fs/shell-read-write-targets.js +2 -3
- package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
- package/dist/tools/fs/shell-reentry-text.js +40 -2
- package/dist/tools/todo.js +63 -63
- package/dist/tools/web.d.ts +19 -14
- package/dist/tools/web.js +46 -61
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +221 -7
- package/wire-changes/core-stores-sql@7.57.0.json +29 -0
- package/wire-changes/core@7.56.0.json +3891 -0
- package/wire-changes/core@7.57.0.json +1487 -0
- package/wire-changes/mods-kernel@7.56.0.json +303 -0
- package/wire-changes/mods-kernel@7.57.0.json +29 -0
- package/wire-changes/primitives@7.57.0.json +245 -0
package/dist/core/tool-policy.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { argsReadFrom, carryArgsReadFrom, withArgsReading } from "./effective-path-target.js";
|
|
4
|
+
import { editRewrittenSentence, readRejudge, rewriteChasedSentence } from "./rewrite-rejudge.js";
|
|
4
5
|
import { brandPolicyAskClass } from "./ask-class.js";
|
|
5
6
|
import { decisionAskClassesOf, headlessDenialMessage } from "./ask-origin.js";
|
|
7
|
+
import { attest, attestationOf, isEngineAttestation, mergeAttestation, mintAttestation, withAttestation } from "./engine-attestation.js";
|
|
6
8
|
import { ownReadRootCandidate, readRootGrantSeat } from "./read-root-grant-screen.js";
|
|
7
9
|
import { decidersNote, settledByDecider } from "./gate-outcome.js";
|
|
8
10
|
import { unjudgedAllowRefused } from "./real-approval.js";
|
|
@@ -10,6 +12,7 @@ export { policyCannotAnswer, rowDemandsAPerson } from "./real-approval.js";
|
|
|
10
12
|
import { sanitizeAutoModeArmingRecipe } from "./auto-mode-arming.js";
|
|
11
13
|
import { join, normalize as normalizePath, sep } from "node:path";
|
|
12
14
|
import { BASH_READONLY_DEFAULT_ALLOW, parseLeadingCommandName } from "../tools/fs/index.js";
|
|
15
|
+
import { readOnlyShellVerdict } from "./read-only-shell.js";
|
|
13
16
|
import { protectivePathTargetOf, shellFaceToolNames } from "./tool-registry.js";
|
|
14
17
|
import { heldBy } from "./tool-name-readings.js";
|
|
15
18
|
import { bindableValueOf, boundInputHashOf, describeBindingFault, exactBoundInputHashOf } from "./canonical-json.js";
|
|
@@ -19,9 +22,9 @@ import { egressText, egressThrownText } from "./untrusted-egress.js";
|
|
|
19
22
|
import { assertNoRetiredKeys, assertNoRetiredToolPolicyKeys, RETIRED_DECISION_MEMBERS, RETIRED_TOOL_POLICY_KEYS } from "./retired-keys.js";
|
|
20
23
|
import { DECISION_MEMBER_ARMS, isEngineRefusal, nestedRecordsOf, receiveContract, receiveNestedRecords, refusedOutOfContract, screenContractValues } from "./decision-receipt.js";
|
|
21
24
|
export { isEngineRefusal } from "./decision-receipt.js";
|
|
22
|
-
import {
|
|
25
|
+
import { isCoveringRuleName, ruleNameCovers } from "./namespaced-rule-name.js";
|
|
23
26
|
import { ruleContentOf } from "./permission-rule-model.js";
|
|
24
|
-
import {
|
|
27
|
+
import { grantWildcardRefusalOf } from "./tool-name-aliases.js";
|
|
25
28
|
import { ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
26
29
|
import { protocolOf } from "./protocol-table.js";
|
|
27
30
|
import { anchorSpelling, isAbsoluteForFamily, normalizeAbsPathLexically, pathFamilyOf, writeTargetPath } from "../tools/fs/safety.js";
|
|
@@ -37,75 +40,7 @@ export function exemptRootsSeat(exemptRoots) {
|
|
|
37
40
|
function settledByNobody(kind) {
|
|
38
41
|
return { kind, who: { party: "none" }, when: Date.now() };
|
|
39
42
|
}
|
|
40
|
-
|
|
41
|
-
settlement: "answer",
|
|
42
|
-
origin: "answer",
|
|
43
|
-
classes: "answer",
|
|
44
|
-
inputDigest: "answer",
|
|
45
|
-
classifierCause: "classifierCause",
|
|
46
|
-
classifierRound: "classifierRound",
|
|
47
|
-
unresolvableCause: "unresolvableCause",
|
|
48
|
-
foldedClasses: "foldedClasses",
|
|
49
|
-
pathDenial: "pathDenial",
|
|
50
|
-
bindingRefusal: "bindingRefusal",
|
|
51
|
-
};
|
|
52
|
-
const ATTESTATION_MEMBERS = Object.keys(ATTESTATION_GROUP_OF);
|
|
53
|
-
const groupLead = (g) => ATTESTATION_MEMBERS.find((k) => ATTESTATION_GROUP_OF[k] === g);
|
|
54
|
-
const ENGINE_ATTESTATIONS = new WeakSet();
|
|
55
|
-
function detachedMember(v) {
|
|
56
|
-
if (Array.isArray(v))
|
|
57
|
-
return Object.freeze([...v]);
|
|
58
|
-
if (typeof v !== "object" || v === null)
|
|
59
|
-
return v;
|
|
60
|
-
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])));
|
|
61
|
-
}
|
|
62
|
-
export function mintAttestation(call, members) {
|
|
63
|
-
const record = { toolCallId: call.toolCallId, toolName: call.toolName };
|
|
64
|
-
for (const k of ATTESTATION_MEMBERS)
|
|
65
|
-
if (members[k] !== undefined)
|
|
66
|
-
record[k] = detachedMember(members[k]);
|
|
67
|
-
const minted = Object.freeze(record);
|
|
68
|
-
ENGINE_ATTESTATIONS.add(minted);
|
|
69
|
-
return minted;
|
|
70
|
-
}
|
|
71
|
-
export function isEngineAttestation(v) {
|
|
72
|
-
return typeof v === "object" && v !== null && ENGINE_ATTESTATIONS.has(v);
|
|
73
|
-
}
|
|
74
|
-
const boundTo = (r, call) => isEngineAttestation(r) && r.toolCallId === call.toolCallId && r.toolName === call.toolName ? r : undefined;
|
|
75
|
-
export function attestationOf(d, call) {
|
|
76
|
-
if (typeof d !== "object" || d === null)
|
|
77
|
-
return undefined;
|
|
78
|
-
return boundTo(Object.getOwnPropertyDescriptor(d, "attestation")?.value, call);
|
|
79
|
-
}
|
|
80
|
-
export function mergeAttestation(call, earlier, later, scope = "all") {
|
|
81
|
-
const a = boundTo(earlier, call);
|
|
82
|
-
const b = boundTo(later, call);
|
|
83
|
-
if (a === undefined)
|
|
84
|
-
return b;
|
|
85
|
-
const members = {};
|
|
86
|
-
if (b !== undefined)
|
|
87
|
-
for (const k of ATTESTATION_MEMBERS)
|
|
88
|
-
if (b[k] !== undefined)
|
|
89
|
-
members[k] = b[k];
|
|
90
|
-
let filled = false;
|
|
91
|
-
for (const g of new Set(Object.values(ATTESTATION_GROUP_OF))) {
|
|
92
|
-
if ((scope === "answer" && g !== "answer") || members[groupLead(g)] !== undefined || a[groupLead(g)] === undefined)
|
|
93
|
-
continue;
|
|
94
|
-
for (const k of ATTESTATION_MEMBERS)
|
|
95
|
-
if (ATTESTATION_GROUP_OF[k] === g && a[k] !== undefined)
|
|
96
|
-
members[k] = a[k];
|
|
97
|
-
filled = true;
|
|
98
|
-
}
|
|
99
|
-
if (!filled)
|
|
100
|
-
return b;
|
|
101
|
-
return mintAttestation(call, members);
|
|
102
|
-
}
|
|
103
|
-
export function attest(d, call, members) {
|
|
104
|
-
return withAttestation(d, mergeAttestation(call, attestationOf(d, call), mintAttestation(call, members)));
|
|
105
|
-
}
|
|
106
|
-
export function withAttestation(d, record) {
|
|
107
|
-
return record === undefined ? d : { ...d, attestation: record };
|
|
108
|
-
}
|
|
43
|
+
export { attest, attestationOf, isEngineAttestation, mergeAttestation, mintAttestation, withAttestation } from "./engine-attestation.js";
|
|
109
44
|
const UNASKED_SEAT_SETTLEMENTS = new Set(["task_aborted", "no_approver"]);
|
|
110
45
|
function seatNeverAsked(settlement) {
|
|
111
46
|
return settlement !== undefined && UNASKED_SEAT_SETTLEMENTS.has(settlement.kind);
|
|
@@ -196,21 +131,11 @@ export function toolPolicyWriteGuardRows(policies) {
|
|
|
196
131
|
return undefined;
|
|
197
132
|
return async (at) => (await Promise.all(sources.map((rowsOf) => rowsOf(at)))).flat();
|
|
198
133
|
}
|
|
199
|
-
export function
|
|
200
|
-
return (entries ?? []).filter((entry) =>
|
|
134
|
+
export function coveringRuleEntries(entries, behavior) {
|
|
135
|
+
return (entries ?? []).filter((entry) => isCoveringRuleName(entry, behavior));
|
|
201
136
|
}
|
|
202
|
-
function
|
|
203
|
-
|
|
204
|
-
return undefined;
|
|
205
|
-
const sentence = wildcardPeerRefusalOf(ruleSpellingOf(entry)?.toolName ?? entry, "allow");
|
|
206
|
-
if (sentence === undefined)
|
|
207
|
-
return undefined;
|
|
208
|
-
const e = new Error(`${who}: ${list} entry "${entry}" — ${sentence}`);
|
|
209
|
-
e.code = "config.invalid_tool_name_set";
|
|
210
|
-
return e;
|
|
211
|
-
}
|
|
212
|
-
export function namespacedCoveringHit(covering, call) {
|
|
213
|
-
return covering.length > 0 && nameListHolds({ has: (name) => covering.some((e) => namespacedRuleNameCovers(e, name)) }, call);
|
|
137
|
+
export function coveringRuleHit(covering, call) {
|
|
138
|
+
return covering.length > 0 && nameListHolds({ has: (name) => covering.some((e) => ruleNameCovers(e, name)) }, call);
|
|
214
139
|
}
|
|
215
140
|
export function projectionToolNames(c) {
|
|
216
141
|
return c.kind === "shell_command" ? { member: "tools", list: c.tools } : { member: "names", list: c.names };
|
|
@@ -219,13 +144,13 @@ export function checkToolPolicyProjection(projection, req) {
|
|
|
219
144
|
const listed = (list) => heldBy("policy.projectionReplay", { has: (n) => list.includes(n) }, req);
|
|
220
145
|
for (const c of projection.components) {
|
|
221
146
|
if (c.kind === "tool_deny") {
|
|
222
|
-
if (listed(c.names) ||
|
|
147
|
+
if (listed(c.names) || coveringRuleHit(coveringRuleEntries(c.names, "deny"), req)) {
|
|
223
148
|
return { action: "deny", message: `tool "${req.toolName}" is denied by a frozen inherited policy projection` };
|
|
224
149
|
}
|
|
225
150
|
continue;
|
|
226
151
|
}
|
|
227
152
|
if (c.kind === "tool_allowlist") {
|
|
228
|
-
if (!listed(c.names) && !
|
|
153
|
+
if (!listed(c.names) && !coveringRuleHit(coveringRuleEntries(c.names, "allow"), req)) {
|
|
229
154
|
return { action: "deny", message: `tool "${req.toolName}" is not in a frozen inherited policy projection's allowlist` };
|
|
230
155
|
}
|
|
231
156
|
continue;
|
|
@@ -300,6 +225,12 @@ const HOOK_SEAM_UNREAD = new Set(["decisionReason"]);
|
|
|
300
225
|
const HOOK_SEAM_OPTIONAL = new Set(["action"]);
|
|
301
226
|
const HOOK_RECEIPTS = new WeakSet();
|
|
302
227
|
const ENGINE_RECEIPTS = new WeakSet();
|
|
228
|
+
function askOfAnotherCall(d, call) {
|
|
229
|
+
if (call === undefined || d.action !== "ask" || d.attestation === undefined || attestationOf(d, call) !== undefined)
|
|
230
|
+
return undefined;
|
|
231
|
+
return refusedOutOfContract(`a permission decision asks with the engine's record of another call — what the engine found about that call's question is not this call's; ` +
|
|
232
|
+
`a policy answers the call it is asked about (a cached or relayed ask is asked again); denied fail-closed rather than reading the findings as absent`);
|
|
233
|
+
}
|
|
303
234
|
export function refuseOutOfContractDecision(d, opts) {
|
|
304
235
|
const hookSeam = opts?.reasonIsNonInput === true;
|
|
305
236
|
if (hookSeam && (d === null || d === undefined || Object.is(d, false)))
|
|
@@ -308,7 +239,7 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
308
239
|
return refusedOutOfContract(`a permission decision's "action" is absent (the decision is ${d === null || d === undefined ? String(d) : `a ${typeof d}`}, not an object) — the closed set is allow/deny/ask; denied fail-closed rather than reading a word outside it as an allow`);
|
|
309
240
|
}
|
|
310
241
|
if ((hookSeam ? HOOK_RECEIPTS : ENGINE_RECEIPTS).has(d) || isEngineRefusal(d))
|
|
311
|
-
return d;
|
|
242
|
+
return askOfAnotherCall(d, opts?.call) ?? d;
|
|
312
243
|
const decision = receiveContract(d, hookSeam ? HOOK_RESULT_MEMBERS : DECISION_MEMBERS, "", RETIRED_DECISION_MEMBERS);
|
|
313
244
|
if (decision.kind === "refused")
|
|
314
245
|
return decision.refused;
|
|
@@ -323,13 +254,9 @@ export function refuseOutOfContractDecision(d, opts) {
|
|
|
323
254
|
: `a permission decision carries an "attestation" the engine did not mint — the member is an engine record (who settled the call, ` +
|
|
324
255
|
`which question it answered); denied fail-closed rather than reading a caller's value as a settlement`);
|
|
325
256
|
}
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return refusedOutOfContract(`a permission decision carries "foldedAskClasses" that no policy fold of the engine attested on it — the member is ` +
|
|
330
|
-
`engine-written (combinePolicies records the classes of the asks it collapsed); denied fail-closed rather than letting a ` +
|
|
331
|
-
`class no station judged reach the class derivation`);
|
|
332
|
-
}
|
|
257
|
+
const foreign = askOfAnotherCall({ action: contract.action, attestation }, opts?.call);
|
|
258
|
+
if (foreign !== undefined)
|
|
259
|
+
return foreign;
|
|
333
260
|
if (hookSeam && contract.additionalContext !== undefined && typeof contract.additionalContext !== "string") {
|
|
334
261
|
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`);
|
|
335
262
|
}
|
|
@@ -387,86 +314,75 @@ export function toolPolicyNameSets(p) {
|
|
|
387
314
|
const sets = p?.nameSets;
|
|
388
315
|
return Array.isArray(sets) ? sets : [];
|
|
389
316
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
const malformed = suffix.length === 0 || sep === 0 || (sep > 0 && suffix.length === sep + 2);
|
|
404
|
-
if (malformed) {
|
|
405
|
-
const family = ns.id.toUpperCase();
|
|
406
|
-
const lesson = `a malformed ${family} tool name (empty peer or tool segment) — it can never match any mounted tool. ` +
|
|
407
|
-
`Use \`${ns.prefix}<peer>\` for every tool of a peer, or \`${ns.prefix}<peer>__<tool>\` for one tool.`;
|
|
408
|
-
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
const spelled = ruleSpellingOf(entry);
|
|
413
|
-
if (spelled === undefined) {
|
|
414
|
-
const lesson = `a spelling no tool name can have — the rule syntax reads no tool name in it, so a name set never names a tool by it. Fix the entry.`;
|
|
317
|
+
function screenToolNameList(entries, list, behavior, invalid) {
|
|
318
|
+
if (entries === undefined)
|
|
319
|
+
return undefined;
|
|
320
|
+
const kept = [];
|
|
321
|
+
const seen = new Set();
|
|
322
|
+
for (const entry of entries) {
|
|
323
|
+
const ns = protocolOf(entry);
|
|
324
|
+
if (ns !== undefined) {
|
|
325
|
+
const suffix = entry.slice(ns.prefix.length);
|
|
326
|
+
const sep = suffix.indexOf("__");
|
|
327
|
+
if (suffix.length === 0 || sep === 0 || (sep > 0 && suffix.length === sep + 2)) {
|
|
328
|
+
const lesson = `a malformed ${ns.id.toUpperCase()} tool name (empty peer or tool segment) — it can never match any mounted tool. ` +
|
|
329
|
+
`Use \`${ns.prefix}<peer>\` for every tool of a peer, or \`${ns.prefix}<peer>__<tool>\` for one tool.`;
|
|
415
330
|
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
416
331
|
continue;
|
|
417
332
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if (wild !== undefined) {
|
|
427
|
-
invalid.push({ entry, list, message: `"${entry}": ${wild}`, lesson: wild });
|
|
428
|
-
continue;
|
|
429
|
-
}
|
|
430
|
-
if (!seen.has(spelled.toolName)) {
|
|
431
|
-
seen.add(spelled.toolName);
|
|
432
|
-
kept.push(spelled.toolName);
|
|
433
|
-
}
|
|
434
|
-
continue;
|
|
435
|
-
}
|
|
333
|
+
}
|
|
334
|
+
const spelled = ruleSpellingOf(entry);
|
|
335
|
+
if (spelled === undefined) {
|
|
336
|
+
const lesson = `a spelling no tool name can have — the rule syntax reads no tool name in it, so a name set never names a tool by it. Fix the entry.`;
|
|
337
|
+
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
if (ruleContentOf(spelled) !== undefined) {
|
|
436
341
|
const lesson = `a rule CONTENT form, not a tool name — a name set matches raw tool names, so this entry ` +
|
|
437
342
|
`can never match any mounted tool (in an allow list it removes the tool entirely). Use the tool NAME here, ` +
|
|
438
343
|
`and route the narrowing through the lane that speaks this grammar: parameter rules via ` +
|
|
439
344
|
`createPermissionRulePolicy, Bash command prefixes via the persisted allow-rule lane.`;
|
|
440
345
|
invalid.push({ entry, list, message: `"${entry}" is ${lesson}`, lesson });
|
|
346
|
+
continue;
|
|
441
347
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
if (invalid.length > 0) {
|
|
447
|
-
if ((opts.onInvalidName ?? "throw") === "throw") {
|
|
448
|
-
const byLesson = new Map();
|
|
449
|
-
for (const i of invalid) {
|
|
450
|
-
const group = byLesson.get(i.lesson) ?? [];
|
|
451
|
-
group.push({ entry: i.entry, list: i.list });
|
|
452
|
-
byLesson.set(i.lesson, group);
|
|
453
|
-
}
|
|
454
|
-
const e = new Error(`createAllowDenyPolicy: ${invalid.length} entr${invalid.length === 1 ? "y is" : "ies are"} not tool name(s):\n` +
|
|
455
|
-
[...byLesson.entries()]
|
|
456
|
-
.map(([lesson, group]) => ` Each of the following is ${lesson}\n` + group.map((g) => ` [${g.list}] "${g.entry}"`).join("\n"))
|
|
457
|
-
.join("\n"));
|
|
458
|
-
e.code = "config.invalid_tool_name_set";
|
|
459
|
-
e.issues = invalid;
|
|
460
|
-
throw e;
|
|
348
|
+
const wild = behavior === "allow" ? grantWildcardRefusalOf(spelled.toolName) : undefined;
|
|
349
|
+
if (wild !== undefined) {
|
|
350
|
+
invalid.push({ entry, list, message: `"${entry}": ${wild}`, lesson: wild });
|
|
351
|
+
continue;
|
|
461
352
|
}
|
|
353
|
+
if (!seen.has(spelled.toolName)) {
|
|
354
|
+
seen.add(spelled.toolName);
|
|
355
|
+
kept.push(spelled.toolName);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return kept;
|
|
359
|
+
}
|
|
360
|
+
function toolNameSetRefusal(who, invalid) {
|
|
361
|
+
const byLesson = new Map();
|
|
362
|
+
for (const i of invalid)
|
|
363
|
+
byLesson.set(i.lesson, [...(byLesson.get(i.lesson) ?? []), { entry: i.entry, list: i.list }]);
|
|
364
|
+
const e = new Error(`${who}: ${invalid.length} entr${invalid.length === 1 ? "y is" : "ies are"} not tool name(s):\n` +
|
|
365
|
+
[...byLesson.entries()].map(([lesson, group]) => ` Each of the following is ${lesson}\n` + group.map((g) => ` [${g.list}] "${g.entry}"`).join("\n")).join("\n"));
|
|
366
|
+
e.code = "config.invalid_tool_name_set";
|
|
367
|
+
e.issues = invalid;
|
|
368
|
+
return e;
|
|
369
|
+
}
|
|
370
|
+
export function createAllowDenyPolicy(opts) {
|
|
371
|
+
assertNoRetiredKeys(opts, RETIRED_ALLOW_DENY_POLICY_OPTIONS, "createAllowDenyPolicy");
|
|
372
|
+
const invalid = [];
|
|
373
|
+
const screenedAllow = screenToolNameList(opts.allow, "allow", "allow", invalid);
|
|
374
|
+
const screenedDeny = screenToolNameList(opts.deny, "deny", "deny", invalid);
|
|
375
|
+
if (invalid.length > 0) {
|
|
376
|
+
if ((opts.onInvalidName ?? "throw") === "throw")
|
|
377
|
+
throw toolNameSetRefusal("createAllowDenyPolicy", invalid);
|
|
462
378
|
for (const issue of invalid)
|
|
463
379
|
opts.onInvalidNameIssue?.(issue);
|
|
464
380
|
}
|
|
465
381
|
opts = { ...opts, ...(screenedAllow ? { allow: screenedAllow } : {}), ...(screenedDeny ? { deny: screenedDeny } : {}) };
|
|
466
382
|
const allow = opts.allow ? new Set(opts.allow) : undefined;
|
|
467
383
|
const deny = new Set(opts.deny ?? []);
|
|
468
|
-
const denyCovering =
|
|
469
|
-
const allowCovering =
|
|
384
|
+
const denyCovering = coveringRuleEntries(opts.deny, "deny");
|
|
385
|
+
const allowCovering = coveringRuleEntries(opts.allow, "allow");
|
|
470
386
|
return {
|
|
471
387
|
projection: {
|
|
472
388
|
components: [
|
|
@@ -477,10 +393,10 @@ export function createAllowDenyPolicy(opts) {
|
|
|
477
393
|
},
|
|
478
394
|
nameSets: [{ ...(opts.allow ? { allow: [...opts.allow] } : {}), ...(opts.deny ? { deny: [...opts.deny] } : {}) }],
|
|
479
395
|
check(req) {
|
|
480
|
-
if (nameListHolds(deny, req) ||
|
|
396
|
+
if (nameListHolds(deny, req) || coveringRuleHit(denyCovering, req)) {
|
|
481
397
|
return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
|
|
482
398
|
}
|
|
483
|
-
if (allow && !nameListHolds(allow, req) && !
|
|
399
|
+
if (allow && !nameListHolds(allow, req) && !coveringRuleHit(allowCovering, req)) {
|
|
484
400
|
return { action: "deny", message: `tool "${req.toolName}" is not in the allowlist` };
|
|
485
401
|
}
|
|
486
402
|
return ALLOW;
|
|
@@ -497,19 +413,21 @@ export function createApprovalPolicy(opts) {
|
|
|
497
413
|
if (opts.approvalTimeoutMs !== undefined && opts.approvalTimeoutMs > 2_147_483_647) {
|
|
498
414
|
throw new Error(`createApprovalPolicy: approvalTimeoutMs must not exceed 2147483647ms (~24.8 days) (got ${opts.approvalTimeoutMs}) — a host timer truncates a larger delay and fires immediately, denying every request at once; omit it to wait indefinitely`);
|
|
499
415
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
416
|
+
const invalid = [];
|
|
417
|
+
const requireApproval = screenToolNameList(opts.requireApproval, "requireApproval", "ask", invalid) ?? [];
|
|
418
|
+
const denied = screenToolNameList(opts.deny, "deny", "deny", invalid);
|
|
419
|
+
const autoAllow = screenToolNameList(opts.autoAllow, "autoAllow", "allow", invalid);
|
|
420
|
+
if (opts.denyByDefault === true)
|
|
421
|
+
screenToolNameList(requireApproval, "requireApproval", "allow", invalid);
|
|
422
|
+
if (invalid.length > 0)
|
|
423
|
+
throw toolNameSetRefusal("createApprovalPolicy", invalid);
|
|
424
|
+
opts = { ...opts, requireApproval, ...(denied !== undefined ? { deny: denied } : {}), ...(autoAllow !== undefined ? { autoAllow } : {}) };
|
|
507
425
|
const need = new Set(opts.requireApproval);
|
|
508
426
|
const deny = new Set(opts.deny ?? []);
|
|
509
427
|
const auto = new Set(opts.autoAllow ?? []);
|
|
510
|
-
const needCovering =
|
|
511
|
-
const denyCovering =
|
|
512
|
-
const autoCovering =
|
|
428
|
+
const needCovering = coveringRuleEntries(opts.requireApproval, "ask");
|
|
429
|
+
const denyCovering = coveringRuleEntries(opts.deny, "deny");
|
|
430
|
+
const autoCovering = coveringRuleEntries(opts.autoAllow, "allow");
|
|
513
431
|
return {
|
|
514
432
|
projection: {
|
|
515
433
|
components: [
|
|
@@ -526,10 +444,10 @@ export function createApprovalPolicy(opts) {
|
|
|
526
444
|
},
|
|
527
445
|
],
|
|
528
446
|
async check(req, signal) {
|
|
529
|
-
if (nameListHolds(deny, req) ||
|
|
447
|
+
if (nameListHolds(deny, req) || coveringRuleHit(denyCovering, req)) {
|
|
530
448
|
return { action: "deny", message: `tool "${req.toolName}" is denied by policy` };
|
|
531
449
|
}
|
|
532
|
-
if (nameListHolds(need, req) ||
|
|
450
|
+
if (nameListHolds(need, req) || coveringRuleHit(needCovering, req)) {
|
|
533
451
|
const attestOver = (inputDigest) => (d, settlement, bindingRefusal) => ({ ...d, attestation: mintAttestation(req, { settlement, origin: "policy", ...(inputDigest !== undefined ? { inputDigest } : {}), ...(bindingRefusal !== undefined ? { bindingRefusal } : {}) }) });
|
|
534
452
|
const unasked = unaskedSeatAnswer(req, signal, { aborted: `approval aborted for "${req.toolName}" (run or turn interrupted)`, unreachable: `approval for "${req.toolName}" was not requested: nobody can be asked about this call` }, "policy");
|
|
535
453
|
if (unasked !== undefined)
|
|
@@ -592,7 +510,7 @@ export function createApprovalPolicy(opts) {
|
|
|
592
510
|
}
|
|
593
511
|
return attest({ action: "deny", message: `approval denied for "${req.toolName}"` }, settledByDecider("person", "refused", undefined));
|
|
594
512
|
}
|
|
595
|
-
if (nameListHolds(auto, req) ||
|
|
513
|
+
if (nameListHolds(auto, req) || coveringRuleHit(autoCovering, req))
|
|
596
514
|
return ALLOW;
|
|
597
515
|
if (opts.denyByDefault) {
|
|
598
516
|
return { action: "deny", message: `tool "${req.toolName}" requires explicit allow` };
|
|
@@ -636,7 +554,6 @@ export function combinePolicies(...policies) {
|
|
|
636
554
|
let asked;
|
|
637
555
|
let current = Object.freeze({ ...req });
|
|
638
556
|
let rewrite;
|
|
639
|
-
let records;
|
|
640
557
|
let ruleAskText;
|
|
641
558
|
let probeMandateSeen = false;
|
|
642
559
|
let mandateSeen = false;
|
|
@@ -644,25 +561,64 @@ export function combinePolicies(...policies) {
|
|
|
644
561
|
let noRulingSeen;
|
|
645
562
|
let authoredBySeen = false;
|
|
646
563
|
const contributors = [];
|
|
647
|
-
const
|
|
564
|
+
const decisions = [];
|
|
565
|
+
const recordsExcept = (at) => decisions.reduce((acc, d, j) => (j !== at && d?.action === "allow" && d.attestation !== undefined ? mergeAttestation(req, acc, d.attestation) : acc), undefined);
|
|
566
|
+
const settleDeny = (d, at) => {
|
|
648
567
|
const out = rewrite !== undefined ? refusalOf(d, current.args) : d;
|
|
568
|
+
const records = recordsExcept(at);
|
|
649
569
|
if (records === undefined)
|
|
650
570
|
return out;
|
|
651
571
|
return { ...out, attestation: mergeAttestation(req, records, d.attestation) };
|
|
652
572
|
};
|
|
653
573
|
let seatDeny;
|
|
654
|
-
|
|
655
|
-
|
|
574
|
+
const denied = (d, at) => {
|
|
575
|
+
decisions[at] = undefined;
|
|
576
|
+
if (!seatNeverAsked(attestationOf(d, current)?.settlement))
|
|
577
|
+
return settleDeny(d, at);
|
|
578
|
+
seatDeny ??= settleDeny(d, at);
|
|
579
|
+
return undefined;
|
|
580
|
+
};
|
|
581
|
+
let emitter = -1;
|
|
582
|
+
let personWrote = false;
|
|
583
|
+
for (const [at, p] of policies.entries()) {
|
|
584
|
+
const d = refuseOutOfContractDecision(await p.check(current, signal), { call: req });
|
|
656
585
|
if (d.action === "deny") {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
586
|
+
const ended = denied(d, at);
|
|
587
|
+
if (ended !== undefined)
|
|
588
|
+
return ended;
|
|
660
589
|
continue;
|
|
661
590
|
}
|
|
662
|
-
|
|
591
|
+
decisions[at] = d;
|
|
592
|
+
if (readRejudge(current, current.args, d).kind === "rewritten") {
|
|
593
|
+
if (personWrote)
|
|
594
|
+
return settleDeny({ action: "deny", message: `${editRewrittenSentence(req.toolName)}, which a later policy layer wrote over a person's edit — denied fail-closed` }, at);
|
|
663
595
|
current = Object.freeze(await withArgsReading(current, d.updatedInput, signal));
|
|
664
596
|
rewrite = d;
|
|
597
|
+
emitter = at;
|
|
598
|
+
personWrote = attestationOf(d, current)?.settlement?.who.party === "person" && answeredFor(d, req, current.args);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
for (let at = 0; at < emitter; at++) {
|
|
602
|
+
const p = policies[at];
|
|
603
|
+
const d = refuseOutOfContractDecision(await p.check(current, signal), { call: req });
|
|
604
|
+
if (d.action === "deny") {
|
|
605
|
+
const ended = denied(d, at);
|
|
606
|
+
if (ended !== undefined)
|
|
607
|
+
return ended;
|
|
608
|
+
continue;
|
|
665
609
|
}
|
|
610
|
+
if (readRejudge(current, current.args, d).kind === "rewritten")
|
|
611
|
+
return settleDeny({ action: "deny", message: rewriteChasedSentence(req.toolName) }, at);
|
|
612
|
+
const { updatedInput: _sameBytes, ...asIs } = d;
|
|
613
|
+
const first = decisions[at];
|
|
614
|
+
decisions[at] = asIs.action === "allow" && first?.action === "allow" && first.attestation !== undefined ? withAttestation(asIs, mergeAttestation(req, first.attestation, asIs.attestation)) : asIs;
|
|
615
|
+
}
|
|
616
|
+
if (seatDeny !== undefined)
|
|
617
|
+
return seatDeny;
|
|
618
|
+
let records;
|
|
619
|
+
for (const d of decisions) {
|
|
620
|
+
if (d === undefined)
|
|
621
|
+
continue;
|
|
666
622
|
if (d.action === "allow" && d.attestation !== undefined)
|
|
667
623
|
records = mergeAttestation(req, records, d.attestation);
|
|
668
624
|
if (d.action === "ask" && (asked === undefined || (d.requiresRealApproval === true && asked.requiresRealApproval !== true))) {
|
|
@@ -684,8 +640,6 @@ export function combinePolicies(...policies) {
|
|
|
684
640
|
if (d.action === "ask")
|
|
685
641
|
contributors.push(d);
|
|
686
642
|
}
|
|
687
|
-
if (seatDeny !== undefined)
|
|
688
|
-
return seatDeny;
|
|
689
643
|
if (asked) {
|
|
690
644
|
const merged = rewrite?.updatedInput;
|
|
691
645
|
const withRuleAsk = ruleAskText !== undefined && asked.matchedAskRule === undefined ? { ...asked, matchedAskRule: ruleAskText } : asked;
|
|
@@ -694,16 +648,15 @@ export function combinePolicies(...policies) {
|
|
|
694
648
|
const withFallback = fallbackSeen !== undefined && withMandate.denialLimitFallback === undefined ? { ...withMandate, denialLimitFallback: fallbackSeen, requiresRealApproval: true } : withMandate;
|
|
695
649
|
const withNoRuling = noRulingSeen !== undefined && withFallback.classifierNoRuling === undefined ? { ...withFallback, classifierNoRuling: noRulingSeen, requiresRealApproval: true } : withFallback;
|
|
696
650
|
const withAuthor = authoredBySeen && withNoRuling.authoredBy === undefined ? { ...withNoRuling, authoredBy: "deployment" } : withNoRuling;
|
|
697
|
-
const folded = new Set(
|
|
651
|
+
const folded = new Set(attestationOf(asked, req)?.foldedClasses ?? []);
|
|
698
652
|
for (const c of contributors)
|
|
699
653
|
if (c !== asked)
|
|
700
|
-
for (const k of decisionAskClassesOf(c))
|
|
654
|
+
for (const k of decisionAskClassesOf(c, req))
|
|
701
655
|
folded.add(k);
|
|
702
656
|
if (withNoRuling !== withMandate)
|
|
703
|
-
for (const k of decisionAskClassesOf(asked))
|
|
657
|
+
for (const k of decisionAskClassesOf(asked, req))
|
|
704
658
|
folded.add(k);
|
|
705
|
-
const
|
|
706
|
-
const out = merged !== undefined ? { ...withClasses, updatedInput: merged } : withClasses;
|
|
659
|
+
const out = merged !== undefined ? { ...withAuthor, updatedInput: merged } : withAuthor;
|
|
707
660
|
return folded.size > 0 ? attest(out, req, { foldedClasses: [...folded] }) : out;
|
|
708
661
|
}
|
|
709
662
|
const allowed = rewrite ?? ALLOW;
|
|
@@ -780,17 +733,17 @@ export function createUnverifiableDeletePolicy(opts) {
|
|
|
780
733
|
if (typeof command !== "string")
|
|
781
734
|
return ALLOW;
|
|
782
735
|
const removal = removalReadingOf(command, req, opts?.removalSeat, safeRoots);
|
|
783
|
-
return removal === undefined ? ALLOW : removal.judge(signal).then((found) => (found === undefined ? ALLOW : removalAsk(found.guard, found.text)));
|
|
736
|
+
return removal === undefined ? ALLOW : removal.judge(signal).then((found) => (found === undefined ? ALLOW : removalAsk(req, found.guard, found.text)));
|
|
784
737
|
},
|
|
785
738
|
}, "external_authority");
|
|
786
739
|
}
|
|
787
|
-
function removalAsk(guard, text) {
|
|
740
|
+
function removalAsk(req, guard, text) {
|
|
788
741
|
const messages = {
|
|
789
742
|
dangerous_delete: `Dangerous removal: ${text}. No permission mode, allow rule or classifier clears this — only a person confirming this call does.`,
|
|
790
743
|
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.`,
|
|
791
|
-
unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}
|
|
744
|
+
unverifiable_shell_text: `Unverifiable shell text (fail-closed unless cleared): ${text}.`,
|
|
792
745
|
};
|
|
793
|
-
return { action: "ask", decisionReason: "safety", requiresRealApproval: true,
|
|
746
|
+
return attest({ action: "ask", decisionReason: "safety", requiresRealApproval: true, message: messages[guard] }, req, { guards: [guard] });
|
|
794
747
|
}
|
|
795
748
|
function pathSegments(p) {
|
|
796
749
|
return p.split(/[\\/]/).filter(Boolean);
|
|
@@ -859,16 +812,15 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
859
812
|
}
|
|
860
813
|
return false;
|
|
861
814
|
};
|
|
862
|
-
const askReason = (what) => ({
|
|
815
|
+
const askReason = (req, what) => attest({
|
|
863
816
|
action: "ask",
|
|
864
817
|
decisionReason: "safety",
|
|
865
818
|
requiresRealApproval: true,
|
|
866
|
-
guards: ["transcript_write"],
|
|
867
819
|
message: `Session-transcript write (fail-closed unless cleared): ${what}. Session transcripts (the .jsonl files ` +
|
|
868
820
|
`under the agent data dir's sessions/ directory) are harness-written session state, not agent working ` +
|
|
869
821
|
`files — modifying or deleting them tampers with the run's own audit trail. Reading them (ls/cat/grep ` +
|
|
870
822
|
`as a single simple command) is fine.`,
|
|
871
|
-
});
|
|
823
|
+
}, req, { guards: ["transcript_write"] });
|
|
872
824
|
return brandPolicyAskClass({
|
|
873
825
|
check(req) {
|
|
874
826
|
if (shellToolsListHolds(shellTools, req)) {
|
|
@@ -879,20 +831,16 @@ export function createTranscriptIntegrityPolicy(opts) {
|
|
|
879
831
|
const cwdInsideProtected = req.cwd !== undefined && inProtectedDir(req.cwd);
|
|
880
832
|
if (!referencesProtectedDir(cmd) && !cwdInsideProtected)
|
|
881
833
|
return ALLOW;
|
|
882
|
-
const
|
|
883
|
-
if (
|
|
834
|
+
const verdict = readOnlyShellVerdict(command, { cwd: req.cwd, readers: readAllow });
|
|
835
|
+
if (verdict.readOnly)
|
|
884
836
|
return ALLOW;
|
|
885
|
-
return askReason("
|
|
886
|
-
? `\`${parsed.name}\` is not a read-only command${cwdInsideProtected ? " and the shell's working directory is inside the transcript directory" : ""}`
|
|
887
|
-
: cwdInsideProtected
|
|
888
|
-
? "the shell's working directory is inside the transcript directory and this is not a single read-only command (fail-closed)"
|
|
889
|
-
: "the command references the transcript directory and is not a single read-only command (fail-closed)");
|
|
837
|
+
return askReason(req, `${cwdInsideProtected ? "the shell's working directory is inside the transcript directory" : "the command references the transcript directory"} and is not read-only: ${verdict.reason}`);
|
|
890
838
|
}
|
|
891
839
|
const writeTarget = protectivePathTargetOf(req);
|
|
892
840
|
if (writeTarget !== undefined && writeTarget.access !== "read") {
|
|
893
841
|
const p = writeTargetPath(req);
|
|
894
842
|
if (typeof p === "string" && inProtectedDir(p, req.cwd)) {
|
|
895
|
-
return askReason(`"${p}" is inside the session-transcript directory`);
|
|
843
|
+
return askReason(req, `"${p}" is inside the session-transcript directory`);
|
|
896
844
|
}
|
|
897
845
|
}
|
|
898
846
|
return ALLOW;
|
|
@@ -6,6 +6,7 @@ import { deliverEngineNotice } from "./types.js";
|
|
|
6
6
|
import { TOOL_SEARCH_NAME } from "./runner/tool-disclosure.js";
|
|
7
7
|
import { mountRuleFace, toolFace } from "./tool-catalog-entries.js";
|
|
8
8
|
import { thrownText } from "./thrown-value.js";
|
|
9
|
+
import { carryNotStartedReceipt } from "./delegation-not-started.js";
|
|
9
10
|
export const TOOL_RESULT_REF_CONFLICT_CODE = "tool_result.ref_conflict";
|
|
10
11
|
export class ToolResultRefConflictError extends Error {
|
|
11
12
|
ref;
|
|
@@ -239,6 +240,8 @@ export function withToolResultOffload(tool, store, thresholdChars, sessionId, re
|
|
|
239
240
|
const wrappedExecute = async (toolCallId, params, signal, onUpdate) => {
|
|
240
241
|
const res = await tool.execute(toolCallId, params, signal, onUpdate);
|
|
241
242
|
const offloadedDetails = res.details === undefined ? undefined : await offloadOversizedDetailStrings(res.details, store, thresholdChars, sessionId, toolCallId, provenance);
|
|
243
|
+
if (offloadedDetails !== undefined)
|
|
244
|
+
carryNotStartedReceipt(res.details, offloadedDetails.value);
|
|
242
245
|
const withDetails = (r) => offloadedDetails === undefined || offloadedDetails.value === res.details ? r : { ...r, details: offloadedDetails.value };
|
|
243
246
|
if (totalTextChars(res.content) <= thresholdChars)
|
|
244
247
|
return withDetails(res);
|