@namzu/sdk 49.0.0 → 50.0.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 +507 -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/public-runtime.d.ts +41 -13
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +35 -7
- 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 +34 -0
- 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/public-runtime.ts +117 -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 +42 -0
- 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
|
@@ -77,6 +77,11 @@ const OWNED_WORK_DISPLAY_LIMIT = 16
|
|
|
77
77
|
export class CompletionInbox {
|
|
78
78
|
private readonly unheard = new Map<TaskId, TaskHandle>()
|
|
79
79
|
private readonly claimed = new Set<TaskId>()
|
|
80
|
+
/** Persistence that must settle before an owned result may be delivered. */
|
|
81
|
+
private readonly deliveryGates = new Map<
|
|
82
|
+
TaskId,
|
|
83
|
+
{ settled: Promise<void>; state: 'pending' | 'ready' | 'failed'; error?: unknown }
|
|
84
|
+
>()
|
|
80
85
|
/** Launched with nothing waiting on it, and not settled yet. */
|
|
81
86
|
private readonly outstanding = new Set<TaskId>()
|
|
82
87
|
/**
|
|
@@ -136,6 +141,8 @@ export class CompletionInbox {
|
|
|
136
141
|
*/
|
|
137
142
|
private readonly unowned = new Map<TaskId, TaskHandle>()
|
|
138
143
|
private readonly arrivals = new Set<() => void>()
|
|
144
|
+
private readonly drains = new Set<() => void>()
|
|
145
|
+
private lifecycle = 0
|
|
139
146
|
private detach?: () => void
|
|
140
147
|
/** Kept for {@link launched}: the source of truth about a task's state. */
|
|
141
148
|
private gateway?: TaskScheduler
|
|
@@ -173,7 +180,10 @@ export class CompletionInbox {
|
|
|
173
180
|
this.markSettled(handle.taskId)
|
|
174
181
|
if (this.claimed.has(handle.taskId)) return
|
|
175
182
|
this.unheard.set(handle.taskId, handle)
|
|
176
|
-
for (const wake of this.arrivals) wake()
|
|
183
|
+
if (this.hasUnheard) for (const wake of this.arrivals) wake()
|
|
184
|
+
if (this.deliveryGates.get(handle.taskId)?.state === 'failed') {
|
|
185
|
+
for (const finish of [...this.drains]) finish()
|
|
186
|
+
}
|
|
177
187
|
})
|
|
178
188
|
return this.detach
|
|
179
189
|
}
|
|
@@ -261,6 +271,47 @@ export class CompletionInbox {
|
|
|
261
271
|
for (const wake of [...this.arrivals]) wake()
|
|
262
272
|
}
|
|
263
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Hold delivery until this owned task's tracking writes have settled.
|
|
276
|
+
*
|
|
277
|
+
* Register synchronously after `launched`, before handing control back to
|
|
278
|
+
* a consumer. The promise receives no worker output from this inbox.
|
|
279
|
+
* Rejections are retained and reported by either drain; the result stays
|
|
280
|
+
* queued rather than being announced with stale tracking state.
|
|
281
|
+
*/
|
|
282
|
+
deferDelivery(taskId: TaskId, settlement: Promise<void>): void {
|
|
283
|
+
if (!this.ours.has(taskId) || this.claimed.has(taskId)) {
|
|
284
|
+
throw new Error('Delivery may only be deferred for an owned, undelivered task')
|
|
285
|
+
}
|
|
286
|
+
if (this.deliveryGates.has(taskId)) {
|
|
287
|
+
throw new Error('This task already has a delivery settlement')
|
|
288
|
+
}
|
|
289
|
+
const gate: {
|
|
290
|
+
settled: Promise<void>
|
|
291
|
+
state: 'pending' | 'ready' | 'failed'
|
|
292
|
+
error?: unknown
|
|
293
|
+
} = { settled: Promise.resolve(), state: 'pending' }
|
|
294
|
+
gate.settled = settlement
|
|
295
|
+
.then(
|
|
296
|
+
() => {
|
|
297
|
+
gate.state = 'ready'
|
|
298
|
+
},
|
|
299
|
+
(error: unknown) => {
|
|
300
|
+
gate.state = 'failed'
|
|
301
|
+
gate.error = error
|
|
302
|
+
},
|
|
303
|
+
)
|
|
304
|
+
.then(() => {
|
|
305
|
+
if (this.deliveryGates.get(taskId) === gate && this.unheard.has(taskId)) {
|
|
306
|
+
for (const wake of [...this.arrivals]) wake()
|
|
307
|
+
// A known tracking failure must not wait behind another row's
|
|
308
|
+
// stalled write. Drains report it without consuming any result.
|
|
309
|
+
if (gate.state === 'failed') for (const finish of [...this.drains]) finish()
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
this.deliveryGates.set(taskId, gate)
|
|
313
|
+
}
|
|
314
|
+
|
|
264
315
|
/**
|
|
265
316
|
* Move an owned task from {@link runningOwned} to {@link settledOwned}.
|
|
266
317
|
*
|
|
@@ -308,8 +359,8 @@ export class CompletionInbox {
|
|
|
308
359
|
*/
|
|
309
360
|
waitForArrival(timeoutMs: number, signal?: AbortSignal): Promise<void> {
|
|
310
361
|
if (signal?.aborted) return Promise.resolve()
|
|
311
|
-
if (this.
|
|
312
|
-
if (this.
|
|
362
|
+
if (this.hasUnheard) return Promise.resolve()
|
|
363
|
+
if (!this.hasPendingWork) return Promise.resolve()
|
|
313
364
|
|
|
314
365
|
return new Promise((resolve) => {
|
|
315
366
|
const finish = (): void => {
|
|
@@ -338,6 +389,7 @@ export class CompletionInbox {
|
|
|
338
389
|
claim(taskId: TaskId): void {
|
|
339
390
|
this.claimed.add(taskId)
|
|
340
391
|
this.unheard.delete(taskId)
|
|
392
|
+
this.deliveryGates.delete(taskId)
|
|
341
393
|
this.outstanding.delete(taskId)
|
|
342
394
|
// A tool only claims a result it is already holding, so a claim is
|
|
343
395
|
// itself proof of settlement — independent of whether the gateway's
|
|
@@ -350,7 +402,9 @@ export class CompletionInbox {
|
|
|
350
402
|
|
|
351
403
|
/** Whether anything is waiting to be told. */
|
|
352
404
|
get hasUnheard(): boolean {
|
|
353
|
-
return this.unheard.
|
|
405
|
+
return [...this.unheard.keys()].some(
|
|
406
|
+
(taskId) => this.deliveryGates.get(taskId)?.state !== 'pending',
|
|
407
|
+
)
|
|
354
408
|
}
|
|
355
409
|
|
|
356
410
|
/**
|
|
@@ -410,16 +464,22 @@ export class CompletionInbox {
|
|
|
410
464
|
}
|
|
411
465
|
|
|
412
466
|
/**
|
|
413
|
-
* Take
|
|
467
|
+
* Take unheard completions whose tracking settlement has succeeded.
|
|
468
|
+
* Pending gates stay queued; a rejected gate throws without consuming any
|
|
469
|
+
* result. Use `drainAsync` to await tracking for results already in hand.
|
|
414
470
|
*
|
|
415
471
|
* Draining rather than peeking: a notification that stays queued after
|
|
416
472
|
* being delivered is the duplicate-delivery bug in a different costume.
|
|
417
473
|
*/
|
|
418
474
|
drain(): TaskHandle[] {
|
|
419
475
|
if (this.unheard.size === 0) return []
|
|
420
|
-
|
|
421
|
-
this.unheard.
|
|
476
|
+
this.checkDeliveryFailures()
|
|
477
|
+
const handles = [...this.unheard.values()].filter(
|
|
478
|
+
(handle) => this.deliveryGates.get(handle.taskId)?.state !== 'pending',
|
|
479
|
+
)
|
|
422
480
|
for (const handle of handles) {
|
|
481
|
+
this.unheard.delete(handle.taskId)
|
|
482
|
+
this.deliveryGates.delete(handle.taskId)
|
|
423
483
|
this.claimed.add(handle.taskId)
|
|
424
484
|
// A delivered result is not pending WORK, and `outstanding` can
|
|
425
485
|
// still be holding this id — the listener clears it, but only if
|
|
@@ -438,6 +498,43 @@ export class CompletionInbox {
|
|
|
438
498
|
return handles
|
|
439
499
|
}
|
|
440
500
|
|
|
501
|
+
private checkDeliveryFailures(): void {
|
|
502
|
+
for (const taskId of this.unheard.keys()) {
|
|
503
|
+
const gate = this.deliveryGates.get(taskId)
|
|
504
|
+
if (gate?.state === 'failed') throw gate.error
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Await tracking for completions already queued, then deliver once.
|
|
510
|
+
* Running workers are never awaited here. Concurrent drains share gates
|
|
511
|
+
* and the existing claim set, so only one consumer receives each result.
|
|
512
|
+
* Aborting releases only this wait and returns no results; tracking and
|
|
513
|
+
* queued completions remain available for a later drain.
|
|
514
|
+
*/
|
|
515
|
+
async drainAsync(signal?: AbortSignal): Promise<TaskHandle[]> {
|
|
516
|
+
const lifecycle = this.lifecycle
|
|
517
|
+
if (signal?.aborted) return []
|
|
518
|
+
this.checkDeliveryFailures()
|
|
519
|
+
const settlements = [...this.unheard.keys()].flatMap((taskId) => {
|
|
520
|
+
const gate = this.deliveryGates.get(taskId)
|
|
521
|
+
return gate ? [gate.settled] : []
|
|
522
|
+
})
|
|
523
|
+
if (settlements.length === 0) return this.drain()
|
|
524
|
+
await new Promise<void>((resolve) => {
|
|
525
|
+
const finish = (): void => {
|
|
526
|
+
signal?.removeEventListener('abort', finish)
|
|
527
|
+
this.drains.delete(finish)
|
|
528
|
+
resolve()
|
|
529
|
+
}
|
|
530
|
+
this.drains.add(finish)
|
|
531
|
+
signal?.addEventListener('abort', finish, { once: true })
|
|
532
|
+
void Promise.all(settlements).then(finish)
|
|
533
|
+
if (signal?.aborted) finish()
|
|
534
|
+
})
|
|
535
|
+
return signal?.aborted || lifecycle !== this.lifecycle ? [] : this.drain()
|
|
536
|
+
}
|
|
537
|
+
|
|
441
538
|
/**
|
|
442
539
|
* Stop expecting a task that is never going to arrive.
|
|
443
540
|
*
|
|
@@ -480,10 +577,12 @@ export class CompletionInbox {
|
|
|
480
577
|
* stops it existing.
|
|
481
578
|
*/
|
|
482
579
|
close(): void {
|
|
580
|
+
this.lifecycle++
|
|
483
581
|
this.detach?.()
|
|
484
582
|
this.detach = undefined
|
|
485
583
|
this.gateway = undefined
|
|
486
584
|
this.unheard.clear()
|
|
585
|
+
this.deliveryGates.clear()
|
|
487
586
|
this.outstanding.clear()
|
|
488
587
|
this.ours.clear()
|
|
489
588
|
this.runningOwned.clear()
|
|
@@ -494,6 +593,8 @@ export class CompletionInbox {
|
|
|
494
593
|
// them to their own deadline for a completion that can no longer come.
|
|
495
594
|
for (const wake of [...this.arrivals]) wake()
|
|
496
595
|
this.arrivals.clear()
|
|
596
|
+
for (const finish of [...this.drains]) finish()
|
|
597
|
+
this.drains.clear()
|
|
497
598
|
}
|
|
498
599
|
}
|
|
499
600
|
|
|
@@ -171,6 +171,11 @@ export class DelegatingTaskScheduler implements TaskScheduler {
|
|
|
171
171
|
if (!this.config.local) throw new NoDelegateError({ agentId: options.agentId })
|
|
172
172
|
return await this.config.local.createTask(options)
|
|
173
173
|
}
|
|
174
|
+
if (options.resumeSessionId)
|
|
175
|
+
throw new DelegateCapabilityError({
|
|
176
|
+
id: delegate.id,
|
|
177
|
+
capability: 'child conversation continuation',
|
|
178
|
+
})
|
|
174
179
|
|
|
175
180
|
if (this.budget) {
|
|
176
181
|
throw new Error(
|
package/src/scheduler/local.ts
CHANGED
|
@@ -112,6 +112,7 @@ export class LocalTaskScheduler implements TaskScheduler {
|
|
|
112
112
|
const task = await this.agentManager.sendMessage(
|
|
113
113
|
{
|
|
114
114
|
agentId: options.agentId,
|
|
115
|
+
...(options.resumeSessionId ? { resumeSessionId: options.resumeSessionId } : {}),
|
|
115
116
|
beforeStart: options.beforeStart,
|
|
116
117
|
...(options.workspace ? { workspace: options.workspace } : {}),
|
|
117
118
|
...(options.planId ? { planId: options.planId } : {}),
|
|
@@ -469,6 +470,7 @@ function toHandle(task: import('../types/agent/task.js').AgentTask): TaskHandle
|
|
|
469
470
|
result: task.result,
|
|
470
471
|
createdAt: task.createdAt,
|
|
471
472
|
completedAt: task.completedAt,
|
|
473
|
+
...(task.childSessionId ? { childSessionId: task.childSessionId } : {}),
|
|
472
474
|
...(task.workspace ? { workspace: task.workspace } : {}),
|
|
473
475
|
}
|
|
474
476
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* `generateSummaryId` from `utils/id.ts`.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import type { SessionId, TenantId } from '../../types/ids/index.js'
|
|
21
|
+
import type { SessionId, TenantId, TurnId } from '../../types/ids/index.js'
|
|
22
22
|
import type { Session } from '../../types/session/entity.js'
|
|
23
23
|
import type { SummaryId } from '../../types/session/ids.js'
|
|
24
24
|
import type { SessionStore } from '../../types/session/store.js'
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
type SessionSummaryOutcome,
|
|
30
30
|
type SessionSummaryRef,
|
|
31
31
|
} from '../../types/summary/ref.js'
|
|
32
|
+
import { StaleSessionError } from '../errors.js'
|
|
32
33
|
import { AgentSummaryTooLongError, SessionAlreadySummarizedError } from './errors.js'
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -50,6 +51,10 @@ export interface SessionSummaryMaterializerDeps {
|
|
|
50
51
|
*/
|
|
51
52
|
export interface MaterializeInput {
|
|
52
53
|
readonly sessionId: SessionId
|
|
54
|
+
/** Seal this invocation independently of the legacy conversation summary. */
|
|
55
|
+
readonly turnId?: TurnId
|
|
56
|
+
/** Keep this terminalization attributed to the admitted owner, if supplied. */
|
|
57
|
+
readonly expectedOwnerVersion?: number
|
|
53
58
|
readonly tenantId: TenantId
|
|
54
59
|
readonly finalOutcome: SessionSummaryOutcome
|
|
55
60
|
readonly agentSummary: string
|
|
@@ -84,19 +89,31 @@ export class SessionSummaryMaterializer {
|
|
|
84
89
|
* - {@link AgentSummaryTooLongError} — `agentSummary` exceeds the max char
|
|
85
90
|
* cap ({@link AGENT_SUMMARY_MAX_CHARS}).
|
|
86
91
|
* - `TenantIsolationError` — session is owned by a different tenant.
|
|
87
|
-
* - {@link SessionAlreadySummarizedError} —
|
|
88
|
-
*
|
|
89
|
-
*
|
|
92
|
+
* - {@link SessionAlreadySummarizedError} — this conversation-summary key
|
|
93
|
+
* or explicit invocation key already has a sealed summary. A new child
|
|
94
|
+
* invocation uses its fresh `turnId`; it never replaces the old summary.
|
|
90
95
|
*/
|
|
91
96
|
async materialize(input: MaterializeInput): Promise<SessionSummaryRef> {
|
|
92
97
|
this.assertSummaryLength(input.agentSummary)
|
|
98
|
+
if (input.turnId && this.deps.store.supportsInvocationSummaries !== true)
|
|
99
|
+
throw new Error('Session store does not support invocation summaries')
|
|
93
100
|
|
|
94
101
|
const session = await this.deps.store.getSession(input.sessionId, input.tenantId)
|
|
95
102
|
if (!session) {
|
|
96
103
|
throw new Error(`Session ${input.sessionId} not found`)
|
|
97
104
|
}
|
|
105
|
+
if (input.expectedOwnerVersion !== undefined) {
|
|
106
|
+
if (this.deps.store.supportsOwnerVersionCas !== true)
|
|
107
|
+
throw new Error('Session store does not support owner-version CAS')
|
|
108
|
+
if (session.ownerVersion !== input.expectedOwnerVersion)
|
|
109
|
+
throw new StaleSessionError({
|
|
110
|
+
sessionId: input.sessionId,
|
|
111
|
+
expectedVersion: input.expectedOwnerVersion,
|
|
112
|
+
actualVersion: session.ownerVersion,
|
|
113
|
+
})
|
|
114
|
+
}
|
|
98
115
|
|
|
99
|
-
const existing = await this.deps.store.getSummary(input.sessionId, input.tenantId)
|
|
116
|
+
const existing = await this.deps.store.getSummary(input.sessionId, input.tenantId, input.turnId)
|
|
100
117
|
if (existing) {
|
|
101
118
|
throw new SessionAlreadySummarizedError({
|
|
102
119
|
sessionId: input.sessionId,
|
|
@@ -107,6 +124,7 @@ export class SessionSummaryMaterializer {
|
|
|
107
124
|
const summary: SessionSummaryRef = {
|
|
108
125
|
id: this.deps.generateSummaryId(),
|
|
109
126
|
sessionRef: input.sessionId,
|
|
127
|
+
...(input.turnId ? { turnRef: input.turnId } : {}),
|
|
110
128
|
tenantId: input.tenantId,
|
|
111
129
|
outcome: input.finalOutcome,
|
|
112
130
|
deliverables: input.declaredDeliverables,
|
|
@@ -116,13 +134,29 @@ export class SessionSummaryMaterializer {
|
|
|
116
134
|
materializedBy: 'kernel',
|
|
117
135
|
}
|
|
118
136
|
|
|
119
|
-
|
|
137
|
+
const legacy = input.turnId
|
|
138
|
+
? await this.deps.store.getSummary(input.sessionId, input.tenantId)
|
|
139
|
+
: undefined
|
|
140
|
+
if (input.expectedOwnerVersion === undefined)
|
|
141
|
+
await this.deps.store.recordSummary(summary, input.tenantId)
|
|
142
|
+
else await this.deps.store.recordSummary(summary, input.tenantId, input.expectedOwnerVersion)
|
|
143
|
+
if (input.turnId) {
|
|
144
|
+
const stored = await this.deps.store.getSummary(input.sessionId, input.tenantId, input.turnId)
|
|
145
|
+
const afterLegacy = await this.deps.store.getSummary(input.sessionId, input.tenantId)
|
|
146
|
+
if (
|
|
147
|
+
stored?.id !== summary.id ||
|
|
148
|
+
stored.sessionRef !== input.sessionId ||
|
|
149
|
+
stored.turnRef !== input.turnId ||
|
|
150
|
+
afterLegacy?.id !== legacy?.id
|
|
151
|
+
)
|
|
152
|
+
throw new Error('Session store did not preserve the invocation summary contract')
|
|
153
|
+
}
|
|
120
154
|
return summary
|
|
121
155
|
}
|
|
122
156
|
|
|
123
157
|
/**
|
|
124
158
|
* Recovery path. Called at boot (or explicitly by the lifecycle manager)
|
|
125
|
-
* for sessions whose
|
|
159
|
+
* for sessions whose selected summary is persisted but whose `session.json`
|
|
126
160
|
* still reports a non-terminal status — the crash window between the two
|
|
127
161
|
* atomic writes on disk.
|
|
128
162
|
*
|
|
@@ -133,9 +167,17 @@ export class SessionSummaryMaterializer {
|
|
|
133
167
|
* mint a new ID, only re-triggers the store's status flip via
|
|
134
168
|
* `recordSummary` when it detects the dangling session.
|
|
135
169
|
*/
|
|
136
|
-
async recover(
|
|
137
|
-
|
|
170
|
+
async recover(
|
|
171
|
+
sessionId: SessionId,
|
|
172
|
+
tenantId: TenantId,
|
|
173
|
+
turnId?: TurnId,
|
|
174
|
+
): Promise<SessionSummaryRef | null> {
|
|
175
|
+
if (turnId && this.deps.store.supportsInvocationSummaries !== true)
|
|
176
|
+
throw new Error('Session store does not support invocation summaries')
|
|
177
|
+
const summary = await this.deps.store.getSummary(sessionId, tenantId, turnId)
|
|
138
178
|
if (!summary) return null
|
|
179
|
+
if (turnId && (summary.turnRef !== turnId || summary.sessionRef !== sessionId))
|
|
180
|
+
throw new Error('Session store returned a different invocation summary')
|
|
139
181
|
|
|
140
182
|
const session = await this.deps.store.getSession(sessionId, tenantId)
|
|
141
183
|
if (!session) return summary
|
|
@@ -434,7 +434,7 @@ export class SessionTokenBudget {
|
|
|
434
434
|
persistence?: SessionTokenBudgetPersistence,
|
|
435
435
|
): SessionTokenBudget {
|
|
436
436
|
const state = validateSessionTokenBudgetSnapshot(snapshot)
|
|
437
|
-
|
|
437
|
+
const restored = new SessionTokenBudget(
|
|
438
438
|
{
|
|
439
439
|
rootAccountId: state.rootAccountId,
|
|
440
440
|
scope: { rootSessionId: state.rootSessionId, rootTurnId: state.rootTurnId },
|
|
@@ -449,6 +449,27 @@ export class SessionTokenBudget {
|
|
|
449
449
|
},
|
|
450
450
|
state.rootAccountId,
|
|
451
451
|
)
|
|
452
|
+
// A request that was in flight when a process stopped has no receipt. On an
|
|
453
|
+
// unbounded account it stays recorded as unknown spend, but it no longer
|
|
454
|
+
// counts as work in progress, so the turn can ask again.
|
|
455
|
+
for (const request of [...restored.ledger.requests.values()]) {
|
|
456
|
+
if (!restored.account(request.accountId).bounded) restored.retainUnresolved(request)
|
|
457
|
+
}
|
|
458
|
+
return restored
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Whether this account, or any account above it, carries a finite limit. A bounded
|
|
463
|
+
* account cannot be admitted past unknown spend, because the unknown amount may
|
|
464
|
+
* already exceed the limit. An unbounded one has no limit to exceed: its unknown
|
|
465
|
+
* spend stays recorded (never as zero) and does not stop the next request.
|
|
466
|
+
*/
|
|
467
|
+
get bounded(): boolean {
|
|
468
|
+
for (let cursor: SessionTokenBudgetAccountSnapshot | undefined = this.node; cursor; ) {
|
|
469
|
+
if (cursor.limit > 0) return true
|
|
470
|
+
cursor = cursor.parentId === undefined ? undefined : this.requireAccount(cursor.parentId)
|
|
471
|
+
}
|
|
472
|
+
return false
|
|
452
473
|
}
|
|
453
474
|
|
|
454
475
|
get limit(): number {
|
|
@@ -590,7 +611,16 @@ export class SessionTokenBudget {
|
|
|
590
611
|
}
|
|
591
612
|
|
|
592
613
|
async finishRequest(requestId: string, usage: TokenUsage): Promise<void> {
|
|
593
|
-
if (this.hasReceipt(requestId))
|
|
614
|
+
if (this.hasReceipt(requestId)) {
|
|
615
|
+
// A request retained as unknown spend can still be answered late. The
|
|
616
|
+
// measured usage is evidence and is kept; the unknown marker stays until
|
|
617
|
+
// an explicit reconciliation clears it.
|
|
618
|
+
const receipt = this.ledger.finishedRequests.get(
|
|
619
|
+
requestId,
|
|
620
|
+
) as SessionTokenBudgetRequestSnapshot
|
|
621
|
+
if (receipt.unresolved === true) return this.failRequest(requestId, usage)
|
|
622
|
+
return this.flush()
|
|
623
|
+
}
|
|
594
624
|
const request = this.requireRequest(requestId)
|
|
595
625
|
try {
|
|
596
626
|
this.recordRequestUsage(request, usage)
|
|
@@ -608,7 +638,25 @@ export class SessionTokenBudget {
|
|
|
608
638
|
|
|
609
639
|
/** Unknown spend cannot be converted into a refund, even after cancellation. */
|
|
610
640
|
async failRequest(requestId: string, usage?: TokenUsage): Promise<void> {
|
|
611
|
-
if (this.hasReceipt(requestId))
|
|
641
|
+
if (this.hasReceipt(requestId)) {
|
|
642
|
+
// An unbounded account retains a failed request as a receipt; usage that
|
|
643
|
+
// arrives late is still evidence of spend and is kept.
|
|
644
|
+
const receipt = this.ledger.finishedRequests.get(
|
|
645
|
+
requestId,
|
|
646
|
+
) as SessionTokenBudgetRequestSnapshot
|
|
647
|
+
if (usage !== undefined && receipt.unresolved === true) {
|
|
648
|
+
try {
|
|
649
|
+
this.recordRequestUsage(receipt, usage)
|
|
650
|
+
} catch (error) {
|
|
651
|
+
this.ledger.poisoned = true
|
|
652
|
+
this.persist()
|
|
653
|
+
await this.flush()
|
|
654
|
+
throw error
|
|
655
|
+
}
|
|
656
|
+
this.persist()
|
|
657
|
+
}
|
|
658
|
+
return this.flush()
|
|
659
|
+
}
|
|
612
660
|
const request = this.requireRequest(requestId)
|
|
613
661
|
request.unresolved = true
|
|
614
662
|
try {
|
|
@@ -619,6 +667,7 @@ export class SessionTokenBudget {
|
|
|
619
667
|
await this.flush()
|
|
620
668
|
throw error
|
|
621
669
|
}
|
|
670
|
+
if (!this.bounded) this.retainUnresolved(request)
|
|
622
671
|
this.persist()
|
|
623
672
|
await this.flush()
|
|
624
673
|
}
|
|
@@ -713,6 +762,12 @@ export class SessionTokenBudget {
|
|
|
713
762
|
if (this.ledger.persistenceError !== undefined) throw this.ledger.persistenceError
|
|
714
763
|
}
|
|
715
764
|
|
|
765
|
+
/** Move a request with no receipt out of flight, keeping its unknown-spend marker. */
|
|
766
|
+
private retainUnresolved(request: SessionTokenBudgetRequestSnapshot): void {
|
|
767
|
+
request.unresolved = true
|
|
768
|
+
this.ledger.requests.delete(request.id)
|
|
769
|
+
this.ledger.finishedRequests.set(request.id, request)
|
|
770
|
+
}
|
|
716
771
|
private uncertainRequests(): SessionTokenBudgetRequestSnapshot[] {
|
|
717
772
|
return [...this.ledger.requests.values(), ...this.ledger.finishedRequests.values()].filter(
|
|
718
773
|
(request) => request.unresolved === true,
|
|
@@ -722,8 +777,8 @@ export class SessionTokenBudget {
|
|
|
722
777
|
if (this.ledger.poisoned || this.ledger.persistenceError !== undefined) return true
|
|
723
778
|
const uncertain = this.uncertainRequests()
|
|
724
779
|
if (uncertain.length === 0) return false
|
|
725
|
-
//
|
|
726
|
-
|
|
780
|
+
// Unknown spend blocks only through a finite limit at or above this account,
|
|
781
|
+
// where it could already have been exceeded; see `bounded`.
|
|
727
782
|
let cursor = this.node
|
|
728
783
|
for (;;) {
|
|
729
784
|
if (cursor.limit > 0) {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
import { createHash } from 'node:crypto'
|
|
38
38
|
import { mkdir, rm } from 'node:fs/promises'
|
|
39
|
-
import { join } from 'node:path'
|
|
39
|
+
import { join, resolve } from 'node:path'
|
|
40
40
|
import {
|
|
41
41
|
ProjectRootPathTakenError,
|
|
42
42
|
StaleProjectError,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
TenantIsolationError,
|
|
45
45
|
} from '../../session/errors.js'
|
|
46
46
|
import { SessionAlreadySummarizedError } from '../../session/summary/errors.js'
|
|
47
|
-
import type { SessionId, TenantId } from '../../types/ids/index.js'
|
|
47
|
+
import type { SessionId, TenantId, TurnId } from '../../types/ids/index.js'
|
|
48
48
|
import type { Project, ProjectStatus } from '../../types/project/entity.js'
|
|
49
49
|
import type { Session } from '../../types/session/entity.js'
|
|
50
50
|
import type { ProjectId, SubSessionId, SummaryId, TopicId } from '../../types/session/ids.js'
|
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
asSessionId,
|
|
69
69
|
asSubSessionId,
|
|
70
70
|
asTopicId,
|
|
71
|
+
asTurnId,
|
|
71
72
|
generateProjectId,
|
|
72
73
|
generateSessionId,
|
|
73
74
|
generateSubSessionId,
|
|
@@ -237,6 +238,7 @@ interface PersistedSubSession {
|
|
|
237
238
|
interface PersistedSummary {
|
|
238
239
|
id: SummaryId
|
|
239
240
|
sessionRef: SessionId
|
|
241
|
+
turnRef?: TurnId
|
|
240
242
|
tenantId: TenantId
|
|
241
243
|
outcome: SessionSummaryOutcome
|
|
242
244
|
deliverables: readonly DeliverableRef[]
|
|
@@ -257,6 +259,10 @@ const SUMMARY_TERMINAL_FLIP_STATUSES: ReadonlySet<Session['status']> = new Set([
|
|
|
257
259
|
'awaiting_merge',
|
|
258
260
|
])
|
|
259
261
|
|
|
262
|
+
// Share the in-process writer guard across store instances addressing the same
|
|
263
|
+
// root. This is not a cross-process lease; external writers remain a host concern.
|
|
264
|
+
const sessionWriters = new Map<string, Promise<void>>()
|
|
265
|
+
|
|
260
266
|
/**
|
|
261
267
|
* Index of projectId → its directory path. Built lazily on lookup via
|
|
262
268
|
* {@link DiskSessionStore.resolveProjectDir}; populated by create / getProject.
|
|
@@ -276,6 +282,8 @@ interface SessionIndexEntry {
|
|
|
276
282
|
}
|
|
277
283
|
|
|
278
284
|
export class DiskSessionStore implements SessionStore {
|
|
285
|
+
readonly supportsInvocationSummaries: boolean = true
|
|
286
|
+
readonly supportsOwnerVersionCas: boolean = true
|
|
279
287
|
private readonly rootDir: string
|
|
280
288
|
private readonly projectIndex = new Map<ProjectId, ProjectIndexEntry>()
|
|
281
289
|
private readonly sessionIndex = new Map<SessionId, SessionIndexEntry>()
|
|
@@ -288,6 +296,24 @@ export class DiskSessionStore implements SessionStore {
|
|
|
288
296
|
this.rootDir = config.rootDir
|
|
289
297
|
}
|
|
290
298
|
|
|
299
|
+
private async withSessionWrite<T>(sessionId: SessionId, operation: () => Promise<T>): Promise<T> {
|
|
300
|
+
const key = resolve(this.rootDir, sessionId)
|
|
301
|
+
const previous = sessionWriters.get(key) ?? Promise.resolve()
|
|
302
|
+
let release = () => {}
|
|
303
|
+
const held = new Promise<void>((resolveWrite) => {
|
|
304
|
+
release = resolveWrite
|
|
305
|
+
})
|
|
306
|
+
const tail = previous.then(() => held)
|
|
307
|
+
sessionWriters.set(key, tail)
|
|
308
|
+
await previous
|
|
309
|
+
try {
|
|
310
|
+
return await operation()
|
|
311
|
+
} finally {
|
|
312
|
+
release()
|
|
313
|
+
if (sessionWriters.get(key) === tail) sessionWriters.delete(key)
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
291
317
|
// Project CRUD ------------------------------------------------------------
|
|
292
318
|
|
|
293
319
|
async createProject(params: CreateProjectParams, tenantId: TenantId): Promise<Project> {
|
|
@@ -654,6 +680,16 @@ export class DiskSessionStore implements SessionStore {
|
|
|
654
680
|
session: Session,
|
|
655
681
|
tenantId: TenantId,
|
|
656
682
|
expectedOwnerVersion?: number,
|
|
683
|
+
): Promise<void> {
|
|
684
|
+
await this.withSessionWrite(session.id, () =>
|
|
685
|
+
this.updateSessionUnlocked(session, tenantId, expectedOwnerVersion),
|
|
686
|
+
)
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
private async updateSessionUnlocked(
|
|
690
|
+
session: Session,
|
|
691
|
+
tenantId: TenantId,
|
|
692
|
+
expectedOwnerVersion?: number,
|
|
657
693
|
): Promise<void> {
|
|
658
694
|
const located = await this.locateSession(session.id)
|
|
659
695
|
if (!located) {
|
|
@@ -669,10 +705,8 @@ export class DiskSessionStore implements SessionStore {
|
|
|
669
705
|
if (existing) {
|
|
670
706
|
this.assertTenant(existing.tenantId, tenantId, `session(${session.id})`)
|
|
671
707
|
}
|
|
672
|
-
// Against
|
|
673
|
-
//
|
|
674
|
-
// processes can still both pass — see the contract note on
|
|
675
|
-
// `SessionStore.updateSession`. In one process it is the real lock.
|
|
708
|
+
// Against the stored version, under the shared in-process writer guard.
|
|
709
|
+
// Other processes can still both pass; see SessionStore.updateSession.
|
|
676
710
|
if (
|
|
677
711
|
expectedOwnerVersion !== undefined &&
|
|
678
712
|
existing !== null &&
|
|
@@ -862,11 +896,22 @@ export class DiskSessionStore implements SessionStore {
|
|
|
862
896
|
* leaves summary present + session still non-terminal — recovery replays
|
|
863
897
|
* the flip via {@link SessionSummaryMaterializer.recover}. Idempotent when
|
|
864
898
|
* the same summary is re-presented (recovery path); rejects a *different*
|
|
865
|
-
* summary
|
|
899
|
+
* summary at the same conversation or invocation key as {@link SessionAlreadySummarizedError}.
|
|
866
900
|
*/
|
|
867
901
|
async recordSummary(
|
|
868
902
|
summary: SessionSummaryRef & { materializedBy: 'kernel' },
|
|
869
903
|
tenantId: TenantId,
|
|
904
|
+
expectedOwnerVersion?: number,
|
|
905
|
+
): Promise<void> {
|
|
906
|
+
await this.withSessionWrite(summary.sessionRef, () =>
|
|
907
|
+
this.recordSummaryUnlocked(summary, tenantId, expectedOwnerVersion),
|
|
908
|
+
)
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
private async recordSummaryUnlocked(
|
|
912
|
+
summary: SessionSummaryRef & { materializedBy: 'kernel' },
|
|
913
|
+
tenantId: TenantId,
|
|
914
|
+
expectedOwnerVersion?: number,
|
|
870
915
|
): Promise<void> {
|
|
871
916
|
if (summary.tenantId !== tenantId) {
|
|
872
917
|
throw new TenantIsolationError({
|
|
@@ -884,8 +929,15 @@ export class DiskSessionStore implements SessionStore {
|
|
|
884
929
|
throw new Error(`Session ${summary.sessionRef} not found on disk`)
|
|
885
930
|
}
|
|
886
931
|
this.assertTenant(sessionRaw.tenantId, tenantId, `session(${summary.sessionRef})`)
|
|
932
|
+
if (expectedOwnerVersion !== undefined && sessionRaw.ownerVersion !== expectedOwnerVersion) {
|
|
933
|
+
throw new StaleSessionError({
|
|
934
|
+
sessionId: summary.sessionRef,
|
|
935
|
+
expectedVersion: expectedOwnerVersion,
|
|
936
|
+
actualVersion: sessionRaw.ownerVersion,
|
|
937
|
+
})
|
|
938
|
+
}
|
|
887
939
|
|
|
888
|
-
const summaryPath =
|
|
940
|
+
const summaryPath = summaryFile(located.path, summary.turnRef)
|
|
889
941
|
const existingRaw = await records.read<PersistedSummary>(summaryPath)
|
|
890
942
|
if (existingRaw) {
|
|
891
943
|
this.assertTenant(existingRaw.tenantId, tenantId, `summary(${existingRaw.id})`)
|
|
@@ -899,6 +951,8 @@ export class DiskSessionStore implements SessionStore {
|
|
|
899
951
|
// to the status flip so crash-between-writes is recovered.
|
|
900
952
|
} else {
|
|
901
953
|
// Step 1: persist summary.
|
|
954
|
+
if (summary.turnRef)
|
|
955
|
+
await mkdir(join(located.path, 'turn-summaries'), { recursive: true, mode: 0o700 })
|
|
902
956
|
await records.write(summaryPath, serializeSummary(summary))
|
|
903
957
|
}
|
|
904
958
|
|
|
@@ -913,10 +967,15 @@ export class DiskSessionStore implements SessionStore {
|
|
|
913
967
|
}
|
|
914
968
|
}
|
|
915
969
|
|
|
916
|
-
async getSummary(
|
|
970
|
+
async getSummary(
|
|
971
|
+
sessionId: SessionId,
|
|
972
|
+
tenantId: TenantId,
|
|
973
|
+
turnId?: TurnId,
|
|
974
|
+
): Promise<SessionSummaryRef | null> {
|
|
975
|
+
if (turnId !== undefined) asTurnId(turnId)
|
|
917
976
|
const located = await this.locateSession(sessionId)
|
|
918
977
|
if (!located) return null
|
|
919
|
-
const raw = await records.read<PersistedSummary>(
|
|
978
|
+
const raw = await records.read<PersistedSummary>(summaryFile(located.path, turnId))
|
|
920
979
|
if (!raw) return null
|
|
921
980
|
this.assertTenant(raw.tenantId, tenantId, `summary(${raw.id})`)
|
|
922
981
|
return deserializeSummary(raw)
|
|
@@ -1161,6 +1220,7 @@ function serializeSummary(s: SessionSummaryRef): PersistedSummary {
|
|
|
1161
1220
|
return {
|
|
1162
1221
|
id: s.id,
|
|
1163
1222
|
sessionRef: s.sessionRef,
|
|
1223
|
+
...(s.turnRef ? { turnRef: s.turnRef } : {}),
|
|
1164
1224
|
tenantId: s.tenantId,
|
|
1165
1225
|
outcome: s.outcome,
|
|
1166
1226
|
deliverables: s.deliverables,
|
|
@@ -1182,6 +1242,7 @@ function deserializeSummary(s: PersistedSummary): SessionSummaryRef {
|
|
|
1182
1242
|
return {
|
|
1183
1243
|
id: s.id,
|
|
1184
1244
|
sessionRef: s.sessionRef,
|
|
1245
|
+
...(s.turnRef ? { turnRef: asTurnId(s.turnRef) } : {}),
|
|
1185
1246
|
tenantId: s.tenantId,
|
|
1186
1247
|
outcome: s.outcome,
|
|
1187
1248
|
deliverables: s.deliverables,
|
|
@@ -1191,3 +1252,9 @@ function deserializeSummary(s: PersistedSummary): SessionSummaryRef {
|
|
|
1191
1252
|
materializedBy: 'kernel',
|
|
1192
1253
|
}
|
|
1193
1254
|
}
|
|
1255
|
+
|
|
1256
|
+
function summaryFile(directory: string, turnId?: TurnId): string {
|
|
1257
|
+
return turnId === undefined
|
|
1258
|
+
? join(directory, 'summary.json')
|
|
1259
|
+
: join(directory, 'turn-summaries', `${asTurnId(turnId)}.json`)
|
|
1260
|
+
}
|