@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
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
export function resolveFileHistoryRequest(spec, deps) {
|
|
2
|
-
const
|
|
3
|
-
if (onTrackFailure !== "refuse" && onTrackFailure !== "proceed-unprotected") {
|
|
4
|
-
const e = new Error(`RunnerDeps.onTrackFailure must be "refuse" or "proceed-unprotected"; got ${JSON.stringify(deps.onTrackFailure)} — refusing prepare rather than silently defaulting a first-touch-failure policy.`);
|
|
5
|
-
e.code = "config.invalid_on_track_failure";
|
|
6
|
-
throw e;
|
|
7
|
-
}
|
|
8
|
-
const wiredSeat = resolveWiredFileHistoryStore(deps.fileHistoryStore);
|
|
2
|
+
const { onTrackFailure, wiredSeat, captureOff } = resolveDeploymentFileHistory(deps);
|
|
9
3
|
const runDeclaredOff = resolveRunFileHistoryWord(spec.fileHistory);
|
|
10
|
-
const captureOff = resolveFileHistoryCaptureWord(deps.fileHistoryCapture, wiredSeat);
|
|
11
4
|
const declaredOff = wiredSeat === "disabled" || runDeclaredOff;
|
|
12
5
|
const fileHistoryStore = declaredOff ? undefined : wiredSeat;
|
|
13
6
|
const captureStore = captureOff ? undefined : fileHistoryStore;
|
|
@@ -34,14 +27,29 @@ export function resolveFileHistoryRequest(spec, deps) {
|
|
|
34
27
|
if (rewindTarget !== undefined && fileHistoryStore === undefined) {
|
|
35
28
|
if (runDeclaredOff)
|
|
36
29
|
throw captureDisabledRefusal(rewindTarget);
|
|
37
|
-
|
|
38
|
-
? `rewind-files: restoring files to entry "${rewindTarget}" requires a history backend, but this deployment declared file history disabled (RunnerDeps.fileHistoryStore: "disabled"), so there is no history to restore — the files were NOT rewound`
|
|
39
|
-
: `rewind-files: restoring files to entry "${rewindTarget}" requires a history backend, but this deployment wired no RunnerDeps.fileHistoryStore — no file history was ever recorded, so the files were NOT rewound`);
|
|
40
|
-
e.code = "rewind.store_unconfigured";
|
|
41
|
-
throw e;
|
|
30
|
+
throw storeUnconfiguredRefusal(wiredSeat, rewindTarget);
|
|
42
31
|
}
|
|
43
32
|
return { onTrackFailure, wiredSeat, runDeclaredOff, captureOff, declaredOff, fileHistoryStore, captureStore, rewindTarget, rewindBefore };
|
|
44
33
|
}
|
|
34
|
+
export function resolveDeploymentFileHistory(deps) {
|
|
35
|
+
const onTrackFailure = deps.onTrackFailure === undefined ? "refuse" : deps.onTrackFailure;
|
|
36
|
+
if (onTrackFailure !== "refuse" && onTrackFailure !== "proceed-unprotected") {
|
|
37
|
+
const e = new Error(`RunnerDeps.onTrackFailure must be "refuse" or "proceed-unprotected"; got ${JSON.stringify(deps.onTrackFailure)} — refusing prepare rather than silently defaulting a first-touch-failure policy.`);
|
|
38
|
+
e.code = "config.invalid_on_track_failure";
|
|
39
|
+
throw e;
|
|
40
|
+
}
|
|
41
|
+
const wiredSeat = resolveWiredFileHistoryStore(deps.fileHistoryStore);
|
|
42
|
+
const captureOff = resolveFileHistoryCaptureWord(deps.fileHistoryCapture, wiredSeat);
|
|
43
|
+
const fileHistoryStore = wiredSeat === "disabled" ? undefined : wiredSeat;
|
|
44
|
+
return { onTrackFailure, wiredSeat, captureOff, fileHistoryStore, captureStore: captureOff ? undefined : fileHistoryStore };
|
|
45
|
+
}
|
|
46
|
+
export function storeUnconfiguredRefusal(wiredSeat, target) {
|
|
47
|
+
const e = new Error(wiredSeat === "disabled"
|
|
48
|
+
? `rewind-files: restoring files to entry "${target}" requires a history backend, but this deployment declared file history disabled (RunnerDeps.fileHistoryStore: "disabled"), so there is no history to restore — the files were NOT rewound`
|
|
49
|
+
: `rewind-files: restoring files to entry "${target}" requires a history backend, but this deployment wired no RunnerDeps.fileHistoryStore — no file history was ever recorded, so the files were NOT rewound`);
|
|
50
|
+
e.code = "rewind.store_unconfigured";
|
|
51
|
+
return e;
|
|
52
|
+
}
|
|
45
53
|
function resolveWiredFileHistoryStore(candidate) {
|
|
46
54
|
if (candidate === undefined || candidate === "disabled")
|
|
47
55
|
return candidate;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE restore of a session's tracked set and the ONE reading of its answer, reached DOWN for by the two seats that
|
|
3
|
+
* restore: the file-history phase's restore seat (`prepare-file-history.ts`, a `restoreFiles` / `rewindFilesTo` run)
|
|
4
|
+
* and the out-of-run rewind (`rewind-files.ts`, `Runner.rewindFiles`). A rewind outside a run is therefore the same
|
|
5
|
+
* history operation as the one a run performs, refused with the same codes and sentences, and handing the paths it
|
|
6
|
+
* moved to the same read-state channel.
|
|
7
|
+
*/
|
|
8
|
+
import type { ExecutionEnv } from "../../internal/harness.js";
|
|
9
|
+
import type { FileHistoryRestoreResult, FileHistoryStore, RewindFilesResult } from "../file-history-store.js";
|
|
10
|
+
import type { SessionReadFileStates } from "./session-read-file-states.js";
|
|
11
|
+
/** A restore outcome a seat may accept: the ledger, with `failed` (the operation could not run) already refused —
|
|
12
|
+
* the out-of-run rewind's answer carries exactly this. */
|
|
13
|
+
export type AcceptedFileHistoryRestore = Extract<RewindFilesResult, {
|
|
14
|
+
dryRun: false;
|
|
15
|
+
}>["restore"];
|
|
16
|
+
/**
|
|
17
|
+
* The ONE restore of a session's tracked set and the ONE reading of its answer — the run's restore seat and the
|
|
18
|
+
* out-of-run `Runner.rewindFiles` both call it, so the two cannot disagree about what a restore means:
|
|
19
|
+
* · every path the attempt may have moved (`filesChanged` ∪ `failed[].path`, whatever the outcome) goes to the
|
|
20
|
+
* session's read-state channel (`noteRestored`), because a read record of the old bytes must stop vouching
|
|
21
|
+
* for them on the session's next leg;
|
|
22
|
+
* · `not_found` is "no boundary for that entry" — `rewind_snapshot.unresolvable` (in a "before" restore, the
|
|
23
|
+
* before-specific sentence);
|
|
24
|
+
* · any other `failed` outcome is `rewind.restore_failed` carrying the ledger and the store's own judgment on
|
|
25
|
+
* the coded `detail` channel (a host reads it, never the prose).
|
|
26
|
+
* A `complete` or `partial` answer is returned for the caller to accept: only a run goes on to work on the tree,
|
|
27
|
+
* so only the run seat has a partial-restore policy.
|
|
28
|
+
*/
|
|
29
|
+
export declare function settleFileHistoryRestore(input: {
|
|
30
|
+
store: FileHistoryStore;
|
|
31
|
+
sessionId: string;
|
|
32
|
+
target: string;
|
|
33
|
+
before: boolean;
|
|
34
|
+
env: ExecutionEnv;
|
|
35
|
+
root: string;
|
|
36
|
+
signal: AbortSignal | undefined;
|
|
37
|
+
readStates: Pick<SessionReadFileStates, "noteRestored"> | undefined;
|
|
38
|
+
}): Promise<AcceptedFileHistoryRestore>;
|
|
39
|
+
/** The per-file ledger as one sentence (counts, then each refused / failed path with its reason). */
|
|
40
|
+
export declare function fileHistoryRestoreLedgerLine(r: FileHistoryRestoreResult): string;
|
|
41
|
+
/** A restore whose entry has no boundary on the session; a PREVIEW's form says "usable" — its probe
|
|
42
|
+
* (`canRestore`) cannot tell a boundary never made from one that is there and unreadable, a real restore can. */
|
|
43
|
+
export declare function noBoundaryRefusal(target: string, sessionId: string, preview?: boolean): Error & {
|
|
44
|
+
code?: string;
|
|
45
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { resolveTrackKey } from "../file-history-store.js";
|
|
2
|
+
import { isGovernanceRetryClass } from "../governance-codes.js";
|
|
3
|
+
export async function settleFileHistoryRestore(input) {
|
|
4
|
+
const { store, sessionId, target, env, root } = input;
|
|
5
|
+
const restored = await store.restore(sessionId, target, env, root, input.signal);
|
|
6
|
+
input.readStates?.noteRestored(sessionId, restoredAbsPathsOf(restored, root));
|
|
7
|
+
if (restored.outcome !== "failed")
|
|
8
|
+
return restored;
|
|
9
|
+
if (restored.error?.code === "not_found") {
|
|
10
|
+
if (input.before)
|
|
11
|
+
throw beforeWithoutBoundaryRefusal(target, sessionId);
|
|
12
|
+
throw noBoundaryRefusal(target, sessionId);
|
|
13
|
+
}
|
|
14
|
+
const e = new Error(`rewind-files restore failed (${restored.error?.code ?? "restore_failed"}): ${restored.error?.message ?? "unknown"} — ledger: ${fileHistoryRestoreLedgerLine(restored)}`);
|
|
15
|
+
e.code = "rewind.restore_failed";
|
|
16
|
+
if (restored.error !== undefined)
|
|
17
|
+
e.detail = { code: restored.error.code, ...(isGovernanceRetryClass(restored.error.permanence) ? { permanence: restored.error.permanence } : {}) };
|
|
18
|
+
throw e;
|
|
19
|
+
}
|
|
20
|
+
export function fileHistoryRestoreLedgerLine(r) {
|
|
21
|
+
return `applied ${r.filesChanged.length}, identical ${r.identicalSkipped.length}, refused ${r.refused.length}${r.refused.length > 0 ? ` (${r.refused.map((f) => `${f.path}: ${f.reason}`).join("; ")})` : ""}, failed ${r.failed.length}${r.failed.length > 0 ? ` (${r.failed.map((f) => `${f.path}: ${f.reason}`).join("; ")})` : ""}`;
|
|
22
|
+
}
|
|
23
|
+
export function noBoundaryRefusal(target, sessionId, preview = false) {
|
|
24
|
+
const e = new Error(preview
|
|
25
|
+
? `rewind-files: no usable file-history boundary exists for entry "${target}" on session "${sessionId}" (never made, reaped, or there but unreadable — a real rewind names which), so there is nothing to preview. ${rewindRefusalTail()}`
|
|
26
|
+
: `rewind-files: no file-history boundary exists for entry "${target}" on session "${sessionId}" — the working tree was NOT rewound. ${rewindRefusalTail()}`);
|
|
27
|
+
e.code = "rewind_snapshot.unresolvable";
|
|
28
|
+
return e;
|
|
29
|
+
}
|
|
30
|
+
function restoredAbsPathsOf(restored, root) {
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const key of [...restored.filesChanged, ...restored.failed.map((f) => f.path)]) {
|
|
33
|
+
const abs = resolveTrackKey(root, key);
|
|
34
|
+
if (abs.ok)
|
|
35
|
+
out.push(abs.abs);
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
function rewindRefusalTail() {
|
|
40
|
+
return `Boundaries are keyed by a turn's INITIAL entry and exist only for turns that recorded history (a RunnerDeps.fileHistoryStore wired, capture on, and the run's file history not disabled); a boundary from the retired whole-tree snapshot era is not restorable by this seat, and reaped boundaries have none.`;
|
|
41
|
+
}
|
|
42
|
+
function beforeWithoutBoundaryRefusal(target, sessionId) {
|
|
43
|
+
const e = new Error(`rewind-files: entry "${target}" has no file-history boundary on session "${sessionId}" — a before-restore needs the target's own boundary and never crosses into an earlier turn, so the working tree was NOT rewound. ${rewindRefusalTail()}`);
|
|
44
|
+
e.code = "rewind_snapshot.unresolvable";
|
|
45
|
+
return e;
|
|
46
|
+
}
|
|
@@ -238,9 +238,9 @@ export interface GatePass {
|
|
|
238
238
|
hookAsk: Extract<PermissionResult, {
|
|
239
239
|
action: "ask";
|
|
240
240
|
}> | undefined;
|
|
241
|
-
/** borrowed-mutable — the
|
|
242
|
-
* it: the allow layer's hook member (its `entries`)
|
|
243
|
-
*
|
|
241
|
+
/** borrowed-mutable — the screen answered its own `allow` (the exact word) for the bytes that run, naming the registration
|
|
242
|
+
* that answered it: the allow layer's hook member (its `entries`). Writers: the dispatch (phase 1) and the fold's second
|
|
243
|
+
* look after a policy rewrite (rewrite-rejudge.ts), whose answer replaces the first. Reader: the lanes' allow layer. */
|
|
244
244
|
hookAllowedBy?: readonly string[];
|
|
245
245
|
/** borrowed-mutable — `tool.check` was raised in this pass's first adjudication, which raises it once: set by the
|
|
246
246
|
* raise in front of the ask branch, read by the raise behind the read-only arm (it then raises nothing). Writer and
|
|
@@ -244,7 +244,7 @@ export function hookDenyExit(pass, deniedReason) {
|
|
|
244
244
|
preToolContext: pass.preToolContext,
|
|
245
245
|
};
|
|
246
246
|
}
|
|
247
|
-
const
|
|
247
|
+
const ancestorUnresolvedClassification = (call) => classifyAsk({ action: "ask", message: "" }, { call, contentQuestion: false, markedUnresolvable: true, org: undefined, tightened: undefined, mandateMarks: {} });
|
|
248
248
|
function unresolvableCauseOfSettlement(gate) {
|
|
249
249
|
if (gate.disposition.kind !== "denied" || gate.disposition.deniedBy !== "ask_resolution" || gate.settlement === undefined)
|
|
250
250
|
return undefined;
|
|
@@ -274,12 +274,13 @@ export async function exitGate(pass) {
|
|
|
274
274
|
const tableSeat = unresolvable !== undefined ? askUnresolvableRemedySeat(unresolvable) : undefined;
|
|
275
275
|
const remedySeat = tableSeat === "absent" && input.askSeatForm === "declared_none" && pass.askClassification?.classes.has("content_question") !== true ? "declared_none" : tableSeat;
|
|
276
276
|
const bindingRefusal = attestationOf(pass.decision, { toolCallId, toolName })?.bindingRefusal;
|
|
277
|
-
const
|
|
277
|
+
const headless = bindingRefusal !== undefined ? undefined : remedySeat !== undefined ? headlessApprovalRemedy({ mode: input.permissionMode?.(), classification: foldCause !== undefined ? ancestorUnresolvedClassification(pass.req) : pass.askClassification, approverSeat: remedySeat, coveredWrite: isProtectedWrite(pass.req), ...(pass.shellUnplacedOptions !== undefined ? { unplacedOptions: pass.shellUnplacedOptions } : {}) }) : undefined;
|
|
278
|
+
const remedy = headless?.sentence;
|
|
278
279
|
const denyReason = withParkFailureCause(`${decisionText(pass.decision) ?? `tool "${toolName}" denied by policy`}${remedy !== undefined ? ` — ${remedy}` : ""}`, pass.parkFailed, unresolvable !== undefined);
|
|
279
280
|
if (unresolvable !== undefined) {
|
|
280
281
|
const cause = unresolvable;
|
|
281
282
|
const noticeRemedy = bindingRefusal ?? remedy;
|
|
282
|
-
pass.notifier.notify(() => input.onAskUnresolvable?.({ toolName, toolCallId, cause, parkLaneExisted: pass.suspendAsk !== undefined, ...(noticeRemedy !== undefined ? { remedy: noticeRemedy } : {}) }), "toolGate.onAskUnresolvable");
|
|
283
|
+
pass.notifier.notify(() => input.onAskUnresolvable?.({ toolName, toolCallId, cause, parkLaneExisted: pass.suspendAsk !== undefined, ...(noticeRemedy !== undefined ? { remedy: noticeRemedy } : {}), ...(headless !== undefined ? { remedies: headless.remedies } : {}) }), "toolGate.onAskUnresolvable");
|
|
283
284
|
}
|
|
284
285
|
const finalInput = frozenInputSnapshot(pass.currentInput);
|
|
285
286
|
await notifyPermissionDenied({
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
import type { ImageContent } from "../../internal/llm.js";
|
|
2
|
+
import { type HostFloor } from "../host-floor.js";
|
|
2
3
|
import type { ImageInput } from "../types.js";
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* are normalized to dotted-decimal by `URL` before this is called, so they're already covered.
|
|
9
|
-
* Note: this checks the LITERAL host; it does NOT resolve DNS, so a hostname resolving to a private IP is not
|
|
10
|
-
* caught here (documented limitation — a deployment needing that supplies its own resolve-and-pin guard).
|
|
5
|
+
* The guard of a remote image URL: https only, then the one egress hop judge with the private-network floor (`hopRefusal`,
|
|
6
|
+
* host-floor.ts) — the deployment's host floor (`RunnerDeps.hostFloor`, `floor`) must admit the host, and a private host is
|
|
7
|
+
* reachable only when the floor's `only` list names it — so an end-user-supplied `images[].url` can't make the server fetch
|
|
8
|
+
* `169.254.169.254` or a private box. The host is read literally (no DNS resolution). Throws on a refused URL.
|
|
11
9
|
*/
|
|
12
|
-
export declare function
|
|
13
|
-
/**
|
|
14
|
-
* Default SSRF guard for a remote image URL: https only, and no internal/reserved hosts (so an
|
|
15
|
-
* end-user-supplied `images[].url` can't make the server fetch `169.254.169.254` or a private box).
|
|
16
|
-
* Note: this checks the URL host literally — it does not resolve DNS, so a hostname that resolves to
|
|
17
|
-
* a private IP is not caught here; a deployment needing that should supply `RunnerDeps.allowImageUrl`
|
|
18
|
-
* (e.g. a CDN allowlist or a resolve-and-pin check). Throws on a disallowed URL.
|
|
19
|
-
*/
|
|
20
|
-
export declare function defaultImageUrlGuard(raw: string): void;
|
|
10
|
+
export declare function defaultImageUrlGuard(raw: string, floor?: HostFloor): void;
|
|
21
11
|
/** Resolve an {@link ImageInput} (inline base64 or a URL to fetch) into a vendored `ImageContent` block. */
|
|
22
|
-
export declare function toImageContent(img: ImageInput,
|
|
12
|
+
export declare function toImageContent(img: ImageInput, floor: HostFloor | undefined): Promise<ImageContent>;
|
|
@@ -1,55 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hopRefusal } from "../host-floor.js";
|
|
2
2
|
import { ADMITTED_IMAGE_MIME_TYPES, imageMagicMatches } from "../image-admission.js";
|
|
3
3
|
import { admitInlineImage } from "./inline-image.js";
|
|
4
4
|
function sniffImageMime(bytes) {
|
|
5
5
|
return ADMITTED_IMAGE_MIME_TYPES.find((mime) => imageMagicMatches(bytes, mime));
|
|
6
6
|
}
|
|
7
|
-
function
|
|
8
|
-
const o = ip.split(".").map(Number);
|
|
9
|
-
if (o.length !== 4 || o.some((n) => !Number.isInteger(n) || n < 0 || n > 255))
|
|
10
|
-
return true;
|
|
11
|
-
const [a, b] = o;
|
|
12
|
-
return (a === 127 ||
|
|
13
|
-
a === 10 ||
|
|
14
|
-
a === 0 ||
|
|
15
|
-
(a === 172 && b >= 16 && b <= 31) ||
|
|
16
|
-
(a === 192 && b === 168) ||
|
|
17
|
-
(a === 169 && b === 254) ||
|
|
18
|
-
(a === 100 && b >= 64 && b <= 127));
|
|
19
|
-
}
|
|
20
|
-
function embeddedV4(h) {
|
|
21
|
-
const fromHex = (hi, lo) => {
|
|
22
|
-
const a = parseInt(hi, 16), c = parseInt(lo, 16);
|
|
23
|
-
return `${(a >> 8) & 255}.${a & 255}.${(c >> 8) & 255}.${c & 255}`;
|
|
24
|
-
};
|
|
25
|
-
let m = /^(?:::ffff:|64:ff9b::)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.exec(h);
|
|
26
|
-
if (m)
|
|
27
|
-
return m[1];
|
|
28
|
-
m = /^(?:::ffff:|64:ff9b::)([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(h);
|
|
29
|
-
if (m)
|
|
30
|
-
return fromHex(m[1], m[2]);
|
|
31
|
-
return undefined;
|
|
32
|
-
}
|
|
33
|
-
export function isPrivateHost(host) {
|
|
34
|
-
const h = host
|
|
35
|
-
.replace(/^\[|\]$/g, "")
|
|
36
|
-
.replace(/\.+$/, "")
|
|
37
|
-
.toLowerCase();
|
|
38
|
-
if (h === "localhost")
|
|
39
|
-
return true;
|
|
40
|
-
const fam = isIP(h);
|
|
41
|
-
if (fam === 0)
|
|
42
|
-
return false;
|
|
43
|
-
if (fam === 4)
|
|
44
|
-
return isPrivateV4(h);
|
|
45
|
-
const v4 = embeddedV4(h);
|
|
46
|
-
if (v4)
|
|
47
|
-
return isPrivateV4(v4);
|
|
48
|
-
if (h === "::1" || h === "::")
|
|
49
|
-
return true;
|
|
50
|
-
return /^fe[89ab]/.test(h) || /^f[cd]/.test(h) || /^fe[c-f]/.test(h);
|
|
51
|
-
}
|
|
52
|
-
export function defaultImageUrlGuard(raw) {
|
|
7
|
+
export function defaultImageUrlGuard(raw, floor) {
|
|
53
8
|
let u;
|
|
54
9
|
try {
|
|
55
10
|
u = new URL(raw);
|
|
@@ -60,9 +15,9 @@ export function defaultImageUrlGuard(raw) {
|
|
|
60
15
|
if (u.protocol !== "https:") {
|
|
61
16
|
throw new Error(`image url must be https (got "${u.protocol}")`);
|
|
62
17
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
18
|
+
const refused = hopRefusal(u, floor, true);
|
|
19
|
+
if (refused !== undefined)
|
|
20
|
+
throw new Error(`image url not fetched — ${refused}`);
|
|
66
21
|
}
|
|
67
22
|
const IMAGE_FETCH_TIMEOUT_MS = 30_000;
|
|
68
23
|
const IMAGE_MAX_BYTES = 20 * 1024 * 1024;
|
|
@@ -112,17 +67,11 @@ async function fetchImageCapped(url) {
|
|
|
112
67
|
}
|
|
113
68
|
return { buf, mimeType: sniffed };
|
|
114
69
|
}
|
|
115
|
-
export async function toImageContent(img,
|
|
70
|
+
export async function toImageContent(img, floor) {
|
|
116
71
|
if ("url" in img) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
defaultImageUrlGuard(img.url);
|
|
124
|
-
}
|
|
125
|
-
const { buf, mimeType } = await fetchImageCapped(img.url);
|
|
72
|
+
const url = img.url;
|
|
73
|
+
defaultImageUrlGuard(url, floor);
|
|
74
|
+
const { buf, mimeType } = await fetchImageCapped(url);
|
|
126
75
|
return { type: "image", data: buf.toString("base64"), mimeType };
|
|
127
76
|
}
|
|
128
77
|
return admitInlineImage(img);
|
|
@@ -29,11 +29,8 @@ import { type OrgGateVerdict, type PersistedRuleAnswer, type PersistedRuleHit, t
|
|
|
29
29
|
import type { PersistedRule, PersistedRuleVerdict, RuleOffer, ScopeRootIdentity, SegmentCoverage } from "../permission-rule-model.js";
|
|
30
30
|
import { type PathRuleBases } from "../permission-rule-model.js";
|
|
31
31
|
import { type HeadLeads } from "../path-rule-binding.js";
|
|
32
|
-
import type { ToolCallLike } from "../tool-registry.js";
|
|
33
32
|
import { type OrgRuleResolution } from "../permission-rule-org.js";
|
|
34
33
|
import { type EffectivePermissionRules, type PermissionRuleStoreProvider, type PersonRowsRead } from "../permission-rule-provider.js";
|
|
35
|
-
/** The one SHELL tool the persisted-rule lane's COMMAND grammar speaks for (the rule-offer face mints for it, the name tools and the host tools); the other grammars' tools are derived (`ruleToolGrammarOf`). */
|
|
36
|
-
export declare const PERSISTED_RULE_TOOL = "Bash";
|
|
37
34
|
/**
|
|
38
35
|
* The evidence an INHERITED-lane ask carries.
|
|
39
36
|
*
|
|
@@ -121,7 +118,7 @@ export interface PermissionRuleLanes {
|
|
|
121
118
|
* `onDegraded` receives the snapshot's degraded line ({@link describeUnreadableOrgRows}) on every adjudication over a
|
|
122
119
|
* snapshot carrying a row this layer cannot read. */
|
|
123
120
|
export declare function orgRuleLane(cfg: {
|
|
124
|
-
read: (toolCallId: string) => Promise<Pick<EffectivePermissionRules, "org">>;
|
|
121
|
+
read: (toolCallId: string, judged: unknown) => Promise<Pick<EffectivePermissionRules, "org">>;
|
|
125
122
|
questionToolMounted: boolean;
|
|
126
123
|
questionToolName: string;
|
|
127
124
|
onRevisionDefect: (message: string) => void;
|
|
@@ -177,10 +174,10 @@ export declare function createPermissionRuleLanes(cfg: {
|
|
|
177
174
|
onRevisionDefect: (message: string) => void;
|
|
178
175
|
/** Sink for a judgment against the rows that threw, and for the org lane's degraded-snapshot line. */
|
|
179
176
|
onDisclosure: (message: string) => void;
|
|
180
|
-
/** The run's one reader of the person's rules: the call's ONE read, pinned, that the read station, the
|
|
181
|
-
* personal lane all take (the lanes consume a reader; they do not make one). */
|
|
177
|
+
/** The run's one reader of the person's rules: the call's ONE read of the bytes judged, pinned, that the read station, the
|
|
178
|
+
* org lane and the personal lane all take (the lanes consume a reader; they do not make one). */
|
|
182
179
|
rows: {
|
|
183
|
-
pin(toolCallId: string): Promise<PersonRowsRead>;
|
|
180
|
+
pin(toolCallId: string, judged?: unknown): Promise<PersonRowsRead>;
|
|
184
181
|
};
|
|
185
182
|
/** The allow layer's auto strip over a stored ALLOW row (true ⇒ out of this call's table BEFORE the coverage is chosen). */
|
|
186
183
|
stripsAllow?: (rule: PersistedRule, req: ToolCallRequest) => boolean;
|
|
@@ -203,9 +200,12 @@ interface RuleOffersAskFacts extends RuleClearanceFacts {
|
|
|
203
200
|
* approval-preview field is a standing example of what happens otherwise: it reached two of the
|
|
204
201
|
* five, so a delegated child's card was silently poorer than the top-level one).
|
|
205
202
|
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
203
|
+
* Silent (no offer and no reason) only where no rule speaks for the call: no lane armed, the anonymous floor,
|
|
204
|
+
* a call the lane never judges — offering an option that redemption would refuse is worse than offering none.
|
|
205
|
+
* Every other card offers the one rule its call's form mints ({@link cardRuleFormOf}: the shell card's
|
|
206
|
+
* command rules, a name or host tool's exact value rule, the whole-tool rule of a call no rule word speaks
|
|
207
|
+
* for) or names why it offers none (`lane_cannot_speak`: a compound, a redirection, a substitution, a path
|
|
208
|
+
* tool, a shell-face sibling, a tool answering to one of those under an alias).
|
|
209
209
|
*
|
|
210
210
|
* Empty, too, on any ask a persisted rule could never CLEAR — "allow rules silence the classifier's
|
|
211
211
|
* questions, never a mandated one". Two doors, matching the two halves of that boundary:
|
|
@@ -270,7 +270,7 @@ export declare function createRuleOffersOf(cfg: {
|
|
|
270
270
|
current: string;
|
|
271
271
|
} | undefined;
|
|
272
272
|
deniesDirectoryRead: ((directory: string) => boolean) | undefined;
|
|
273
|
-
}): (call: Pick<
|
|
273
|
+
}): (call: Pick<ToolCallRequest, "toolName" | "face">, args: unknown, ask: RuleOffersAskFacts | undefined) => {
|
|
274
274
|
ruleOffers?: readonly RuleOffer[];
|
|
275
275
|
ruleOffersAbsence?: RuleOffersAbsence;
|
|
276
276
|
execCwd?: string;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { persistedRuleMandateOf, ruleClearanceOf } from "../ask-origin.js";
|
|
2
2
|
import {} from "../hooks.js";
|
|
3
|
-
import { adjudicatePersistedDomainRules, adjudicatePersistedNameRules, adjudicatePersistedPathRules, adjudicatePersistedRules, callPathFaceOf, escapeForDisclosure, faceRowsSpeakFor, laneToolNamesOf, nameRuleSubjectOf, ruleToolGrammarOf, segmentCoverageOf, suggestRuleForHost, suggestRuleForName, suggestRulesForCommand } from "../permission-rule-model.js";
|
|
3
|
+
import { adjudicatePersistedDomainRules, adjudicatePersistedNameRules, adjudicatePersistedPathRules, adjudicatePersistedRules, adjudicatePersistedToolRules, callPathFaceOf, cardRuleFormOf, eligiblePersisted, escapeForDisclosure, faceRowsSpeakFor, parseRuleText, laneToolNamesOf, nameRuleSubjectOf, ruleToolGrammarOf, segmentCoverageOf, suggestRuleForHost, suggestRuleForName, suggestRuleForTool, suggestRulesForCommand, wholeToolRuleReaches } from "../permission-rule-model.js";
|
|
4
4
|
import { callHostTargetOf } from "../host-target.js";
|
|
5
5
|
import { callTargetViewsOf, validatePath } from "../effective-path-target.js";
|
|
6
6
|
import { bindPathRules, persistedRowAnchors, projectScopeIdentity } from "../path-rule-binding.js";
|
|
7
7
|
import { heldBy, seatOf, wireOf } from "../tool-name-readings.js";
|
|
8
8
|
import { describeUnreadableOrgRows, readOrgRules, settleOrgVerdictWithin } from "../permission-rule-org.js";
|
|
9
9
|
import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
10
|
+
import { routesContent } from "../tool-catalog-entries.js";
|
|
10
11
|
import { ownerStoreOf } from "../permission-rule-provider.js";
|
|
12
|
+
import { readPrincipal } from "../principal-name.js";
|
|
11
13
|
import { thrownText } from "../thrown-value.js";
|
|
12
14
|
import { strongestAnswer } from "../persisted-rule-arms.js";
|
|
13
15
|
import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
|
|
14
|
-
export const PERSISTED_RULE_TOOL = "Bash";
|
|
15
16
|
const NO_LEADS = new Map();
|
|
16
17
|
export function inheritedAskRuleEvidence(provider) {
|
|
17
18
|
const org = provider?.partitions.org === true ? "not_adjudicated" : "not_wired";
|
|
@@ -59,7 +60,7 @@ export function orgRuleLane(cfg) {
|
|
|
59
60
|
return { status: "available" };
|
|
60
61
|
let resolution;
|
|
61
62
|
try {
|
|
62
|
-
resolution = (await cfg.read(req.toolCallId)).org;
|
|
63
|
+
resolution = (await cfg.read(req.toolCallId, req.args)).org;
|
|
63
64
|
}
|
|
64
65
|
catch (err) {
|
|
65
66
|
return { status: "unavailable", disclosures: [`the permission-rule store threw while resolving the org partition: ${thrownText(err)}`] };
|
|
@@ -106,10 +107,10 @@ export function createPermissionRuleLanes(cfg) {
|
|
|
106
107
|
}
|
|
107
108
|
if (provider === undefined)
|
|
108
109
|
return { personal: undefined, org: undefined };
|
|
109
|
-
const anonymous = cfg.principal
|
|
110
|
+
const anonymous = readPrincipal(cfg.principal).kind === "absent";
|
|
110
111
|
const reader = cfg.rows;
|
|
111
|
-
const orgViewOf = async (toolCallId) => {
|
|
112
|
-
const read = await reader.pin(toolCallId);
|
|
112
|
+
const orgViewOf = async (toolCallId, judged) => {
|
|
113
|
+
const read = await reader.pin(toolCallId, judged);
|
|
113
114
|
if (read.org === undefined)
|
|
114
115
|
throw new Error(read.unreadable ?? "the store did not answer");
|
|
115
116
|
return { org: read.org };
|
|
@@ -121,14 +122,26 @@ export function createPermissionRuleLanes(cfg) {
|
|
|
121
122
|
const judged = laneToolNamesOf(req).map((n) => [n, ruleToolGrammarOf(n)]);
|
|
122
123
|
if (!judged.some(([, g]) => g === "path") && faceRowsSpeakFor(callPathFaceOf(req)))
|
|
123
124
|
judged.push([req.toolName, "path"]);
|
|
124
|
-
const view = await reader.pin(req.toolCallId);
|
|
125
|
-
|
|
125
|
+
const view = await reader.pin(req.toolCallId, req.args);
|
|
126
|
+
const ownRow = (r) => judged.some(([n]) => n === r.tool) || wholeToolRuleReaches(r.tool, req);
|
|
127
|
+
if (judged.length === 0 && !view.rules.some(ownRow))
|
|
126
128
|
return view.unreadable !== undefined ? { unreadable: true } : undefined;
|
|
127
129
|
try {
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
+
const stripped = view.rules.filter((r) => r.behavior !== "allow" || cfg.stripsAllow?.(r, req) !== true);
|
|
131
|
+
const judgesPath = judged.some(([, g]) => g === "path");
|
|
132
|
+
const noRule = [];
|
|
133
|
+
const table = stripped.filter((r) => {
|
|
134
|
+
const read = ownRow(r) || (judgesPath && (r.match === "path" || r.match === "subpath")) ? parseRuleText(r.rule, r.behavior) : undefined;
|
|
135
|
+
if (read !== undefined && "reject" in read)
|
|
136
|
+
noRule.push({ row: r, why: read.reject.message });
|
|
137
|
+
return read === undefined || !("reject" in read) || r.behavior !== "allow";
|
|
138
|
+
});
|
|
139
|
+
const leads = judgesPath ? await cfg.leads.resolve(bindPathRules(table.filter((r) => r.match === "path" || r.match === "subpath").map((r) => ({ parsed: r, ruleText: r.rule, rule: r })), (spec) => anchorsOf(spec.rule))) : NO_LEADS;
|
|
130
140
|
const scopeIdentity = await projectScopeIdentity(table, cfg.rootCanonical, cfg.leads);
|
|
131
|
-
const
|
|
141
|
+
const wholeTool = persistedRuleAnswerOf(adjudicatePersistedToolRules(table, { request: req, cwd: cfg.root, sessionId: cfg.sessionId, ...(scopeIdentity !== undefined ? { scopeIdentity } : {}) }));
|
|
142
|
+
const judgedAnswer = strongestAnswer([...judged.map(([n, grammar]) => judgeAgainst(table, { ...req, toolName: n }, grammar, leads, scopeIdentity)), wholeTool]);
|
|
143
|
+
const unjudged = noRule.find(({ row }) => (row.behavior === "deny" || row.behavior === "ask") && eligiblePersisted(row, { tool: row.tool, cwd: cfg.root, sessionId: cfg.sessionId, ...(scopeIdentity !== undefined ? { scopeIdentity } : {}) }, row.behavior));
|
|
144
|
+
const answer = unjudged !== undefined && !(judgedAnswer !== undefined && "behavior" in judgedAnswer && judgedAnswer.behavior === "deny") ? unjudgedRowAnswer(unjudged.row, unjudged.why, req.toolName) : judgedAnswer;
|
|
132
145
|
const stands = answer !== undefined && (("behavior" in answer && answer.behavior === "deny") || "unreadable" in answer);
|
|
133
146
|
return view.unreadable !== undefined && !stands ? { unreadable: true } : answer;
|
|
134
147
|
}
|
|
@@ -138,6 +151,11 @@ export function createPermissionRuleLanes(cfg) {
|
|
|
138
151
|
return { unreadable: true, reason: why };
|
|
139
152
|
}
|
|
140
153
|
};
|
|
154
|
+
const unjudgedRowAnswer = (row, refusal, tool) => {
|
|
155
|
+
const why = `the stored ${row.behavior} rule ${escapeForDisclosure(row.rule)} is no rule this engine reads (${refusal})`;
|
|
156
|
+
cfg.onDisclosure(`the persisted rule lane could not judge a ${tool} call against the rows it read — ${why}`);
|
|
157
|
+
return { unreadable: true, reason: why };
|
|
158
|
+
};
|
|
141
159
|
const anchorsOf = (rule) => persistedRowAnchors(rule.scope, cfg.chainTop);
|
|
142
160
|
const judgeAgainst = (table, req, grammar, leads, scopeIdentity) => {
|
|
143
161
|
const liveCwd = cfg.liveCwd();
|
|
@@ -164,11 +182,9 @@ export function createPermissionRuleLanes(cfg) {
|
|
|
164
182
|
export function createRuleOffersOf(cfg) {
|
|
165
183
|
return (call, args, ask) => {
|
|
166
184
|
const toolName = wireOf("offer.laneTool", call);
|
|
167
|
-
|
|
168
|
-
if (!cfg.laneArmed || (toolName !== PERSISTED_RULE_TOOL && grammar !== "name" && grammar !== "domain"))
|
|
169
|
-
return {};
|
|
170
|
-
if ((cfg.principal === undefined || cfg.principal === "") && !cfg.localOwnerDeclared)
|
|
185
|
+
if (!cfg.laneArmed || (readPrincipal(cfg.principal).kind === "absent" && !cfg.localOwnerDeclared) || routesContent(call.face))
|
|
171
186
|
return {};
|
|
187
|
+
const form = cardRuleFormOf(toolName, call);
|
|
172
188
|
const tierSeat = seatOf("offer.marks", cfg.irreversibilityTier, call);
|
|
173
189
|
const closedDoor = ruleClearanceOf(ask, {
|
|
174
190
|
egress: heldBy("offer.marks.egress", cfg.egressTools, call),
|
|
@@ -177,11 +193,17 @@ export function createRuleOffersOf(cfg) {
|
|
|
177
193
|
}).word;
|
|
178
194
|
if (closedDoor !== undefined)
|
|
179
195
|
return { ruleOffersAbsence: closedDoor };
|
|
180
|
-
if (
|
|
196
|
+
if (form === "tool") {
|
|
197
|
+
const offer = suggestRuleForTool(toolName);
|
|
198
|
+
return offer !== undefined ? { ruleOffers: [offer] } : { ruleOffersAbsence: "lane_cannot_speak" };
|
|
199
|
+
}
|
|
200
|
+
if (form === undefined)
|
|
201
|
+
return { ruleOffersAbsence: "lane_cannot_speak" };
|
|
202
|
+
if (form === "name") {
|
|
181
203
|
const offer = suggestRuleForName(toolName, nameRuleSubjectOf(toolName, args) ?? "");
|
|
182
204
|
return offer !== undefined ? { ruleOffers: [offer] } : { ruleOffersAbsence: "lane_cannot_speak" };
|
|
183
205
|
}
|
|
184
|
-
if (
|
|
206
|
+
if (form === "domain") {
|
|
185
207
|
const host = callHostTargetOf({ toolName: call.toolName, args, face: call.face }, "grant");
|
|
186
208
|
const offer = host !== undefined && "host" in host ? suggestRuleForHost(toolName, host.host) : undefined;
|
|
187
209
|
return offer !== undefined ? { ruleOffers: [offer] } : { ruleOffersAbsence: "lane_cannot_speak" };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The person's persisted rules as ONE run reads them.
|
|
3
3
|
*
|
|
4
|
-
* ## One read per
|
|
4
|
+
* ## One read per judgment of a call's bytes
|
|
5
5
|
*
|
|
6
|
-
* A call
|
|
7
|
-
*
|
|
8
|
-
* others are handed the same answer, and the tables the call's tool judges with when it executes are
|
|
9
|
-
* ({@link PathTablesFacade.forCall}).
|
|
6
|
+
* A call's bytes are judged against ONE read of the store, pinned to its `toolCallId` ({@link PersonPathRows.pin}): whichever
|
|
7
|
+
* of the consumers judging those bytes asks first — the read station's judgment, the org layer, the personal rule lane —
|
|
8
|
+
* takes the read, the others are handed the same answer, and the tables the call's tool judges with when it executes are
|
|
9
|
+
* compiled from it ({@link PathTablesFacade.forCall}). Judging other bytes of the same call (an approved edit) is another
|
|
10
|
+
* judgment: it takes a new read, which the call then holds — a rule written while a person decided binds their edit. A call is an attempt the leg's occurrence table holds; the pin is released when the
|
|
10
11
|
* table no longer holds that attempt. A judgment that is no call of the leg (a visibility probe's fixed id, a gate with no
|
|
11
12
|
* leg) keeps nothing: its rule lanes take a read of their own, its read station the run's latest tables.
|
|
12
13
|
*
|
|
@@ -106,10 +107,12 @@ export interface PersonPathRows {
|
|
|
106
107
|
readonly holdsPersonRows: boolean;
|
|
107
108
|
/** The prepare read — the unit's first write. `undefined`, synchronously, when there is no person's rows to read. */
|
|
108
109
|
prime(): Promise<void> | undefined;
|
|
109
|
-
/** The rows of a call's one read — a call the leg's occurrence table holds: taken by its
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
|
|
110
|
+
/** The rows of a call's one read of the bytes it judges (`judged`) — a call the leg's occurrence table holds: taken by its
|
|
111
|
+
* first consumer, handed to every other that judges the same bytes (or names none) until the table no longer holds that
|
|
112
|
+
* attempt; a judgment of OTHER bytes of the call (an approved edit, its outlet form) takes a new read, which the call then
|
|
113
|
+
* holds — a judgment reads the store, as the session rules' does. Any other judgment (no leg, or an id the table does not
|
|
114
|
+
* hold — a visibility probe) takes a read of its own, kept by nobody. Bounded ({@link PERSON_READ_BOUND_MS}); never rejects. */
|
|
115
|
+
pin(toolCallId: string, judged?: unknown): Promise<PersonRowsRead>;
|
|
113
116
|
/** Settles once the tables a reader takes are compiled: a pinned call's own; any other reader's (no id, or a call holding
|
|
114
117
|
* no pin), the unit's newest — through every change that lands meanwhile, within {@link PATH_TABLES_READY_BOUND_MS} —
|
|
115
118
|
* or at `signal` or the run's cut ({@link PersonPathRowsConfig.signal}). Never rejects: a reader whose wait was cut
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ownerStoreOf } from "../permission-rule-provider.js";
|
|
2
|
+
import { readPrincipal } from "../principal-name.js";
|
|
2
3
|
import { ORG_ADJUDICATION_TIMEOUT_MS } from "../permission-rule-org.js";
|
|
4
|
+
import { canonicalize } from "../canonical-json.js";
|
|
3
5
|
import { PATH_RULE_FACES, READ_RULE_TOOL, eligiblePersisted, noticeRuleText } from "../permission-rule-model.js";
|
|
4
6
|
import { bindPathRules, persistedRowAnchors, projectScopeIdentity } from "../path-rule-binding.js";
|
|
5
7
|
import { DEFAULT_GATE_AWAIT_TIMEOUT_MS, gateWaitFailureOf, withGateTimeout } from "../gate-bounded-await.js";
|
|
@@ -21,7 +23,7 @@ const COMPILED_TABLES_KEPT = 8;
|
|
|
21
23
|
export const EMPTY_READ_ROOTS = Object.assign(() => [], { forCall: () => () => [], ready: () => Promise.resolve() });
|
|
22
24
|
export function createPersonPathRows(cfg) {
|
|
23
25
|
const provider = cfg.provider;
|
|
24
|
-
const anonymous = cfg.principal
|
|
26
|
+
const anonymous = readPrincipal(cfg.principal).kind === "absent";
|
|
25
27
|
const holdsPersonRows = provider !== undefined && provider.partitions.durable && (!anonymous || cfg.localOwnerDeclared);
|
|
26
28
|
const partitions = PARTITIONS.filter((p) => (p === "durable" ? provider?.partitions.durable === true : provider?.partitions.session === true));
|
|
27
29
|
const unit = { durable: { failedSeq: 0 }, session: { failedSeq: 0 } };
|
|
@@ -186,20 +188,29 @@ export function createPersonPathRows(cfg) {
|
|
|
186
188
|
pins.delete(toolCallId);
|
|
187
189
|
return undefined;
|
|
188
190
|
};
|
|
189
|
-
const enter = (toolCallId, attempt) => {
|
|
191
|
+
const enter = (toolCallId, attempt, judged) => {
|
|
190
192
|
const rows = readOnce("call").then((read) => (entry.read = read));
|
|
191
|
-
const entry = { attempt, rows, tables: holdsPersonRows ? rows.then((read) => settleTables(entry, read)) : Promise.resolve(), ...(holdsPersonRows ? {} : { settled: {} }) };
|
|
193
|
+
const entry = { attempt, rows, tables: holdsPersonRows ? rows.then((read) => settleTables(entry, read)) : Promise.resolve(), ...(holdsPersonRows ? {} : { settled: {} }), ...(judged !== undefined ? { judged: { value: judged } } : {}) };
|
|
192
194
|
pins.set(toolCallId, entry);
|
|
193
195
|
return entry;
|
|
194
196
|
};
|
|
195
|
-
const
|
|
197
|
+
const serves = (p, judged) => {
|
|
198
|
+
if (judged === undefined || p.judged === undefined || p.judged.value === judged)
|
|
199
|
+
return true;
|
|
200
|
+
p.judged.canonical ??= canonicalize(p.judged.value);
|
|
201
|
+
return p.judged.canonical === canonicalize(judged);
|
|
202
|
+
};
|
|
203
|
+
const pin = (toolCallId, judged) => {
|
|
196
204
|
for (const id of [...pins.keys()])
|
|
197
205
|
pinOf(id);
|
|
198
206
|
const known = pinOf(toolCallId);
|
|
199
|
-
if (known !== undefined)
|
|
207
|
+
if (known !== undefined && serves(known, judged)) {
|
|
208
|
+
if (judged !== undefined)
|
|
209
|
+
known.judged ??= { value: judged };
|
|
200
210
|
return known.rows;
|
|
211
|
+
}
|
|
201
212
|
const attempt = cfg.occurrences?.get(toolCallId);
|
|
202
|
-
return attempt === undefined ? readOnce("call") : enter(toolCallId, attempt).rows;
|
|
213
|
+
return attempt === undefined ? readOnce("call") : enter(toolCallId, attempt, judged).rows;
|
|
203
214
|
};
|
|
204
215
|
const settleTables = async (entry, read) => {
|
|
205
216
|
try {
|
|
@@ -317,7 +328,7 @@ export function onPinnedRead(rows, stations) {
|
|
|
317
328
|
const id = callOpts.toolCallId;
|
|
318
329
|
if (readStationMemberOf(call, members) === undefined)
|
|
319
330
|
return check.judge(call, args, cwd, signal, callOpts);
|
|
320
|
-
const ready = id !== undefined && rows.holds(id) ? rows.pin(id).then(() => rows.tablesReady(id)) : rows.tablesReady(undefined, signal);
|
|
331
|
+
const ready = id !== undefined && rows.holds(id) ? rows.pin(id, args).then(() => rows.tablesReady(id)) : rows.tablesReady(undefined, signal);
|
|
321
332
|
return ready.then(() => check.judge(call, args, cwd, signal, callOpts) ?? VOUCHED);
|
|
322
333
|
},
|
|
323
334
|
unanswered: (call, cause) => check.unanswered(call, cause),
|
|
@@ -24,6 +24,7 @@ import { type RecoveredOrphan } from "../session-reconcile.js";
|
|
|
24
24
|
import type { TaskSpec, ToolEffect } from "../types.js";
|
|
25
25
|
import type { PrepareResume } from "./contracts.js";
|
|
26
26
|
import { type ResumeAtBranch } from "./branch-writeback.js";
|
|
27
|
+
import { type LegWrites } from "./session-write-ledger.js";
|
|
27
28
|
export interface PrepareAcquireReconcileInput {
|
|
28
29
|
/** borrowed-mutable (service port) — the deployment's session store. This phase's verbs on it are
|
|
29
30
|
* the acquire/forget half of the session resource protocol: `acquire` per attempt, `forget` to
|
|
@@ -54,6 +55,8 @@ export interface PrepareAcquireReconcileInput {
|
|
|
54
55
|
durableParkGap?: string;
|
|
55
56
|
/** borrowed-readonly — the incident channel for this phase's own cleanup legs: a `resumeAt` branch it could not write back, a forget that did not settle. */
|
|
56
57
|
report?: (err: Error, sessionId: string) => void;
|
|
58
|
+
/** borrowed-mutable (the Runner's) — this leg's view of the session write ledger, every storage write issued through it ({@link writesThroughLeg}); absent for a standalone prepare. */
|
|
59
|
+
legWrites?: LegWrites;
|
|
57
60
|
}
|
|
58
61
|
/** The phase's outputs (four-class form). All six are fresh bindings —
|
|
59
62
|
* the driver destructures them into consts, so a consumer moved ahead of this call is a lexical
|