@namzu/sdk 49.0.0 → 50.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +541 -0
- package/README.md +137 -125
- package/dist/agents/QueryAgent.d.ts.map +1 -1
- package/dist/agents/QueryAgent.js +1 -0
- package/dist/agents/QueryAgent.js.map +1 -1
- package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/examples/SupervisorAgent.js +1 -0
- package/dist/agents/examples/SupervisorAgent.js.map +1 -1
- package/dist/agents/runAgent.d.ts +2 -0
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js +1 -0
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/authorization/shell-lexer.d.ts.map +1 -1
- package/dist/authorization/shell-lexer.js +16 -1
- package/dist/authorization/shell-lexer.js.map +1 -1
- package/dist/bridge/acp/permission.d.ts +8 -2
- package/dist/bridge/acp/permission.d.ts.map +1 -1
- package/dist/bridge/acp/permission.js +1 -0
- package/dist/bridge/acp/permission.js.map +1 -1
- package/dist/bridge/acp/server.d.ts +25 -1
- package/dist/bridge/acp/server.d.ts.map +1 -1
- package/dist/bridge/acp/server.js +205 -21
- package/dist/bridge/acp/server.js.map +1 -1
- package/dist/bridge/acp/tasks.d.ts +5 -0
- package/dist/bridge/acp/tasks.d.ts.map +1 -0
- package/dist/bridge/acp/tasks.js +19 -0
- package/dist/bridge/acp/tasks.js.map +1 -0
- package/dist/bridge/acp/update.d.ts.map +1 -1
- package/dist/bridge/acp/update.js +148 -13
- package/dist/bridge/acp/update.js.map +1 -1
- package/dist/config/runtime.d.ts +31 -31
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +11 -4
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +6 -3
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/constants/acp/index.d.ts +3 -0
- package/dist/constants/acp/index.d.ts.map +1 -1
- package/dist/constants/acp/index.js +3 -0
- package/dist/constants/acp/index.js.map +1 -1
- package/dist/contracts/a2a.d.ts +80 -80
- package/dist/contracts/schemas.d.ts +2 -2
- package/dist/contracts/session/schemas.d.ts +10 -10
- package/dist/manager/agent/lifecycle.d.ts +11 -0
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +178 -3
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/plan/lifecycle.d.ts +7 -8
- package/dist/manager/plan/lifecycle.d.ts.map +1 -1
- package/dist/manager/plan/lifecycle.js +7 -8
- package/dist/manager/plan/lifecycle.js.map +1 -1
- package/dist/manager/resident/consumption.d.ts +8 -8
- package/dist/manager/resident/learning-cycle.d.ts +2 -2
- package/dist/manager/resident/learning-observation.d.ts +12 -12
- package/dist/manager/resident/learning.d.ts +82 -82
- package/dist/manager/resident/outbox.d.ts +8 -8
- package/dist/manager/resident/proposal.d.ts +2 -2
- package/dist/manager/resident/store.d.ts +10 -10
- package/dist/manager/session/attribution.d.ts +1 -0
- package/dist/manager/session/attribution.d.ts.map +1 -1
- package/dist/manager/session/attribution.js +9 -1
- package/dist/manager/session/attribution.js.map +1 -1
- package/dist/manager/session/streamed-message-identity.d.ts +6 -0
- package/dist/manager/session/streamed-message-identity.d.ts.map +1 -0
- package/dist/manager/session/streamed-message-identity.js +14 -0
- package/dist/manager/session/streamed-message-identity.js.map +1 -0
- package/dist/manager/session/turn-recorder.d.ts.map +1 -1
- package/dist/manager/session/turn-recorder.js +4 -3
- package/dist/manager/session/turn-recorder.js.map +1 -1
- package/dist/pals/activity/causality.d.ts +23 -0
- package/dist/pals/activity/causality.d.ts.map +1 -0
- package/dist/pals/activity/causality.js +205 -0
- package/dist/pals/activity/causality.js.map +1 -0
- package/dist/pals/activity/projection.d.ts +5 -0
- package/dist/pals/activity/projection.d.ts.map +1 -0
- package/dist/pals/activity/projection.js +79 -0
- package/dist/pals/activity/projection.js.map +1 -0
- package/dist/pals/activity/source.d.ts +16 -0
- package/dist/pals/activity/source.d.ts.map +1 -0
- package/dist/pals/activity/source.js +235 -0
- package/dist/pals/activity/source.js.map +1 -0
- package/dist/pals/activity/subscription-policy.d.ts +38 -0
- package/dist/pals/activity/subscription-policy.d.ts.map +1 -0
- package/dist/pals/activity/subscription-policy.js +183 -0
- package/dist/pals/activity/subscription-policy.js.map +1 -0
- package/dist/pals/activity/subscription-schema.d.ts +353 -0
- package/dist/pals/activity/subscription-schema.d.ts.map +1 -0
- package/dist/pals/activity/subscription-schema.js +24 -0
- package/dist/pals/activity/subscription-schema.js.map +1 -0
- package/dist/pals/activity/subscription-store.d.ts +25 -0
- package/dist/pals/activity/subscription-store.d.ts.map +1 -0
- package/dist/pals/activity/subscription-store.js +152 -0
- package/dist/pals/activity/subscription-store.js.map +1 -0
- package/dist/pals/activity/subscription-types.d.ts +42 -0
- package/dist/pals/activity/subscription-types.d.ts.map +1 -0
- package/dist/pals/activity/subscription-types.js +2 -0
- package/dist/pals/activity/subscription-types.js.map +1 -0
- package/dist/pals/activity/subscriptions.d.ts +32 -0
- package/dist/pals/activity/subscriptions.d.ts.map +1 -0
- package/dist/pals/activity/subscriptions.js +151 -0
- package/dist/pals/activity/subscriptions.js.map +1 -0
- package/dist/pals/activity/types.d.ts +77 -0
- package/dist/pals/activity/types.d.ts.map +1 -0
- package/dist/pals/activity/types.js +2 -0
- package/dist/pals/activity/types.js.map +1 -0
- package/dist/pals/channels/ingress.d.ts +9 -0
- package/dist/pals/channels/ingress.d.ts.map +1 -0
- package/dist/pals/channels/ingress.js +131 -0
- package/dist/pals/channels/ingress.js.map +1 -0
- package/dist/pals/channels/routes.d.ts +20 -0
- package/dist/pals/channels/routes.d.ts.map +1 -0
- package/dist/pals/channels/routes.js +111 -0
- package/dist/pals/channels/routes.js.map +1 -0
- package/dist/pals/channels/routing.d.ts +37 -0
- package/dist/pals/channels/routing.d.ts.map +1 -0
- package/dist/pals/channels/routing.js +150 -0
- package/dist/pals/channels/routing.js.map +1 -0
- package/dist/pals/channels/schema.d.ts +234 -0
- package/dist/pals/channels/schema.d.ts.map +1 -0
- package/dist/pals/channels/schema.js +94 -0
- package/dist/pals/channels/schema.js.map +1 -0
- package/dist/pals/channels/types.d.ts +115 -0
- package/dist/pals/channels/types.d.ts.map +1 -0
- package/dist/pals/channels/types.js +2 -0
- package/dist/pals/channels/types.js.map +1 -0
- package/dist/pals/communication/broker.d.ts +8 -0
- package/dist/pals/communication/broker.d.ts.map +1 -0
- package/dist/pals/communication/broker.js +121 -0
- package/dist/pals/communication/broker.js.map +1 -0
- package/dist/pals/communication/dispatch.d.ts +4 -0
- package/dist/pals/communication/dispatch.d.ts.map +1 -0
- package/dist/pals/communication/dispatch.js +57 -0
- package/dist/pals/communication/dispatch.js.map +1 -0
- package/dist/pals/communication/inbound.d.ts +9 -0
- package/dist/pals/communication/inbound.d.ts.map +1 -0
- package/dist/pals/communication/inbound.js +155 -0
- package/dist/pals/communication/inbound.js.map +1 -0
- package/dist/pals/communication/ingress-dispatch.d.ts +5 -0
- package/dist/pals/communication/ingress-dispatch.d.ts.map +1 -0
- package/dist/pals/communication/ingress-dispatch.js +51 -0
- package/dist/pals/communication/ingress-dispatch.js.map +1 -0
- package/dist/pals/communication/ingress-inbound.d.ts +9 -0
- package/dist/pals/communication/ingress-inbound.d.ts.map +1 -0
- package/dist/pals/communication/ingress-inbound.js +222 -0
- package/dist/pals/communication/ingress-inbound.js.map +1 -0
- package/dist/pals/communication/ingress-schema.d.ts +7829 -0
- package/dist/pals/communication/ingress-schema.d.ts.map +1 -0
- package/dist/pals/communication/ingress-schema.js +479 -0
- package/dist/pals/communication/ingress-schema.js.map +1 -0
- package/dist/pals/communication/ingress-types.d.ts +187 -0
- package/dist/pals/communication/ingress-types.d.ts.map +1 -0
- package/dist/pals/communication/ingress-types.js +73 -0
- package/dist/pals/communication/ingress-types.js.map +1 -0
- package/dist/pals/communication/operator.d.ts +75 -0
- package/dist/pals/communication/operator.d.ts.map +1 -0
- package/dist/pals/communication/operator.js +217 -0
- package/dist/pals/communication/operator.js.map +1 -0
- package/dist/pals/communication/policy.d.ts +41 -0
- package/dist/pals/communication/policy.d.ts.map +1 -0
- package/dist/pals/communication/policy.js +138 -0
- package/dist/pals/communication/policy.js.map +1 -0
- package/dist/pals/communication/schema.d.ts +2000 -0
- package/dist/pals/communication/schema.d.ts.map +1 -0
- package/dist/pals/communication/schema.js +170 -0
- package/dist/pals/communication/schema.js.map +1 -0
- package/dist/pals/communication/store.d.ts +61 -0
- package/dist/pals/communication/store.d.ts.map +1 -0
- package/dist/pals/communication/store.js +450 -0
- package/dist/pals/communication/store.js.map +1 -0
- package/dist/pals/communication/tools.d.ts +23 -0
- package/dist/pals/communication/tools.d.ts.map +1 -0
- package/dist/pals/communication/tools.js +107 -0
- package/dist/pals/communication/tools.js.map +1 -0
- package/dist/pals/communication/types.d.ts +168 -0
- package/dist/pals/communication/types.d.ts.map +1 -0
- package/dist/pals/communication/types.js +24 -0
- package/dist/pals/communication/types.js.map +1 -0
- package/dist/pals/communication/verify.d.ts +22 -0
- package/dist/pals/communication/verify.d.ts.map +1 -0
- package/dist/pals/communication/verify.js +142 -0
- package/dist/pals/communication/verify.js.map +1 -0
- package/dist/pals/lifecycle.d.ts +37 -0
- package/dist/pals/lifecycle.d.ts.map +1 -0
- package/dist/pals/lifecycle.js +22 -0
- package/dist/pals/lifecycle.js.map +1 -0
- package/dist/pals/prompt.d.ts +30 -0
- package/dist/pals/prompt.d.ts.map +1 -0
- package/dist/pals/prompt.js +65 -0
- package/dist/pals/prompt.js.map +1 -0
- package/dist/pals/reference-images.d.ts +44 -0
- package/dist/pals/reference-images.d.ts.map +1 -0
- package/dist/pals/reference-images.js +248 -0
- package/dist/pals/reference-images.js.map +1 -0
- package/dist/pals/runtime.d.ts +46 -0
- package/dist/pals/runtime.d.ts.map +1 -0
- package/dist/pals/runtime.js +624 -0
- package/dist/pals/runtime.js.map +1 -0
- package/dist/pals/store.d.ts +26 -0
- package/dist/pals/store.d.ts.map +1 -0
- package/dist/pals/store.js +334 -0
- package/dist/pals/store.js.map +1 -0
- package/dist/pals/types.d.ts +145 -0
- package/dist/pals/types.d.ts.map +1 -0
- package/dist/pals/types.js +2 -0
- package/dist/pals/types.js.map +1 -0
- package/dist/peers/envelope.js +1 -1
- package/dist/peers/envelope.js.map +1 -1
- package/dist/peers/protocol.d.ts +83 -83
- package/dist/peers/record.d.ts +10 -10
- package/dist/plugin/shell-hook.d.ts.map +1 -1
- package/dist/plugin/shell-hook.js +7 -2
- package/dist/plugin/shell-hook.js.map +1 -1
- package/dist/process/kill-tree.d.ts.map +1 -1
- package/dist/process/kill-tree.js +9 -1
- package/dist/process/kill-tree.js.map +1 -1
- package/dist/provider/errors.d.ts +19 -0
- package/dist/provider/errors.d.ts.map +1 -1
- package/dist/provider/errors.js +123 -2
- package/dist/provider/errors.js.map +1 -1
- package/dist/provider/strict-schema.d.ts +28 -0
- package/dist/provider/strict-schema.d.ts.map +1 -1
- package/dist/provider/strict-schema.js +86 -0
- package/dist/provider/strict-schema.js.map +1 -1
- package/dist/public-runtime.d.ts +42 -14
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +36 -8
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +8 -3
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +8 -3
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +27 -7
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/tool/presentation.d.ts +1 -0
- package/dist/registry/tool/presentation.d.ts.map +1 -1
- package/dist/registry/tool/presentation.js +9 -7
- package/dist/registry/tool/presentation.js.map +1 -1
- package/dist/runtime/harness-session/index.d.ts +5 -0
- package/dist/runtime/harness-session/index.d.ts.map +1 -0
- package/dist/runtime/harness-session/index.js +928 -0
- package/dist/runtime/harness-session/index.js.map +1 -0
- package/dist/runtime/harness-session/journal.d.ts +37 -0
- package/dist/runtime/harness-session/journal.d.ts.map +1 -0
- package/dist/runtime/harness-session/journal.js +177 -0
- package/dist/runtime/harness-session/journal.js.map +1 -0
- package/dist/runtime/harness-session/saved-view.d.ts +8 -0
- package/dist/runtime/harness-session/saved-view.d.ts.map +1 -0
- package/dist/runtime/harness-session/saved-view.js +112 -0
- package/dist/runtime/harness-session/saved-view.js.map +1 -0
- package/dist/runtime/jobs/awaited-jobs.d.ts +2 -1
- package/dist/runtime/jobs/awaited-jobs.d.ts.map +1 -1
- package/dist/runtime/jobs/awaited-jobs.js +2 -1
- package/dist/runtime/jobs/awaited-jobs.js.map +1 -1
- package/dist/runtime/jobs/registry.d.ts +56 -1
- package/dist/runtime/jobs/registry.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.js +351 -34
- package/dist/runtime/jobs/registry.js.map +1 -1
- package/dist/runtime/query/abandon-turn.d.ts +12 -1
- package/dist/runtime/query/abandon-turn.d.ts.map +1 -1
- package/dist/runtime/query/abandon-turn.js +3 -1
- package/dist/runtime/query/abandon-turn.js.map +1 -1
- package/dist/runtime/query/checkpoint.d.ts +4 -0
- package/dist/runtime/query/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/checkpoint.js +10 -0
- package/dist/runtime/query/checkpoint.js.map +1 -1
- package/dist/runtime/query/durable-inbound.d.ts +5 -0
- package/dist/runtime/query/durable-inbound.d.ts.map +1 -0
- package/dist/runtime/query/durable-inbound.js +89 -0
- package/dist/runtime/query/durable-inbound.js.map +1 -0
- package/dist/runtime/query/events.d.ts +4 -0
- package/dist/runtime/query/events.d.ts.map +1 -1
- package/dist/runtime/query/events.js +22 -5
- package/dist/runtime/query/events.js.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.d.ts +5 -1
- package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.js +85 -13
- package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +41 -18
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +227 -114
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +3 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +21 -4
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +18 -6
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +144 -67
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/outstanding-work.d.ts +9 -5
- package/dist/runtime/query/iteration/outstanding-work.d.ts.map +1 -1
- package/dist/runtime/query/iteration/outstanding-work.js +61 -6
- package/dist/runtime/query/iteration/outstanding-work.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +4 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +99 -16
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/observation-context.d.ts +2 -2
- package/dist/runtime/query/observation-context.d.ts.map +1 -1
- package/dist/runtime/query/observation-context.js +20 -13
- package/dist/runtime/query/observation-context.js.map +1 -1
- package/dist/runtime/query/prepare-turn.js +2 -2
- package/dist/runtime/query/prepare-turn.js.map +1 -1
- package/dist/runtime/query/prompt-cache.d.ts +1 -0
- package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
- package/dist/runtime/query/prompt-cache.js +2 -0
- package/dist/runtime/query/prompt-cache.js.map +1 -1
- package/dist/runtime/query/prompt.d.ts +2 -0
- package/dist/runtime/query/prompt.d.ts.map +1 -1
- package/dist/runtime/query/prompt.js +23 -1
- package/dist/runtime/query/prompt.js.map +1 -1
- package/dist/runtime/query/repeat-call.d.ts +12 -3
- package/dist/runtime/query/repeat-call.d.ts.map +1 -1
- package/dist/runtime/query/repeat-call.js +33 -10
- package/dist/runtime/query/repeat-call.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts +5 -6
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +30 -3
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/resume-session.js +1 -1
- package/dist/runtime/query/resume-session.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +8 -1
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +6 -0
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/saved-presentation.d.ts +13 -0
- package/dist/runtime/query/saved-presentation.d.ts.map +1 -0
- package/dist/runtime/query/saved-presentation.js +63 -0
- package/dist/runtime/query/saved-presentation.js.map +1 -0
- package/dist/runtime/query/steering.d.ts +6 -9
- package/dist/runtime/query/steering.d.ts.map +1 -1
- package/dist/runtime/query/steering.js.map +1 -1
- package/dist/runtime/query/tool-executions.d.ts +7 -3
- package/dist/runtime/query/tool-executions.d.ts.map +1 -1
- package/dist/runtime/query/tool-executions.js +89 -9
- package/dist/runtime/query/tool-executions.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +3 -1
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +3 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/scheduler/completion-inbox.d.ts +25 -1
- package/dist/scheduler/completion-inbox.d.ts.map +1 -1
- package/dist/scheduler/completion-inbox.js +102 -8
- package/dist/scheduler/completion-inbox.js.map +1 -1
- package/dist/scheduler/delegating.d.ts.map +1 -1
- package/dist/scheduler/delegating.js +5 -0
- package/dist/scheduler/delegating.js.map +1 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +2 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/session/summary/materialize.d.ts +10 -6
- package/dist/session/summary/materialize.d.ts.map +1 -1
- package/dist/session/summary/materialize.js +41 -8
- package/dist/session/summary/materialize.js.map +1 -1
- package/dist/store/budget/ledger.d.ts +9 -0
- package/dist/store/budget/ledger.d.ts.map +1 -1
- package/dist/store/budget/ledger.js +58 -6
- package/dist/store/budget/ledger.js.map +1 -1
- package/dist/store/evidence/index-page.d.ts +12 -12
- package/dist/store/evidence/source-text.d.ts +4 -4
- package/dist/store/session/disk.d.ts +9 -4
- package/dist/store/session/disk.d.ts.map +1 -1
- package/dist/store/session/disk.js +57 -11
- package/dist/store/session/disk.js.map +1 -1
- package/dist/store/session/memory.d.ts +5 -3
- package/dist/store/session/memory.d.ts.map +1 -1
- package/dist/store/session/memory.js +24 -7
- package/dist/store/session/memory.js.map +1 -1
- package/dist/store/session-log/core.d.ts +26 -6
- package/dist/store/session-log/core.d.ts.map +1 -1
- package/dist/store/session-log/core.js +61 -8
- package/dist/store/session-log/core.js.map +1 -1
- package/dist/store/session-log/disk.d.ts +2 -2
- package/dist/store/session-log/disk.d.ts.map +1 -1
- package/dist/store/session-log/disk.js +1 -0
- package/dist/store/session-log/disk.js.map +1 -1
- package/dist/store/session-log/fold.d.ts +7 -0
- package/dist/store/session-log/fold.d.ts.map +1 -1
- package/dist/store/session-log/fold.js +21 -0
- package/dist/store/session-log/fold.js.map +1 -1
- package/dist/store/session-log/index.d.ts +5 -3
- package/dist/store/session-log/index.d.ts.map +1 -1
- package/dist/store/session-log/index.js +3 -1
- package/dist/store/session-log/index.js.map +1 -1
- package/dist/store/session-log/memory.d.ts +1 -1
- package/dist/store/session-log/memory.d.ts.map +1 -1
- package/dist/store/session-log/memory.js +1 -0
- package/dist/store/session-log/memory.js.map +1 -1
- package/dist/store/session-log/spill.d.ts +10 -3
- package/dist/store/session-log/spill.d.ts.map +1 -1
- package/dist/store/session-log/spill.js +70 -5
- package/dist/store/session-log/spill.js.map +1 -1
- package/dist/store/session-log/structured-result.d.ts +21 -0
- package/dist/store/session-log/structured-result.d.ts.map +1 -0
- package/dist/store/session-log/structured-result.js +67 -0
- package/dist/store/session-log/structured-result.js.map +1 -0
- package/dist/store/task/disk.d.ts +11 -0
- package/dist/store/task/disk.d.ts.map +1 -1
- package/dist/store/task/disk.js +41 -2
- package/dist/store/task/disk.js.map +1 -1
- package/dist/store/task/memory.d.ts.map +1 -1
- package/dist/store/task/memory.js +15 -3
- package/dist/store/task/memory.js.map +1 -1
- package/dist/tools/admit-facts.d.ts +13 -0
- package/dist/tools/admit-facts.d.ts.map +1 -0
- package/dist/tools/admit-facts.js +142 -0
- package/dist/tools/admit-facts.js.map +1 -0
- package/dist/tools/builtins/bash.d.ts +4 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +108 -22
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/browser.d.ts +10 -10
- package/dist/tools/builtins/computer-use.d.ts +90 -90
- package/dist/tools/builtins/edit.d.ts +17 -0
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +46 -1
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/file-write-result.d.ts.map +1 -1
- package/dist/tools/builtins/file-write-result.js +13 -0
- package/dist/tools/builtins/file-write-result.js.map +1 -1
- package/dist/tools/builtins/glob.d.ts.map +1 -1
- package/dist/tools/builtins/glob.js +12 -0
- package/dist/tools/builtins/glob.js.map +1 -1
- package/dist/tools/builtins/grep.d.ts.map +1 -1
- package/dist/tools/builtins/grep.js +14 -0
- package/dist/tools/builtins/grep.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +2 -0
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +1 -0
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/job.d.ts.map +1 -1
- package/dist/tools/builtins/job.js +4 -1
- package/dist/tools/builtins/job.js.map +1 -1
- package/dist/tools/builtins/lsp.d.ts +2 -2
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +49 -0
- package/dist/tools/builtins/read-file.js.map +1 -1
- package/dist/tools/builtins/view-image.d.ts +24 -0
- package/dist/tools/builtins/view-image.d.ts.map +1 -0
- package/dist/tools/builtins/view-image.js +385 -0
- package/dist/tools/builtins/view-image.js.map +1 -0
- package/dist/tools/builtins/wait-for-job-bounds.d.ts +2 -0
- package/dist/tools/builtins/wait-for-job-bounds.d.ts.map +1 -1
- package/dist/tools/builtins/wait-for-job-bounds.js +1 -0
- package/dist/tools/builtins/wait-for-job-bounds.js.map +1 -1
- package/dist/tools/builtins/wait-for-job.d.ts +2 -0
- package/dist/tools/builtins/wait-for-job.d.ts.map +1 -1
- package/dist/tools/builtins/wait-for-job.js +104 -6
- package/dist/tools/builtins/wait-for-job.js.map +1 -1
- package/dist/tools/builtins/write-file.d.ts.map +1 -1
- package/dist/tools/builtins/write-file.js +1 -0
- package/dist/tools/builtins/write-file.js.map +1 -1
- package/dist/tools/command-shell.d.ts +37 -2
- package/dist/tools/command-shell.d.ts.map +1 -1
- package/dist/tools/command-shell.js +100 -3
- package/dist/tools/command-shell.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts +9 -19
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +127 -67
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/coordinator/wait-with-idle-bound.d.ts +2 -0
- package/dist/tools/coordinator/wait-with-idle-bound.d.ts.map +1 -1
- package/dist/tools/coordinator/wait-with-idle-bound.js +1 -1
- package/dist/tools/coordinator/wait-with-idle-bound.js.map +1 -1
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +4 -0
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/failure-facts.d.ts +8 -0
- package/dist/tools/failure-facts.d.ts.map +1 -0
- package/dist/tools/failure-facts.js +24 -0
- package/dist/tools/failure-facts.js.map +1 -0
- package/dist/tools/host-output.d.ts +24 -0
- package/dist/tools/host-output.d.ts.map +1 -0
- package/dist/tools/host-output.js +117 -0
- package/dist/tools/host-output.js.map +1 -0
- package/dist/tools/oem-code-pages.d.ts +8 -0
- package/dist/tools/oem-code-pages.d.ts.map +1 -0
- package/dist/tools/oem-code-pages.js +23 -0
- package/dist/tools/oem-code-pages.js.map +1 -0
- package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
- package/dist/tools/schedules/schedule-tool.js +35 -6
- package/dist/tools/schedules/schedule-tool.js.map +1 -1
- package/dist/tools/schedules/types.d.ts +23 -3
- package/dist/tools/schedules/types.d.ts.map +1 -1
- package/dist/tools/task/list.d.ts.map +1 -1
- package/dist/tools/task/list.js +14 -6
- package/dist/tools/task/list.js.map +1 -1
- package/dist/tools/task/present.d.ts.map +1 -1
- package/dist/tools/task/present.js +26 -6
- package/dist/tools/task/present.js.map +1 -1
- package/dist/tools/task/update.d.ts.map +1 -1
- package/dist/tools/task/update.js +12 -5
- package/dist/tools/task/update.js.map +1 -1
- package/dist/tools/text-window.d.ts +19 -0
- package/dist/tools/text-window.d.ts.map +1 -0
- package/dist/tools/text-window.js +83 -0
- package/dist/tools/text-window.js.map +1 -0
- package/dist/toolsets/manager.d.ts +11 -0
- package/dist/toolsets/manager.d.ts.map +1 -1
- package/dist/toolsets/manager.js +45 -1
- package/dist/toolsets/manager.js.map +1 -1
- package/dist/types/acp/index.d.ts +137 -1
- package/dist/types/acp/index.d.ts.map +1 -1
- package/dist/types/agent/base.d.ts +3 -0
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/manager.d.ts +8 -23
- package/dist/types/agent/manager.d.ts.map +1 -1
- package/dist/types/agent/scheduler.d.ts +10 -1
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +4 -0
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/authorization/index.d.ts +30 -30
- package/dist/types/connector/mcp.d.ts +7 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/errors/catalog.d.ts.map +1 -1
- package/dist/types/errors/catalog.js +4 -2
- package/dist/types/errors/catalog.js.map +1 -1
- package/dist/types/harness/schema.d.ts +354 -0
- package/dist/types/harness/schema.d.ts.map +1 -0
- package/dist/types/harness/schema.js +203 -0
- package/dist/types/harness/schema.js.map +1 -0
- package/dist/types/harness/session.d.ts +278 -0
- package/dist/types/harness/session.d.ts.map +1 -0
- package/dist/types/harness/session.js +2 -0
- package/dist/types/harness/session.js.map +1 -0
- package/dist/types/hitl/index.d.ts +12 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/job/index.d.ts +47 -0
- package/dist/types/job/index.d.ts.map +1 -0
- package/dist/types/job/index.js +2 -0
- package/dist/types/job/index.js.map +1 -0
- package/dist/types/message/inbound-delivery.d.ts +44 -0
- package/dist/types/message/inbound-delivery.d.ts.map +1 -0
- package/dist/types/message/inbound-delivery.js +14 -0
- package/dist/types/message/inbound-delivery.js.map +1 -0
- package/dist/types/message/index.d.ts +4 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +5 -1
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +6 -6
- package/dist/types/sandbox/index.d.ts +39 -2
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/session/checkpoint.d.ts +24 -17
- package/dist/types/session/checkpoint.d.ts.map +1 -1
- package/dist/types/session/checkpoint.js +1 -0
- package/dist/types/session/checkpoint.js.map +1 -1
- package/dist/types/session/events.d.ts +23 -1
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/session/records.d.ts +1514 -565
- package/dist/types/session/records.d.ts.map +1 -1
- package/dist/types/session/records.js +89 -1
- package/dist/types/session/records.js.map +1 -1
- package/dist/types/session/step.d.ts +2 -0
- package/dist/types/session/step.d.ts.map +1 -1
- package/dist/types/session/step.js.map +1 -1
- package/dist/types/session/store.d.ts +19 -10
- package/dist/types/session/store.d.ts.map +1 -1
- package/dist/types/session/tool-execution.d.ts +6 -0
- package/dist/types/session/tool-execution.d.ts.map +1 -1
- package/dist/types/structured-output/index.d.ts +12 -2
- package/dist/types/structured-output/index.d.ts.map +1 -1
- package/dist/types/summary/ref.d.ts +3 -1
- package/dist/types/summary/ref.d.ts.map +1 -1
- package/dist/types/tool/index.d.ts +32 -4
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/types/tool/presentation.d.ts +106 -0
- package/dist/types/tool/presentation.d.ts.map +1 -1
- package/dist/utils/json-snapshot.d.ts +6 -2
- package/dist/utils/json-snapshot.d.ts.map +1 -1
- package/dist/utils/json-snapshot.js +19 -9
- package/dist/utils/json-snapshot.js.map +1 -1
- package/dist/utils/structured-result-json.d.ts +5 -0
- package/dist/utils/structured-result-json.d.ts.map +1 -0
- package/dist/utils/structured-result-json.js +10 -0
- package/dist/utils/structured-result-json.js.map +1 -0
- package/package.json +1 -1
- package/src/agents/QueryAgent.ts +1 -0
- package/src/agents/examples/SupervisorAgent.ts +1 -0
- package/src/agents/runAgent.ts +3 -0
- package/src/authorization/shell-lexer.ts +16 -1
- package/src/bridge/acp/permission.ts +17 -3
- package/src/bridge/acp/server.ts +271 -25
- package/src/bridge/acp/tasks.ts +23 -0
- package/src/bridge/acp/update.ts +167 -13
- package/src/connector/mcp/adapter.ts +16 -4
- package/src/connector/mcp/client.ts +6 -2
- package/src/constants/acp/index.ts +4 -0
- package/src/manager/agent/lifecycle.ts +230 -3
- package/src/manager/plan/lifecycle.ts +11 -9
- package/src/manager/session/attribution.ts +12 -2
- package/src/manager/session/streamed-message-identity.ts +21 -0
- package/src/manager/session/turn-recorder.ts +4 -3
- package/src/pals/activity/causality.ts +261 -0
- package/src/pals/activity/projection.ts +89 -0
- package/src/pals/activity/source.ts +240 -0
- package/src/pals/activity/subscription-policy.ts +230 -0
- package/src/pals/activity/subscription-schema.ts +27 -0
- package/src/pals/activity/subscription-store.ts +172 -0
- package/src/pals/activity/subscription-types.ts +48 -0
- package/src/pals/activity/subscriptions.ts +209 -0
- package/src/pals/activity/types.ts +108 -0
- package/src/pals/channels/ingress.ts +153 -0
- package/src/pals/channels/routes.ts +118 -0
- package/src/pals/channels/routing.ts +197 -0
- package/src/pals/channels/schema.ts +108 -0
- package/src/pals/channels/types.ts +156 -0
- package/src/pals/communication/broker.ts +131 -0
- package/src/pals/communication/dispatch.ts +66 -0
- package/src/pals/communication/inbound.ts +193 -0
- package/src/pals/communication/ingress-dispatch.ts +63 -0
- package/src/pals/communication/ingress-inbound.ts +269 -0
- package/src/pals/communication/ingress-schema.ts +526 -0
- package/src/pals/communication/ingress-types.ts +336 -0
- package/src/pals/communication/operator.ts +315 -0
- package/src/pals/communication/policy.ts +174 -0
- package/src/pals/communication/schema.ts +173 -0
- package/src/pals/communication/store.ts +577 -0
- package/src/pals/communication/tools.ts +139 -0
- package/src/pals/communication/types.ts +227 -0
- package/src/pals/communication/verify.ts +220 -0
- package/src/pals/lifecycle.ts +54 -0
- package/src/pals/prompt.ts +101 -0
- package/src/pals/reference-images.ts +322 -0
- package/src/pals/runtime.ts +670 -0
- package/src/pals/store.ts +369 -0
- package/src/pals/types.ts +157 -0
- package/src/peers/envelope.ts +1 -1
- package/src/plugin/shell-hook.ts +8 -2
- package/src/process/kill-tree.ts +10 -1
- package/src/provider/errors.ts +135 -2
- package/src/provider/strict-schema.ts +90 -0
- package/src/public-runtime.ts +118 -12
- package/src/public-tools.ts +13 -1
- package/src/public-types.ts +69 -7
- package/src/registry/tool/presentation.ts +9 -4
- package/src/runtime/harness-session/index.ts +1125 -0
- package/src/runtime/harness-session/journal.ts +209 -0
- package/src/runtime/harness-session/saved-view.ts +122 -0
- package/src/runtime/jobs/awaited-jobs.ts +2 -1
- package/src/runtime/jobs/registry.ts +397 -41
- package/src/runtime/query/abandon-turn.ts +18 -2
- package/src/runtime/query/checkpoint.ts +11 -0
- package/src/runtime/query/durable-inbound.ts +101 -0
- package/src/runtime/query/events.ts +22 -5
- package/src/runtime/query/executor/tool-call-admission.ts +125 -32
- package/src/runtime/query/executor.ts +316 -130
- package/src/runtime/query/index.ts +24 -4
- package/src/runtime/query/iteration/index.ts +218 -104
- package/src/runtime/query/iteration/outstanding-work.ts +55 -7
- package/src/runtime/query/iteration/phases/context.ts +4 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +118 -21
- package/src/runtime/query/observation-context.ts +22 -16
- package/src/runtime/query/prepare-turn.ts +2 -2
- package/src/runtime/query/prompt-cache.ts +3 -0
- package/src/runtime/query/prompt.ts +32 -1
- package/src/runtime/query/repeat-call.ts +40 -10
- package/src/runtime/query/resume-pending.ts +60 -7
- package/src/runtime/query/resume-session.ts +1 -1
- package/src/runtime/query/review-policy.ts +23 -2
- package/src/runtime/query/saved-presentation.ts +70 -0
- package/src/runtime/query/steering.ts +6 -9
- package/src/runtime/query/tool-executions.ts +108 -9
- package/src/runtime/query/tooling.ts +6 -1
- package/src/scheduler/completion-inbox.ts +108 -7
- package/src/scheduler/delegating.ts +5 -0
- package/src/scheduler/local.ts +2 -0
- package/src/session/summary/materialize.ts +51 -9
- package/src/store/budget/ledger.ts +60 -5
- package/src/store/session/disk.ts +77 -10
- package/src/store/session/memory.ts +32 -7
- package/src/store/session-log/core.ts +118 -11
- package/src/store/session-log/disk.ts +9 -2
- package/src/store/session-log/fold.ts +22 -0
- package/src/store/session-log/index.ts +5 -0
- package/src/store/session-log/memory.ts +2 -1
- package/src/store/session-log/spill.ts +89 -6
- package/src/store/session-log/structured-result.ts +96 -0
- package/src/store/task/disk.ts +46 -2
- package/src/store/task/memory.ts +13 -3
- package/src/tools/admit-facts.ts +145 -0
- package/src/tools/builtins/bash.ts +132 -24
- package/src/tools/builtins/edit.ts +54 -1
- package/src/tools/builtins/file-write-result.ts +14 -0
- package/src/tools/builtins/glob.ts +12 -0
- package/src/tools/builtins/grep.ts +14 -0
- package/src/tools/builtins/index.ts +2 -0
- package/src/tools/builtins/job.ts +4 -1
- package/src/tools/builtins/read-file.ts +57 -0
- package/src/tools/builtins/view-image.ts +409 -0
- package/src/tools/builtins/wait-for-job-bounds.ts +3 -0
- package/src/tools/builtins/wait-for-job.ts +141 -32
- package/src/tools/builtins/write-file.ts +4 -2
- package/src/tools/command-shell.ts +132 -5
- package/src/tools/coordinator/agent.ts +9 -19
- package/src/tools/coordinator/index.ts +150 -75
- package/src/tools/coordinator/wait-with-idle-bound.ts +3 -1
- package/src/tools/defineTool.ts +4 -0
- package/src/tools/failure-facts.ts +24 -0
- package/src/tools/host-output.ts +136 -0
- package/src/tools/oem-code-pages.ts +22 -0
- package/src/tools/schedules/schedule-tool.ts +38 -5
- package/src/tools/schedules/types.ts +23 -3
- package/src/tools/task/list.ts +15 -7
- package/src/tools/task/present.ts +37 -7
- package/src/tools/task/update.ts +12 -5
- package/src/tools/text-window.ts +87 -0
- package/src/toolsets/manager.ts +58 -1
- package/src/types/acp/index.ts +150 -4
- package/src/types/agent/base.ts +3 -0
- package/src/types/agent/manager.ts +8 -23
- package/src/types/agent/scheduler.ts +10 -1
- package/src/types/agent/task.ts +4 -0
- package/src/types/connector/mcp.ts +7 -0
- package/src/types/errors/catalog.ts +4 -2
- package/src/types/harness/schema.ts +203 -0
- package/src/types/harness/session.ts +306 -0
- package/src/types/hitl/index.ts +17 -1
- package/src/types/job/index.ts +42 -0
- package/src/types/message/inbound-delivery.ts +63 -0
- package/src/types/message/index.ts +8 -1
- package/src/types/sandbox/index.ts +46 -0
- package/src/types/session/checkpoint.ts +4 -1
- package/src/types/session/events.ts +23 -1
- package/src/types/session/records.ts +114 -2
- package/src/types/session/step.ts +2 -0
- package/src/types/session/store.ts +23 -9
- package/src/types/session/tool-execution.ts +6 -0
- package/src/types/structured-output/index.ts +13 -2
- package/src/types/summary/ref.ts +3 -1
- package/src/types/tool/index.ts +39 -5
- package/src/types/tool/presentation.ts +121 -0
- package/src/utils/json-snapshot.ts +26 -9
- package/src/utils/structured-result-json.ts +10 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import type { SessionId } from '../../types/ids/index.js'
|
|
4
|
+
import type { InboundDeliveryRef } from '../../types/message/inbound-delivery.js'
|
|
5
|
+
import { isEntityId } from '../../utils/id.js'
|
|
6
|
+
import { ingressInboxSchema } from '../communication/ingress-schema.js'
|
|
7
|
+
import type { PalChannelIntent } from '../communication/ingress-types.js'
|
|
8
|
+
import { PAL_CHANNEL_NAMESPACE, ingressMessageRef } from '../communication/ingress-types.js'
|
|
9
|
+
import { addressSchema, freezeCommunicationValue, label } from '../communication/schema.js'
|
|
10
|
+
import { verifyIngressRecorded } from '../communication/verify.js'
|
|
11
|
+
import { captureConnection, nativeTuple, verifiedActionSchema } from './schema.js'
|
|
12
|
+
import type {
|
|
13
|
+
PalChannelExecutionContext,
|
|
14
|
+
PalChannelResolvedRoute,
|
|
15
|
+
PalChannelRouterOptions,
|
|
16
|
+
PalChannelVerifiedAction,
|
|
17
|
+
} from './types.js'
|
|
18
|
+
|
|
19
|
+
const contextSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
recipient: addressSchema,
|
|
22
|
+
sessionId: z.custom<SessionId>((value) => isEntityId(value, 'session')),
|
|
23
|
+
profileRevision: z.number().int().positive().safe(),
|
|
24
|
+
})
|
|
25
|
+
.strict()
|
|
26
|
+
const refSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
namespace: z.literal(PAL_CHANNEL_NAMESPACE),
|
|
29
|
+
id: z.string().regex(/^[a-f0-9]{64}$/),
|
|
30
|
+
digest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
31
|
+
})
|
|
32
|
+
.strict()
|
|
33
|
+
|
|
34
|
+
/** Resolves original authenticated destinations. It does not imply remote delivery. */
|
|
35
|
+
export class PalChannelRouter {
|
|
36
|
+
private readonly options: PalChannelRouterOptions
|
|
37
|
+
private readonly connection
|
|
38
|
+
constructor(options: PalChannelRouterOptions) {
|
|
39
|
+
if (typeof options.verify !== 'function' || typeof options.authorize !== 'function')
|
|
40
|
+
throw new Error('Channel routing requires trusted verification and current authorization.')
|
|
41
|
+
this.options = Object.freeze({ ...options })
|
|
42
|
+
this.connection = captureConnection(options.connection)
|
|
43
|
+
}
|
|
44
|
+
private assertRecipient(context: PalChannelExecutionContext) {
|
|
45
|
+
if (context.recipient.tenantId !== this.connection.tenantId)
|
|
46
|
+
throw new Error('Foreign channel response tenant.')
|
|
47
|
+
const pal = this.options.pals.get(context.recipient.palId)
|
|
48
|
+
if (!pal || pal.paused) throw new Error('Channel response Pal is paused or unavailable.')
|
|
49
|
+
return this.options.pals.getRevision(pal.id, context.profileRevision)
|
|
50
|
+
}
|
|
51
|
+
private async recorded(
|
|
52
|
+
input: InboundDeliveryRef,
|
|
53
|
+
context: PalChannelExecutionContext,
|
|
54
|
+
signal: AbortSignal,
|
|
55
|
+
) {
|
|
56
|
+
const ref = freezeCommunicationValue(refSchema.parse(input))
|
|
57
|
+
const definition = this.assertRecipient(context)
|
|
58
|
+
const snapshot = await this.options.store.readIngress(context.recipient)
|
|
59
|
+
const found = snapshot?.messages.find((message) => message.id === ref.id)
|
|
60
|
+
if (!found) throw new Error('Channel response does not name an accepted delivery.')
|
|
61
|
+
const message = freezeCommunicationValue(ingressInboxSchema.parse(found))
|
|
62
|
+
if (
|
|
63
|
+
!('kind' in message) ||
|
|
64
|
+
message.kind !== 'channel' ||
|
|
65
|
+
message.phase !== 'recorded' ||
|
|
66
|
+
!message.receipt ||
|
|
67
|
+
!isDeepStrictEqual(ingressMessageRef(message), ref)
|
|
68
|
+
)
|
|
69
|
+
throw new Error('Channel response requires the exact recorded channel delivery.')
|
|
70
|
+
if (
|
|
71
|
+
message.source.tenantId !== this.connection.tenantId ||
|
|
72
|
+
message.source.provider !== this.connection.provider ||
|
|
73
|
+
message.source.connectionId !== this.connection.connectionId ||
|
|
74
|
+
message.source.externalTenantId !== this.connection.externalTenantId
|
|
75
|
+
)
|
|
76
|
+
throw new Error('Channel response belongs to another connection.')
|
|
77
|
+
if (!isDeepStrictEqual(nativeTuple(message.source), nativeTuple(message.routeKey)))
|
|
78
|
+
throw new Error('Channel message source does not match its original native route.')
|
|
79
|
+
const binding = await this.options.store.routeIngress(message.routeKey)
|
|
80
|
+
if (
|
|
81
|
+
!binding ||
|
|
82
|
+
binding.id !== message.routeId ||
|
|
83
|
+
binding.phase !== 'active' ||
|
|
84
|
+
binding.sessionId !== context.sessionId ||
|
|
85
|
+
binding.profileRevision !== context.profileRevision ||
|
|
86
|
+
binding.key.recipient.palId !== context.recipient.palId ||
|
|
87
|
+
binding.key.recipient.tenantId !== context.recipient.tenantId
|
|
88
|
+
)
|
|
89
|
+
throw new Error('Channel response belongs to another Pal conversation or profile.')
|
|
90
|
+
signal.throwIfAborted()
|
|
91
|
+
await verifyIngressRecorded(message, message.receipt, {
|
|
92
|
+
binding,
|
|
93
|
+
definition,
|
|
94
|
+
access: await this.options.host.openConversation(binding, signal),
|
|
95
|
+
})
|
|
96
|
+
signal.throwIfAborted()
|
|
97
|
+
this.assertRecipient(context)
|
|
98
|
+
return { ...message, receipt: message.receipt }
|
|
99
|
+
}
|
|
100
|
+
private async resolve(
|
|
101
|
+
input: InboundDeliveryRef,
|
|
102
|
+
context: PalChannelExecutionContext,
|
|
103
|
+
signal: AbortSignal,
|
|
104
|
+
action?: PalChannelVerifiedAction,
|
|
105
|
+
): Promise<PalChannelResolvedRoute> {
|
|
106
|
+
const message = await this.recorded(input, context, signal)
|
|
107
|
+
if (
|
|
108
|
+
action &&
|
|
109
|
+
(action.externalTenantId !== message.source.externalTenantId ||
|
|
110
|
+
!isDeepStrictEqual(
|
|
111
|
+
nativeTuple({
|
|
112
|
+
...action,
|
|
113
|
+
provider: this.connection.provider,
|
|
114
|
+
connectionId: this.connection.connectionId,
|
|
115
|
+
}),
|
|
116
|
+
nativeTuple(message.source),
|
|
117
|
+
))
|
|
118
|
+
)
|
|
119
|
+
throw new Error('Channel action belongs to another native conversation, channel or thread.')
|
|
120
|
+
const allowed = await this.options.authorize(
|
|
121
|
+
freezeCommunicationValue({
|
|
122
|
+
phase: action ? 'action' : 'reply',
|
|
123
|
+
message: message as PalChannelIntent,
|
|
124
|
+
context,
|
|
125
|
+
actorId: action?.actorId ?? message.source.actorId,
|
|
126
|
+
...(action ? { action } : {}),
|
|
127
|
+
}),
|
|
128
|
+
)
|
|
129
|
+
signal.throwIfAborted()
|
|
130
|
+
if (allowed.allow !== true) throw new Error(`Channel routing refused: ${allowed.reason}`)
|
|
131
|
+
this.assertRecipient(context)
|
|
132
|
+
return freezeCommunicationValue({
|
|
133
|
+
connection: this.connection,
|
|
134
|
+
identity: {
|
|
135
|
+
provider: message.source.provider,
|
|
136
|
+
connectionId: message.source.connectionId,
|
|
137
|
+
externalTenantId: message.source.externalTenantId,
|
|
138
|
+
nativeConversationId: message.source.nativeConversationId,
|
|
139
|
+
nativeChannelId: message.source.nativeChannelId,
|
|
140
|
+
nativeThreadId: message.source.nativeThreadId,
|
|
141
|
+
},
|
|
142
|
+
deliveryRef: {
|
|
143
|
+
namespace: PAL_CHANNEL_NAMESPACE,
|
|
144
|
+
id: message.id,
|
|
145
|
+
digest: message.digest,
|
|
146
|
+
},
|
|
147
|
+
recordedReceipt: message.receipt,
|
|
148
|
+
eventActorId: message.source.actorId,
|
|
149
|
+
currentActorId: action?.actorId ?? message.source.actorId,
|
|
150
|
+
context,
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
async replyRoute(
|
|
154
|
+
input: InboundDeliveryRef,
|
|
155
|
+
execution: PalChannelExecutionContext,
|
|
156
|
+
signal: AbortSignal = new AbortController().signal,
|
|
157
|
+
) {
|
|
158
|
+
const context = freezeCommunicationValue(contextSchema.parse(execution))
|
|
159
|
+
const ref = refSchema.parse(input)
|
|
160
|
+
signal.throwIfAborted()
|
|
161
|
+
return this.resolve(ref, context, signal)
|
|
162
|
+
}
|
|
163
|
+
async actionRoute(
|
|
164
|
+
raw: unknown,
|
|
165
|
+
execution: PalChannelExecutionContext,
|
|
166
|
+
signal: AbortSignal = new AbortController().signal,
|
|
167
|
+
) {
|
|
168
|
+
const context = freezeCommunicationValue(contextSchema.parse(execution))
|
|
169
|
+
signal.throwIfAborted()
|
|
170
|
+
const action = freezeCommunicationValue(
|
|
171
|
+
verifiedActionSchema.parse(
|
|
172
|
+
await this.options.verify(structuredClone(raw), this.connection, signal),
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
signal.throwIfAborted()
|
|
176
|
+
const route = await this.resolve(action.deliveryRef, context, signal, action)
|
|
177
|
+
return freezeCommunicationValue({ route, action })
|
|
178
|
+
}
|
|
179
|
+
async executeAction(
|
|
180
|
+
raw: unknown,
|
|
181
|
+
execution: PalChannelExecutionContext,
|
|
182
|
+
signal: AbortSignal = new AbortController().signal,
|
|
183
|
+
) {
|
|
184
|
+
if (!this.options.actions)
|
|
185
|
+
throw new Error('Channel action execution is unsupported by this host.')
|
|
186
|
+
const context = await this.actionRoute(raw, execution, signal)
|
|
187
|
+
signal.throwIfAborted()
|
|
188
|
+
this.assertRecipient(context.route.context)
|
|
189
|
+
const result = await this.options.actions.execute(context, signal)
|
|
190
|
+
return freezeCommunicationValue(
|
|
191
|
+
z
|
|
192
|
+
.object({ status: z.enum(['applied', 'rejected']), receiptId: label })
|
|
193
|
+
.strict()
|
|
194
|
+
.parse(result),
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { channelRouteKeySchema, channelSourceSchema } from '../communication/ingress-schema.js'
|
|
4
|
+
import type { PalChannelIdentity } from '../communication/ingress-types.js'
|
|
5
|
+
import { addressSchema, freezeCommunicationValue, hash, label } from '../communication/schema.js'
|
|
6
|
+
import type { PalChannelConnection, PalChannelRouteDecision } from './types.js'
|
|
7
|
+
|
|
8
|
+
export const connectionSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
tenantId: addressSchema.shape.tenantId,
|
|
11
|
+
provider: label,
|
|
12
|
+
connectionId: label,
|
|
13
|
+
externalTenantId: label,
|
|
14
|
+
})
|
|
15
|
+
.strict()
|
|
16
|
+
const verifiedIdentity = {
|
|
17
|
+
externalTenantId: label,
|
|
18
|
+
nativeConversationId: label,
|
|
19
|
+
nativeChannelId: label.nullable(),
|
|
20
|
+
nativeThreadId: label.nullable(),
|
|
21
|
+
actorId: label,
|
|
22
|
+
eventId: label,
|
|
23
|
+
}
|
|
24
|
+
export const verifiedMessageSchema = z
|
|
25
|
+
.object({
|
|
26
|
+
...verifiedIdentity,
|
|
27
|
+
kind: z.literal('message'),
|
|
28
|
+
body: z
|
|
29
|
+
.string()
|
|
30
|
+
.min(1)
|
|
31
|
+
.max(32_000)
|
|
32
|
+
.refine((value) => !value.includes('\0')),
|
|
33
|
+
})
|
|
34
|
+
.strict()
|
|
35
|
+
export const verifiedActionSchema = z
|
|
36
|
+
.object({
|
|
37
|
+
...verifiedIdentity,
|
|
38
|
+
kind: z.literal('action'),
|
|
39
|
+
deliveryRef: z
|
|
40
|
+
.object({
|
|
41
|
+
namespace: z.literal('namzu-pal-channel/1'),
|
|
42
|
+
id: z.string().regex(/^[a-f0-9]{64}$/),
|
|
43
|
+
digest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
44
|
+
})
|
|
45
|
+
.strict(),
|
|
46
|
+
actionId: label,
|
|
47
|
+
payloadDigest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
48
|
+
payload: z
|
|
49
|
+
.string()
|
|
50
|
+
.min(1)
|
|
51
|
+
.max(32_000)
|
|
52
|
+
.refine((value) => !value.includes('\0')),
|
|
53
|
+
})
|
|
54
|
+
.strict()
|
|
55
|
+
.refine(
|
|
56
|
+
(value) => createHash('sha256').update(value.payload).digest('hex') === value.payloadDigest,
|
|
57
|
+
'Channel action payload does not match its authenticated digest.',
|
|
58
|
+
)
|
|
59
|
+
export const routeDecisionSchema = z
|
|
60
|
+
.object({
|
|
61
|
+
v: z.literal(1),
|
|
62
|
+
revision: z.literal(1),
|
|
63
|
+
identity: channelRouteKeySchema.omit({
|
|
64
|
+
v: true,
|
|
65
|
+
kind: true,
|
|
66
|
+
recipient: true,
|
|
67
|
+
}),
|
|
68
|
+
recipient: addressSchema,
|
|
69
|
+
profileRevision: z.number().int().positive().safe(),
|
|
70
|
+
})
|
|
71
|
+
.strict()
|
|
72
|
+
|
|
73
|
+
export function captureConnection(input: PalChannelConnection): PalChannelConnection {
|
|
74
|
+
return freezeCommunicationValue(connectionSchema.parse(input))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function checkedIdentity(connection: PalChannelConnection, event: unknown) {
|
|
78
|
+
const source = channelSourceSchema.parse(event)
|
|
79
|
+
if (
|
|
80
|
+
source.tenantId !== connection.tenantId ||
|
|
81
|
+
source.provider !== connection.provider ||
|
|
82
|
+
source.connectionId !== connection.connectionId ||
|
|
83
|
+
source.externalTenantId !== connection.externalTenantId
|
|
84
|
+
)
|
|
85
|
+
throw new Error('Channel identity does not belong to the authenticated connection.')
|
|
86
|
+
return freezeCommunicationValue(source)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function nativeTuple(identity: PalChannelIdentity): readonly unknown[] {
|
|
90
|
+
return [
|
|
91
|
+
identity.provider,
|
|
92
|
+
identity.connectionId,
|
|
93
|
+
identity.externalTenantId,
|
|
94
|
+
identity.nativeConversationId,
|
|
95
|
+
identity.nativeChannelId,
|
|
96
|
+
identity.nativeThreadId,
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function decisionId(
|
|
101
|
+
decision: Pick<PalChannelRouteDecision, 'identity' | 'recipient'>,
|
|
102
|
+
): string {
|
|
103
|
+
return hash([1, decision.recipient.tenantId, nativeTuple(decision.identity)])
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function checkedDecision(input: unknown): PalChannelRouteDecision {
|
|
107
|
+
return freezeCommunicationValue(routeDecisionSchema.parse(input))
|
|
108
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { SessionId } from '../../types/ids/index.js'
|
|
2
|
+
import type {
|
|
3
|
+
InboundDeliveryReceipt,
|
|
4
|
+
InboundDeliveryRef,
|
|
5
|
+
} from '../../types/message/inbound-delivery.js'
|
|
6
|
+
import type {
|
|
7
|
+
PalChannelIdentity,
|
|
8
|
+
PalChannelIntent,
|
|
9
|
+
PalChannelSource,
|
|
10
|
+
PalIngressAcceptanceReceipt,
|
|
11
|
+
PalIngressHostPort,
|
|
12
|
+
PalIngressStore,
|
|
13
|
+
} from '../communication/ingress-types.js'
|
|
14
|
+
import type { PalAddress, PalMessageAuthorization } from '../communication/types.js'
|
|
15
|
+
import type { PalStore } from '../types.js'
|
|
16
|
+
|
|
17
|
+
/** Host-selected connection identity. Credentials belong only to the verifier closure. */
|
|
18
|
+
export interface PalChannelConnection {
|
|
19
|
+
readonly tenantId: PalAddress['tenantId']
|
|
20
|
+
readonly provider: string
|
|
21
|
+
readonly connectionId: string
|
|
22
|
+
readonly externalTenantId: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PalChannelVerifiedIdentity {
|
|
26
|
+
readonly externalTenantId: string
|
|
27
|
+
readonly nativeConversationId: string
|
|
28
|
+
readonly nativeChannelId: string | null
|
|
29
|
+
readonly nativeThreadId: string | null
|
|
30
|
+
readonly actorId: string
|
|
31
|
+
readonly eventId: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Only new, authenticated messages enter the inbox. Edits and service events require another port. */
|
|
35
|
+
export interface PalChannelVerifiedMessage extends PalChannelVerifiedIdentity {
|
|
36
|
+
readonly kind: 'message'
|
|
37
|
+
readonly body: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Authentication must cover the action reference, identity and exact action payload. */
|
|
41
|
+
export interface PalChannelVerifiedAction extends PalChannelVerifiedIdentity {
|
|
42
|
+
readonly kind: 'action'
|
|
43
|
+
readonly deliveryRef: InboundDeliveryRef
|
|
44
|
+
readonly actionId: string
|
|
45
|
+
readonly payloadDigest: string
|
|
46
|
+
/** Exact authenticated JSON payload; the host action port must parse its native action schema. */
|
|
47
|
+
readonly payload: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type PalChannelVerifiedEvent = PalChannelVerifiedMessage | PalChannelVerifiedAction
|
|
51
|
+
|
|
52
|
+
/** Required trusted host callback; raw events cannot select a connection or its credentials. */
|
|
53
|
+
export type PalChannelVerifier = (
|
|
54
|
+
raw: unknown,
|
|
55
|
+
connection: PalChannelConnection,
|
|
56
|
+
signal: AbortSignal,
|
|
57
|
+
) => Promise<PalChannelVerifiedEvent>
|
|
58
|
+
|
|
59
|
+
export interface PalChannelRouteDecision {
|
|
60
|
+
readonly v: 1
|
|
61
|
+
readonly revision: 1
|
|
62
|
+
readonly identity: PalChannelIdentity
|
|
63
|
+
readonly recipient: PalAddress
|
|
64
|
+
readonly profileRevision: number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** One immutable decision per tenant and full native tuple. The inbox owns the actual session. */
|
|
68
|
+
export interface PalChannelRoutes {
|
|
69
|
+
get(
|
|
70
|
+
connection: PalChannelConnection,
|
|
71
|
+
identity: PalChannelIdentity,
|
|
72
|
+
): Promise<PalChannelRouteDecision | null>
|
|
73
|
+
reserve(decision: PalChannelRouteDecision): Promise<PalChannelRouteDecision>
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface PalChannelAuthorizationRequest {
|
|
77
|
+
readonly phase: 'accept' | 'deliver' | 'wake'
|
|
78
|
+
readonly kind: 'channel'
|
|
79
|
+
readonly source: PalChannelSource
|
|
80
|
+
readonly recipient: PalAddress
|
|
81
|
+
readonly routeKey: PalChannelIntent['routeKey']
|
|
82
|
+
readonly body: string
|
|
83
|
+
readonly replyTo: null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface PalChannelIngressOptions {
|
|
87
|
+
readonly connection: PalChannelConnection
|
|
88
|
+
readonly verify: PalChannelVerifier
|
|
89
|
+
readonly routes: PalChannelRoutes
|
|
90
|
+
readonly store: PalIngressStore
|
|
91
|
+
readonly pals: PalStore
|
|
92
|
+
/** Host selection is used only before the first immutable route decision. */
|
|
93
|
+
readonly selectRecipient: (
|
|
94
|
+
event: PalChannelVerifiedMessage,
|
|
95
|
+
connection: PalChannelConnection,
|
|
96
|
+
) => Promise<PalAddress>
|
|
97
|
+
readonly authorize: (request: PalChannelAuthorizationRequest) => Promise<PalMessageAuthorization>
|
|
98
|
+
readonly host?: PalIngressHostPort
|
|
99
|
+
readonly now?: () => number
|
|
100
|
+
readonly onNotificationError?: (
|
|
101
|
+
error: unknown,
|
|
102
|
+
receipt: PalIngressAcceptanceReceipt,
|
|
103
|
+
) => void | Promise<void>
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface PalChannelExecutionContext {
|
|
107
|
+
readonly recipient: PalAddress
|
|
108
|
+
readonly sessionId: SessionId
|
|
109
|
+
readonly profileRevision: number
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface PalChannelRouteAuthorizationRequest {
|
|
113
|
+
readonly phase: 'reply' | 'action'
|
|
114
|
+
readonly message: PalChannelIntent
|
|
115
|
+
readonly context: PalChannelExecutionContext
|
|
116
|
+
/** Reply uses its triggering event actor; actions authenticate their current actor independently. */
|
|
117
|
+
readonly actorId: string
|
|
118
|
+
readonly action?: PalChannelVerifiedAction
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface PalChannelResolvedRoute {
|
|
122
|
+
readonly connection: PalChannelConnection
|
|
123
|
+
readonly identity: PalChannelIdentity
|
|
124
|
+
readonly deliveryRef: InboundDeliveryRef
|
|
125
|
+
readonly recordedReceipt: InboundDeliveryReceipt
|
|
126
|
+
readonly eventActorId: string
|
|
127
|
+
readonly currentActorId: string
|
|
128
|
+
readonly context: PalChannelExecutionContext
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface PalChannelRouterOptions {
|
|
132
|
+
readonly connection: PalChannelConnection
|
|
133
|
+
readonly verify: PalChannelVerifier
|
|
134
|
+
readonly store: PalIngressStore
|
|
135
|
+
readonly pals: PalStore
|
|
136
|
+
readonly host: PalIngressHostPort
|
|
137
|
+
readonly authorize: (
|
|
138
|
+
request: PalChannelRouteAuthorizationRequest,
|
|
139
|
+
) => Promise<PalMessageAuthorization>
|
|
140
|
+
/** Must durably consume an exact native action once and confirm its result. No transport default. */
|
|
141
|
+
readonly actions?: PalChannelActionPort
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface PalChannelActionContext {
|
|
145
|
+
readonly route: PalChannelResolvedRoute
|
|
146
|
+
readonly action: PalChannelVerifiedAction
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface PalChannelActionPort {
|
|
150
|
+
execute(context: PalChannelActionContext, signal: AbortSignal): Promise<PalChannelActionResult>
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface PalChannelActionResult {
|
|
154
|
+
readonly status: 'applied' | 'rejected'
|
|
155
|
+
readonly receiptId: string
|
|
156
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {
|
|
2
|
+
freezeCommunicationValue,
|
|
3
|
+
intentDigest,
|
|
4
|
+
intentSchema,
|
|
5
|
+
label,
|
|
6
|
+
messageId,
|
|
7
|
+
sendRequestSchema,
|
|
8
|
+
sourceSchema,
|
|
9
|
+
} from './schema.js'
|
|
10
|
+
import { routeId } from './schema.js'
|
|
11
|
+
import {
|
|
12
|
+
type PalMessageBrokerOptions,
|
|
13
|
+
type PalMessageSender,
|
|
14
|
+
type PalMessageSenderContext,
|
|
15
|
+
type PalRouteBinding,
|
|
16
|
+
type PalRouteKey,
|
|
17
|
+
sameAddress,
|
|
18
|
+
} from './types.js'
|
|
19
|
+
import { verifyConversation } from './verify.js'
|
|
20
|
+
|
|
21
|
+
/** Host-owned identity and current policy; model text never selects its sender. */
|
|
22
|
+
export class PalMessageBroker {
|
|
23
|
+
constructor(private readonly options: PalMessageBrokerOptions) {
|
|
24
|
+
if (typeof options.authorize !== 'function')
|
|
25
|
+
throw new Error('Pal communication requires explicit authorization.')
|
|
26
|
+
}
|
|
27
|
+
sender(input: PalMessageSenderContext): PalMessageSender {
|
|
28
|
+
const source = freezeCommunicationValue(sourceSchema.parse(input))
|
|
29
|
+
return {
|
|
30
|
+
send: async (input) => {
|
|
31
|
+
const request = freezeCommunicationValue(sendRequestSchema.parse(input))
|
|
32
|
+
const { pals, store, host } = this.options
|
|
33
|
+
if (!host) throw new Error('Pal sender requires a trusted conversation host.')
|
|
34
|
+
const sender = pals.get(source.address.palId)
|
|
35
|
+
if (!sender || sender.paused) throw new Error('Sender Pal is paused or unavailable.')
|
|
36
|
+
const definition = pals.getRevision(sender.id, source.profileRevision)
|
|
37
|
+
const recipient = request.recipient
|
|
38
|
+
if (recipient.tenantId !== source.address.tenantId)
|
|
39
|
+
throw new Error('Cross-tenant Pal messages are refused.')
|
|
40
|
+
const target = pals.get(recipient.palId)
|
|
41
|
+
if (!target) throw new Error('Recipient Pal is unavailable.')
|
|
42
|
+
const validationKey: PalRouteKey = {
|
|
43
|
+
v: 1,
|
|
44
|
+
kind: 'pal',
|
|
45
|
+
sender: source.address,
|
|
46
|
+
senderConversationId: source.conversationId,
|
|
47
|
+
recipient: source.address,
|
|
48
|
+
dialogKey: 'sender-validation',
|
|
49
|
+
}
|
|
50
|
+
const validation: PalRouteBinding = {
|
|
51
|
+
id: routeId(validationKey),
|
|
52
|
+
key: validationKey,
|
|
53
|
+
sessionId: source.conversationId,
|
|
54
|
+
profileRevision: source.profileRevision,
|
|
55
|
+
revision: 1,
|
|
56
|
+
phase: 'active',
|
|
57
|
+
}
|
|
58
|
+
const signal = new AbortController().signal
|
|
59
|
+
await verifyConversation({
|
|
60
|
+
binding: validation,
|
|
61
|
+
definition,
|
|
62
|
+
access: await host.openConversation(validation, signal),
|
|
63
|
+
})
|
|
64
|
+
let dialogKey = label.parse(request.dialogKey ?? 'default')
|
|
65
|
+
let profileRevision = target.revision
|
|
66
|
+
let conversationId: typeof source.conversationId | undefined
|
|
67
|
+
const replyTo = request.replyTo ?? null
|
|
68
|
+
if (replyTo !== null) {
|
|
69
|
+
const prior = (await store.read(source.address))?.messages.find((m) => m.id === replyTo)
|
|
70
|
+
if (!prior || prior.phase !== 'recorded' || !sameAddress(prior.source.address, recipient))
|
|
71
|
+
throw new Error('Reply does not name an observed, authorized incoming Pal message.')
|
|
72
|
+
const route = await store.route(prior.routeKey)
|
|
73
|
+
if (!route || route.sessionId !== source.conversationId)
|
|
74
|
+
throw new Error('Reply belongs to another conversation.')
|
|
75
|
+
conversationId = prior.source.conversationId
|
|
76
|
+
profileRevision = prior.source.profileRevision
|
|
77
|
+
dialogKey = `reply:${conversationId}`
|
|
78
|
+
}
|
|
79
|
+
const routeKey: PalRouteKey = {
|
|
80
|
+
v: 1,
|
|
81
|
+
kind: 'pal',
|
|
82
|
+
sender: source.address,
|
|
83
|
+
senderConversationId: source.conversationId,
|
|
84
|
+
recipient,
|
|
85
|
+
dialogKey,
|
|
86
|
+
}
|
|
87
|
+
const requestContext = freezeCommunicationValue({
|
|
88
|
+
phase: 'send' as const,
|
|
89
|
+
source,
|
|
90
|
+
recipient,
|
|
91
|
+
routeKey,
|
|
92
|
+
body: request.body,
|
|
93
|
+
replyTo,
|
|
94
|
+
})
|
|
95
|
+
const authorization = await this.options.authorize(requestContext)
|
|
96
|
+
if (!authorization.allow) throw new Error(`Pal send refused: ${authorization.reason}`)
|
|
97
|
+
if (pals.get(sender.id)?.paused) throw new Error('Sender Pal was paused before acceptance.')
|
|
98
|
+
const intent = {
|
|
99
|
+
id: messageId(source, request.operationId),
|
|
100
|
+
operationId: request.operationId,
|
|
101
|
+
source,
|
|
102
|
+
recipient,
|
|
103
|
+
routeKey,
|
|
104
|
+
body: request.body,
|
|
105
|
+
replyTo,
|
|
106
|
+
grant: authorization.grant,
|
|
107
|
+
createdAt: (this.options.now ?? Date.now)(),
|
|
108
|
+
}
|
|
109
|
+
const immutableIntent = freezeCommunicationValue(
|
|
110
|
+
intentSchema.parse({ ...intent, digest: intentDigest(intent) }),
|
|
111
|
+
)
|
|
112
|
+
const accepted = await store.accept(immutableIntent, profileRevision, conversationId)
|
|
113
|
+
const report = (error: unknown) => {
|
|
114
|
+
try {
|
|
115
|
+
void Promise.resolve(this.options.onNotificationError?.(error, accepted)).catch(
|
|
116
|
+
() => undefined,
|
|
117
|
+
)
|
|
118
|
+
} catch {
|
|
119
|
+
/* Acceptance already committed. */
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
void Promise.resolve(host.notify?.(recipient)).catch(report)
|
|
124
|
+
} catch (error) {
|
|
125
|
+
report(error)
|
|
126
|
+
}
|
|
127
|
+
return accepted
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createPalInboxSource, reconcilePalDelivery } from './inbound.js'
|
|
2
|
+
import type { PalIngressStore } from './ingress-types.js'
|
|
3
|
+
import {
|
|
4
|
+
type PalAddress,
|
|
5
|
+
type PalDispatchOutcome,
|
|
6
|
+
type PalMessageBrokerOptions,
|
|
7
|
+
authorizationRequest,
|
|
8
|
+
currentRecipient,
|
|
9
|
+
} from './types.js'
|
|
10
|
+
import { verifyConversation } from './verify.js'
|
|
11
|
+
|
|
12
|
+
/** Finite opt-in operation; host retains normal query/computer ownership. */
|
|
13
|
+
export async function dispatchPalMessagesOnce(
|
|
14
|
+
options: PalMessageBrokerOptions,
|
|
15
|
+
recipient: PalAddress,
|
|
16
|
+
signal: AbortSignal,
|
|
17
|
+
): Promise<PalDispatchOutcome> {
|
|
18
|
+
signal.throwIfAborted()
|
|
19
|
+
const host = options.host
|
|
20
|
+
if (!host)
|
|
21
|
+
return {
|
|
22
|
+
status: 'blocked',
|
|
23
|
+
reason: 'No Pal conversation host is configured.',
|
|
24
|
+
}
|
|
25
|
+
const shared = options.store as Partial<PalIngressStore>
|
|
26
|
+
if (shared.readIngress) {
|
|
27
|
+
const full = await shared.readIngress(recipient)
|
|
28
|
+
if (full?.messages.some((message) => message.phase === 'claimed' && 'kind' in message))
|
|
29
|
+
return { status: 'idle', reason: 'unresolved' }
|
|
30
|
+
}
|
|
31
|
+
let state = await options.store.read(recipient)
|
|
32
|
+
const unresolved = state?.messages.find((m) => m.phase === 'claimed')
|
|
33
|
+
if (unresolved) {
|
|
34
|
+
const binding = state?.routes.find((r) => r.id === unresolved.routeId)
|
|
35
|
+
if (
|
|
36
|
+
!binding ||
|
|
37
|
+
!(await reconcilePalDelivery({ ...options, binding, host }, unresolved, signal))
|
|
38
|
+
)
|
|
39
|
+
return { status: 'idle', reason: 'unresolved' }
|
|
40
|
+
state = await options.store.read(recipient)
|
|
41
|
+
}
|
|
42
|
+
const message = state?.messages.find((m) => m.phase === 'pending')
|
|
43
|
+
if (!message) return { status: 'idle', reason: 'empty' }
|
|
44
|
+
let binding = state?.routes.find((r) => r.id === message.routeId)
|
|
45
|
+
if (!binding) throw new Error('Pal incoming message has no route binding.')
|
|
46
|
+
const authorization = await options.authorize(authorizationRequest(message, 'wake'))
|
|
47
|
+
if (!authorization.allow) return { status: 'blocked', reason: authorization.reason }
|
|
48
|
+
currentRecipient(options.pals, binding)
|
|
49
|
+
signal.throwIfAborted()
|
|
50
|
+
await host.ensureConversation(binding, signal)
|
|
51
|
+
const definition = currentRecipient(options.pals, binding)
|
|
52
|
+
const access = await host.openConversation(binding, signal)
|
|
53
|
+
await verifyConversation({ binding, access, definition })
|
|
54
|
+
if (binding.phase === 'reserved')
|
|
55
|
+
binding = await options.store.activate(binding, {
|
|
56
|
+
binding,
|
|
57
|
+
access,
|
|
58
|
+
definition,
|
|
59
|
+
})
|
|
60
|
+
const currentAuthorization = await options.authorize(authorizationRequest(message, 'wake'))
|
|
61
|
+
if (!currentAuthorization.allow) return { status: 'blocked', reason: currentAuthorization.reason }
|
|
62
|
+
currentRecipient(options.pals, binding)
|
|
63
|
+
signal.throwIfAborted()
|
|
64
|
+
await host.runConversation(binding, createPalInboxSource({ ...options, binding, host }), signal)
|
|
65
|
+
return { status: 'ran', binding }
|
|
66
|
+
}
|