@namzu/sdk 45.1.0 → 48.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 +436 -8
- package/README.md +7 -8
- package/dist/advisory/history.d.ts.map +1 -1
- package/dist/advisory/history.js +21 -1
- package/dist/advisory/history.js.map +1 -1
- package/dist/advisory/index.d.ts +1 -1
- package/dist/advisory/index.d.ts.map +1 -1
- package/dist/advisory/index.js +1 -1
- package/dist/advisory/index.js.map +1 -1
- package/dist/advisory/registry.d.ts +17 -0
- package/dist/advisory/registry.d.ts.map +1 -1
- package/dist/advisory/registry.js +26 -0
- package/dist/advisory/registry.js.map +1 -1
- package/dist/agents/PipelineAgent.d.ts +2 -46
- package/dist/agents/PipelineAgent.d.ts.map +1 -1
- package/dist/agents/PipelineAgent.js +2 -242
- package/dist/agents/PipelineAgent.js.map +1 -1
- package/dist/agents/QueryAgent.d.ts +21 -0
- package/dist/agents/QueryAgent.d.ts.map +1 -0
- package/dist/agents/QueryAgent.js +214 -0
- package/dist/agents/QueryAgent.js.map +1 -0
- package/dist/agents/ReactiveAgent.d.ts +4 -16
- package/dist/agents/ReactiveAgent.d.ts.map +1 -1
- package/dist/agents/ReactiveAgent.js +4 -183
- package/dist/agents/ReactiveAgent.js.map +1 -1
- package/dist/agents/RouterAgent.d.ts +2 -20
- package/dist/agents/RouterAgent.d.ts.map +1 -1
- package/dist/agents/RouterAgent.js +2 -266
- package/dist/agents/RouterAgent.js.map +1 -1
- package/dist/agents/SupervisorAgent.d.ts +3 -43
- package/dist/agents/SupervisorAgent.d.ts.map +1 -1
- package/dist/agents/SupervisorAgent.js +3 -418
- package/dist/agents/SupervisorAgent.js.map +1 -1
- package/dist/agents/defineAgent.d.ts +2 -1
- package/dist/agents/defineAgent.d.ts.map +1 -1
- package/dist/agents/defineAgent.js +6 -1
- package/dist/agents/defineAgent.js.map +1 -1
- package/dist/agents/examples/PipelineAgent.d.ts +46 -0
- package/dist/agents/examples/PipelineAgent.d.ts.map +1 -0
- package/dist/agents/examples/PipelineAgent.js +242 -0
- package/dist/agents/examples/PipelineAgent.js.map +1 -0
- package/dist/agents/examples/RouterAgent.d.ts +22 -0
- package/dist/agents/examples/RouterAgent.d.ts.map +1 -0
- package/dist/agents/examples/RouterAgent.js +268 -0
- package/dist/agents/examples/RouterAgent.js.map +1 -0
- package/dist/agents/examples/SupervisorAgent.d.ts +45 -0
- package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -0
- package/dist/agents/examples/SupervisorAgent.js +406 -0
- package/dist/agents/examples/SupervisorAgent.js.map +1 -0
- package/dist/agents/explore.d.ts +6 -3
- package/dist/agents/explore.d.ts.map +1 -1
- package/dist/agents/explore.js +6 -3
- package/dist/agents/explore.js.map +1 -1
- package/dist/agents/forward-options.d.ts +11 -0
- package/dist/agents/forward-options.d.ts.map +1 -0
- package/dist/agents/forward-options.js +15 -0
- package/dist/agents/forward-options.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/runAgent.d.ts +19 -8
- package/dist/agents/runAgent.d.ts.map +1 -1
- package/dist/agents/runAgent.js +99 -29
- package/dist/agents/runAgent.js.map +1 -1
- package/dist/authorization/command-line.d.ts +2 -0
- package/dist/authorization/command-line.d.ts.map +1 -1
- package/dist/authorization/command-line.js +2 -2
- package/dist/authorization/command-line.js.map +1 -1
- package/dist/authorization/gate.d.ts +13 -2
- package/dist/authorization/gate.d.ts.map +1 -1
- package/dist/authorization/gate.js +37 -5
- package/dist/authorization/gate.js.map +1 -1
- package/dist/authorization/program.d.ts +151 -0
- package/dist/authorization/program.d.ts.map +1 -0
- package/dist/authorization/program.js +713 -0
- package/dist/authorization/program.js.map +1 -0
- package/dist/authorization/reexec-wrapper.d.ts +106 -0
- package/dist/authorization/reexec-wrapper.d.ts.map +1 -0
- package/dist/authorization/reexec-wrapper.js +532 -0
- package/dist/authorization/reexec-wrapper.js.map +1 -0
- package/dist/authorization/rules.d.ts +9 -0
- package/dist/authorization/rules.d.ts.map +1 -1
- package/dist/authorization/rules.js +27 -1
- package/dist/authorization/rules.js.map +1 -1
- package/dist/authorization/shell-lexer.d.ts +39 -0
- package/dist/authorization/shell-lexer.d.ts.map +1 -1
- package/dist/authorization/shell-lexer.js +113 -69
- package/dist/authorization/shell-lexer.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +6 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/capabilities/index.d.ts +54 -0
- package/dist/capabilities/index.d.ts.map +1 -0
- package/dist/capabilities/index.js +92 -0
- package/dist/capabilities/index.js.map +1 -0
- package/dist/config/registry.d.ts +2 -1
- package/dist/config/registry.d.ts.map +1 -1
- package/dist/config/registry.js +3 -2
- package/dist/config/registry.js.map +1 -1
- package/dist/connector/index.d.ts +4 -4
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +3 -3
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/adapter.d.ts +16 -1
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +60 -4
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/client.d.ts +13 -4
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +20 -3
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/discovery.d.ts +24 -1
- package/dist/connector/mcp/discovery.d.ts.map +1 -1
- package/dist/connector/mcp/discovery.js +44 -0
- package/dist/connector/mcp/discovery.js.map +1 -1
- package/dist/connector/mcp/index.d.ts +2 -0
- package/dist/connector/mcp/index.d.ts.map +1 -1
- package/dist/connector/mcp/index.js +11 -0
- package/dist/connector/mcp/index.js.map +1 -1
- package/dist/connector/mcp/mcp-toolset.d.ts +133 -0
- package/dist/connector/mcp/mcp-toolset.d.ts.map +1 -0
- package/dist/connector/mcp/mcp-toolset.js +399 -0
- package/dist/connector/mcp/mcp-toolset.js.map +1 -0
- package/dist/connector/tools/index.d.ts +2 -2
- package/dist/connector/tools/index.d.ts.map +1 -1
- package/dist/connector/tools/index.js +1 -1
- package/dist/connector/tools/index.js.map +1 -1
- package/dist/connector/tools/router.d.ts +15 -13
- package/dist/connector/tools/router.d.ts.map +1 -1
- package/dist/connector/tools/router.js +30 -51
- package/dist/connector/tools/router.js.map +1 -1
- package/dist/contracts/a2a.d.ts +2 -2
- package/dist/directory/derive-supervisor.d.ts +2 -2
- package/dist/directory/derive-supervisor.d.ts.map +1 -1
- package/dist/directory/derive-supervisor.js +6 -7
- package/dist/directory/derive-supervisor.js.map +1 -1
- package/dist/directory/derive.d.ts.map +1 -1
- package/dist/directory/derive.js +5 -5
- package/dist/directory/derive.js.map +1 -1
- package/dist/execution/code-runtime/types.d.ts +2 -2
- package/dist/execution/code-runtime/types.js +1 -1
- package/dist/invariants/index.d.ts +2 -1
- package/dist/invariants/index.d.ts.map +1 -1
- package/dist/invariants/index.js +3 -2
- package/dist/invariants/index.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +9 -0
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/connector/environment.d.ts +6 -0
- package/dist/manager/connector/environment.d.ts.map +1 -1
- package/dist/manager/connector/environment.js +11 -4
- package/dist/manager/connector/environment.js.map +1 -1
- package/dist/manager/connector/index.d.ts +2 -2
- package/dist/manager/connector/index.d.ts.map +1 -1
- package/dist/manager/connector/index.js +2 -2
- package/dist/manager/connector/index.js.map +1 -1
- package/dist/manager/connector/tenant.d.ts +6 -0
- package/dist/manager/connector/tenant.d.ts.map +1 -1
- package/dist/manager/connector/tenant.js +11 -4
- package/dist/manager/connector/tenant.js.map +1 -1
- package/dist/manager/index.d.ts +2 -2
- package/dist/manager/index.d.ts.map +1 -1
- package/dist/manager/index.js +2 -2
- package/dist/manager/index.js.map +1 -1
- package/dist/manager/resident/learning-observation.d.ts +4 -4
- package/dist/manager/resident/learning.d.ts +36 -36
- package/dist/manager/session/attribution.d.ts +22 -0
- package/dist/manager/session/attribution.d.ts.map +1 -0
- package/dist/manager/session/attribution.js +64 -0
- package/dist/manager/session/attribution.js.map +1 -0
- package/dist/manager/session/turn-recorder.d.ts +14 -0
- package/dist/manager/session/turn-recorder.d.ts.map +1 -1
- package/dist/manager/session/turn-recorder.js +208 -55
- package/dist/manager/session/turn-recorder.js.map +1 -1
- package/dist/peers/address.d.ts +36 -0
- package/dist/peers/address.d.ts.map +1 -0
- package/dist/peers/address.js +52 -0
- package/dist/peers/address.js.map +1 -0
- package/dist/peers/client.d.ts +47 -0
- package/dist/peers/client.d.ts.map +1 -0
- package/dist/peers/client.js +132 -0
- package/dist/peers/client.js.map +1 -0
- package/dist/peers/dir.d.ts +88 -0
- package/dist/peers/dir.d.ts.map +1 -0
- package/dist/peers/dir.js +139 -0
- package/dist/peers/dir.js.map +1 -0
- package/dist/peers/endpoint.d.ts +144 -0
- package/dist/peers/endpoint.d.ts.map +1 -0
- package/dist/peers/endpoint.js +420 -0
- package/dist/peers/endpoint.js.map +1 -0
- package/dist/peers/envelope.d.ts +42 -0
- package/dist/peers/envelope.d.ts.map +1 -0
- package/dist/peers/envelope.js +110 -0
- package/dist/peers/envelope.js.map +1 -0
- package/dist/peers/index.d.ts +30 -0
- package/dist/peers/index.d.ts.map +1 -0
- package/dist/peers/index.js +22 -0
- package/dist/peers/index.js.map +1 -0
- package/dist/peers/protocol.d.ts +645 -0
- package/dist/peers/protocol.d.ts.map +1 -0
- package/dist/peers/protocol.js +151 -0
- package/dist/peers/protocol.js.map +1 -0
- package/dist/peers/record.d.ts +71 -0
- package/dist/peers/record.d.ts.map +1 -0
- package/dist/peers/record.js +45 -0
- package/dist/peers/record.js.map +1 -0
- package/dist/peers/registry.d.ts +54 -0
- package/dist/peers/registry.d.ts.map +1 -0
- package/dist/peers/registry.js +213 -0
- package/dist/peers/registry.js.map +1 -0
- package/dist/plugin/define.d.ts +24 -0
- package/dist/plugin/define.d.ts.map +1 -0
- package/dist/plugin/define.js +42 -0
- package/dist/plugin/define.js.map +1 -0
- package/dist/plugin/index.d.ts +2 -0
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +1 -0
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/lifecycle.d.ts +27 -3
- package/dist/plugin/lifecycle.d.ts.map +1 -1
- package/dist/plugin/lifecycle.js +242 -92
- package/dist/plugin/lifecycle.js.map +1 -1
- package/dist/plugin/resolver.d.ts +2 -2
- package/dist/plugin/resolver.d.ts.map +1 -1
- package/dist/plugin/resolver.js.map +1 -1
- package/dist/plugin/shell-hook.d.ts.map +1 -1
- package/dist/plugin/shell-hook.js +17 -3
- package/dist/plugin/shell-hook.js.map +1 -1
- package/dist/pricing/catalogue.generated.d.ts.map +1 -1
- package/dist/pricing/catalogue.generated.js +28 -4
- package/dist/pricing/catalogue.generated.js.map +1 -1
- package/dist/probe/errors.d.ts +2 -1
- package/dist/probe/errors.d.ts.map +1 -1
- package/dist/probe/errors.js +3 -2
- package/dist/probe/errors.js.map +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts +18 -7
- package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
- package/dist/prompt/coding-agent-doctrine.js +11 -6
- package/dist/prompt/coding-agent-doctrine.js.map +1 -1
- package/dist/prompt/contributions.d.ts +4 -1
- package/dist/prompt/contributions.d.ts.map +1 -1
- package/dist/prompt/contributions.js +7 -2
- package/dist/prompt/contributions.js.map +1 -1
- package/dist/prompt/index.d.ts +1 -1
- package/dist/prompt/index.d.ts.map +1 -1
- package/dist/prompt/index.js +1 -1
- package/dist/prompt/index.js.map +1 -1
- package/dist/provider/collect-chat-completion.d.ts +6 -1
- package/dist/provider/collect-chat-completion.d.ts.map +1 -1
- package/dist/provider/collect-chat-completion.js +88 -10
- package/dist/provider/collect-chat-completion.js.map +1 -1
- package/dist/provider/mock.d.ts.map +1 -1
- package/dist/provider/mock.js +23 -6
- package/dist/provider/mock.js.map +1 -1
- package/dist/provider/registry.d.ts +2 -1
- package/dist/provider/registry.d.ts.map +1 -1
- package/dist/provider/registry.js +3 -2
- package/dist/provider/registry.js.map +1 -1
- package/dist/provider/tool-call-framing.d.ts +164 -0
- package/dist/provider/tool-call-framing.d.ts.map +1 -0
- package/dist/provider/tool-call-framing.js +163 -0
- package/dist/provider/tool-call-framing.js.map +1 -0
- package/dist/public-runtime.d.ts +27 -14
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +49 -11
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +9 -6
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +13 -5
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +16 -5
- package/dist/public-types.d.ts.map +1 -1
- package/dist/read-model/registry.d.ts +2 -1
- package/dist/read-model/registry.d.ts.map +1 -1
- package/dist/read-model/registry.js +3 -2
- package/dist/read-model/registry.js.map +1 -1
- package/dist/registry/ManagedRegistry.d.ts +30 -0
- package/dist/registry/ManagedRegistry.d.ts.map +1 -1
- package/dist/registry/ManagedRegistry.js +45 -6
- package/dist/registry/ManagedRegistry.js.map +1 -1
- package/dist/registry/collision.d.ts +57 -0
- package/dist/registry/collision.d.ts.map +1 -0
- package/dist/registry/collision.js +41 -0
- package/dist/registry/collision.js.map +1 -0
- package/dist/registry/command/index.d.ts +5 -3
- package/dist/registry/command/index.d.ts.map +1 -1
- package/dist/registry/command/index.js +6 -4
- package/dist/registry/command/index.js.map +1 -1
- package/dist/registry/index.d.ts +3 -4
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +2 -2
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/plugin/index.d.ts.map +1 -1
- package/dist/registry/plugin/index.js +14 -1
- package/dist/registry/plugin/index.js.map +1 -1
- package/dist/registry/tool/callable.d.ts +22 -0
- package/dist/registry/tool/callable.d.ts.map +1 -0
- package/dist/registry/tool/callable.js +28 -0
- package/dist/registry/tool/callable.js.map +1 -0
- package/dist/registry/tool/execute.d.ts +14 -77
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +15 -720
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/registry/tool/portable.d.ts +25 -0
- package/dist/registry/tool/portable.d.ts.map +1 -1
- package/dist/registry/tool/portable.js +50 -0
- package/dist/registry/tool/portable.js.map +1 -1
- package/dist/registry/tool/presentation.d.ts +6 -5
- package/dist/registry/tool/presentation.d.ts.map +1 -1
- package/dist/registry/tool/presentation.js +3 -3
- package/dist/registry/tool/presentation.js.map +1 -1
- package/dist/runtime/bidi/session.d.ts +5 -4
- package/dist/runtime/bidi/session.d.ts.map +1 -1
- package/dist/runtime/bidi/session.js +18 -1
- package/dist/runtime/bidi/session.js.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.d.ts +82 -13
- package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.js +227 -17
- package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +37 -5
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +103 -14
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/file-evidence-replay.d.ts +1 -1
- package/dist/runtime/query/file-evidence-replay.d.ts.map +1 -1
- package/dist/runtime/query/file-evidence-replay.js +8 -7
- package/dist/runtime/query/file-evidence-replay.js.map +1 -1
- package/dist/runtime/query/fork/prepare.d.ts +4 -1
- package/dist/runtime/query/fork/prepare.d.ts.map +1 -1
- package/dist/runtime/query/fork/prepare.js +4 -0
- package/dist/runtime/query/fork/prepare.js.map +1 -1
- package/dist/runtime/query/guardrail-presets.d.ts +4 -3
- package/dist/runtime/query/guardrail-presets.d.ts.map +1 -1
- package/dist/runtime/query/guardrail-presets.js +4 -3
- package/dist/runtime/query/guardrail-presets.js.map +1 -1
- package/dist/runtime/query/index.d.ts +23 -10
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +149 -70
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +8 -1
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +2 -2
- package/dist/runtime/query/iteration/phases/context.d.ts.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 +55 -2
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +342 -116
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/iteration/tool-input.d.ts +79 -0
- package/dist/runtime/query/iteration/tool-input.d.ts.map +1 -0
- package/dist/runtime/query/iteration/tool-input.js +291 -0
- package/dist/runtime/query/iteration/tool-input.js.map +1 -0
- 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.map +1 -1
- package/dist/runtime/query/prelude-lease.d.ts +18 -0
- package/dist/runtime/query/prelude-lease.d.ts.map +1 -0
- package/dist/runtime/query/prelude-lease.js +121 -0
- package/dist/runtime/query/prelude-lease.js.map +1 -0
- package/dist/runtime/query/prepare-turn.d.ts.map +1 -1
- package/dist/runtime/query/prepare-turn.js +386 -187
- package/dist/runtime/query/prepare-turn.js.map +1 -1
- package/dist/runtime/query/prompt-cache.d.ts +2 -2
- package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
- package/dist/runtime/query/prompt.d.ts +2 -2
- package/dist/runtime/query/prompt.d.ts.map +1 -1
- package/dist/runtime/query/prompt.js +1 -1
- package/dist/runtime/query/prompt.js.map +1 -1
- package/dist/runtime/query/resume-session.d.ts.map +1 -1
- package/dist/runtime/query/resume-session.js +37 -2
- package/dist/runtime/query/resume-session.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +65 -3
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +143 -22
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +3 -2
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/runtime/query/turn-state.d.ts.map +1 -1
- package/dist/runtime/query/turn-state.js +5 -0
- package/dist/runtime/query/turn-state.js.map +1 -1
- package/dist/runtime/system-events.d.ts +112 -0
- package/dist/runtime/system-events.d.ts.map +1 -0
- package/dist/runtime/system-events.js +183 -0
- package/dist/runtime/system-events.js.map +1 -0
- package/dist/scheduler/delegating.d.ts +2 -1
- package/dist/scheduler/delegating.d.ts.map +1 -1
- package/dist/scheduler/delegating.js +3 -2
- package/dist/scheduler/delegating.js.map +1 -1
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/registry.d.ts +18 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +20 -0
- package/dist/skills/registry.js.map +1 -1
- package/dist/store/evidence/index-page.d.ts +2 -2
- package/dist/store/session-log/conformance.d.ts +1 -1
- package/dist/store/session-log/conformance.d.ts.map +1 -1
- package/dist/store/session-log/conformance.js +49 -8
- package/dist/store/session-log/conformance.js.map +1 -1
- package/dist/store/session-log/core.d.ts +8 -3
- package/dist/store/session-log/core.d.ts.map +1 -1
- package/dist/store/session-log/core.js +2 -1
- package/dist/store/session-log/core.js.map +1 -1
- package/dist/store/session-log/fold.d.ts +12 -0
- package/dist/store/session-log/fold.d.ts.map +1 -1
- package/dist/store/session-log/fold.js +57 -7
- package/dist/store/session-log/fold.js.map +1 -1
- package/dist/store/session-log/index.d.ts +2 -2
- package/dist/store/session-log/index.d.ts.map +1 -1
- package/dist/store/session-log/index.js +1 -1
- package/dist/store/session-log/index.js.map +1 -1
- package/dist/test-support/toolset.d.ts +19 -0
- package/dist/test-support/toolset.d.ts.map +1 -0
- package/dist/test-support/toolset.js +20 -0
- package/dist/test-support/toolset.js.map +1 -0
- package/dist/tools/builtins/bash.d.ts +29 -0
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +19 -9
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/browser-url.d.ts +1 -1
- package/dist/tools/builtins/browser-url.js +1 -1
- package/dist/tools/builtins/browser.d.ts +6 -6
- package/dist/tools/builtins/computer-use-coordinates.d.ts +65 -0
- package/dist/tools/builtins/computer-use-coordinates.d.ts.map +1 -0
- package/dist/tools/builtins/computer-use-coordinates.js +123 -0
- package/dist/tools/builtins/computer-use-coordinates.js.map +1 -0
- package/dist/tools/builtins/computer-use-image.d.ts +77 -0
- package/dist/tools/builtins/computer-use-image.d.ts.map +1 -0
- package/dist/tools/builtins/computer-use-image.js +223 -0
- package/dist/tools/builtins/computer-use-image.js.map +1 -0
- package/dist/tools/builtins/computer-use.d.ts +519 -14
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +1196 -183
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +9 -1
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +2 -1
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +1 -1
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/json-string-hint.d.ts +15 -0
- package/dist/tools/builtins/json-string-hint.d.ts.map +1 -0
- package/dist/tools/builtins/json-string-hint.js +17 -0
- package/dist/tools/builtins/json-string-hint.js.map +1 -0
- package/dist/tools/builtins/search-tools.d.ts.map +1 -1
- package/dist/tools/builtins/search-tools.js +7 -15
- package/dist/tools/builtins/search-tools.js.map +1 -1
- package/dist/tools/builtins/skill.d.ts +74 -0
- package/dist/tools/builtins/skill.d.ts.map +1 -1
- package/dist/tools/builtins/skill.js +214 -174
- package/dist/tools/builtins/skill.js.map +1 -1
- package/dist/tools/builtins/write-file.d.ts.map +1 -1
- package/dist/tools/builtins/write-file.js +11 -0
- package/dist/tools/builtins/write-file.js.map +1 -1
- package/dist/tools/command-shell.d.ts +10 -0
- package/dist/tools/command-shell.d.ts.map +1 -1
- package/dist/tools/command-shell.js +45 -1
- package/dist/tools/command-shell.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js +5 -0
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
- package/dist/tools/coordinator/ask-user-question.js +26 -13
- package/dist/tools/coordinator/ask-user-question.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +5 -0
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/coordinator/question-options.d.ts +78 -0
- package/dist/tools/coordinator/question-options.d.ts.map +1 -0
- package/dist/tools/coordinator/question-options.js +153 -0
- package/dist/tools/coordinator/question-options.js.map +1 -0
- package/dist/tools/defineTool.d.ts +12 -0
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +24 -0
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/memory/search.d.ts.map +1 -1
- package/dist/tools/memory/search.js +4 -1
- package/dist/tools/memory/search.js.map +1 -1
- package/dist/tools/memory/update.d.ts.map +1 -1
- package/dist/tools/memory/update.js +8 -5
- package/dist/tools/memory/update.js.map +1 -1
- package/dist/tools/render-nonce.d.ts +47 -0
- package/dist/tools/render-nonce.d.ts.map +1 -0
- package/dist/tools/render-nonce.js +63 -0
- package/dist/tools/render-nonce.js.map +1 -0
- package/dist/tools/roster.d.ts +46 -19
- package/dist/tools/roster.d.ts.map +1 -1
- package/dist/tools/roster.js +63 -33
- package/dist/tools/roster.js.map +1 -1
- package/dist/tools/schedules/present.d.ts.map +1 -1
- package/dist/tools/schedules/present.js +2 -0
- package/dist/tools/schedules/present.js.map +1 -1
- package/dist/tools/schedules/schedule-tool.d.ts +6 -5
- package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
- package/dist/tools/schedules/schedule-tool.js +208 -37
- package/dist/tools/schedules/schedule-tool.js.map +1 -1
- package/dist/tools/schedules/types.d.ts +120 -6
- package/dist/tools/schedules/types.d.ts.map +1 -1
- package/dist/tools/trusted-read-only.d.ts +9 -5
- package/dist/tools/trusted-read-only.d.ts.map +1 -1
- package/dist/tools/trusted-read-only.js +14 -10
- package/dist/tools/trusted-read-only.js.map +1 -1
- package/dist/tools/untrusted-envelope.d.ts +67 -28
- package/dist/tools/untrusted-envelope.d.ts.map +1 -1
- package/dist/tools/untrusted-envelope.js +108 -59
- package/dist/tools/untrusted-envelope.js.map +1 -1
- package/dist/toolsets/combine.d.ts +44 -0
- package/dist/toolsets/combine.d.ts.map +1 -0
- package/dist/toolsets/combine.js +153 -0
- package/dist/toolsets/combine.js.map +1 -0
- package/dist/toolsets/manager.d.ts +201 -0
- package/dist/toolsets/manager.d.ts.map +1 -0
- package/dist/toolsets/manager.js +837 -0
- package/dist/toolsets/manager.js.map +1 -0
- package/dist/toolsets/source-glob.d.ts +15 -0
- package/dist/toolsets/source-glob.d.ts.map +1 -0
- package/dist/toolsets/source-glob.js +23 -0
- package/dist/toolsets/source-glob.js.map +1 -0
- package/dist/toolsets/toolset.d.ts +20 -0
- package/dist/toolsets/toolset.d.ts.map +1 -0
- package/dist/toolsets/toolset.js +28 -0
- package/dist/toolsets/toolset.js.map +1 -0
- package/dist/toolsets/types.d.ts +128 -0
- package/dist/toolsets/types.d.ts.map +1 -0
- package/dist/toolsets/types.js +33 -0
- package/dist/toolsets/types.js.map +1 -0
- package/dist/toolsets/wrappers.d.ts +59 -0
- package/dist/toolsets/wrappers.d.ts.map +1 -0
- package/dist/toolsets/wrappers.js +165 -0
- package/dist/toolsets/wrappers.js.map +1 -0
- package/dist/types/agent/base.d.ts +27 -16
- package/dist/types/agent/base.d.ts.map +1 -1
- package/dist/types/agent/index.d.ts +1 -0
- package/dist/types/agent/index.d.ts.map +1 -1
- package/dist/types/agent/index.js +1 -0
- package/dist/types/agent/index.js.map +1 -1
- package/dist/types/agent/pipeline.d.ts +2 -0
- package/dist/types/agent/pipeline.d.ts.map +1 -1
- package/dist/types/agent/query.d.ts +117 -0
- package/dist/types/agent/query.d.ts.map +1 -0
- package/dist/types/agent/query.js +2 -0
- package/dist/types/agent/query.js.map +1 -0
- package/dist/types/agent/reactive.d.ts +2 -129
- package/dist/types/agent/reactive.d.ts.map +1 -1
- package/dist/types/agent/router.d.ts +2 -0
- package/dist/types/agent/router.d.ts.map +1 -1
- package/dist/types/agent/supervisor.d.ts +5 -2
- package/dist/types/agent/supervisor.d.ts.map +1 -1
- package/dist/types/authorization/index.d.ts +70 -12
- package/dist/types/authorization/index.d.ts.map +1 -1
- package/dist/types/authorization/index.js +11 -0
- package/dist/types/authorization/index.js.map +1 -1
- package/dist/types/computer-use/index.d.ts +176 -0
- package/dist/types/computer-use/index.d.ts.map +1 -1
- package/dist/types/computer-use/index.js.map +1 -1
- package/dist/types/connector/mcp.d.ts +32 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/errors/index.d.ts +15 -0
- package/dist/types/errors/index.d.ts.map +1 -1
- package/dist/types/errors/index.js.map +1 -1
- package/dist/types/hitl/index.d.ts +57 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/message/index.d.ts +130 -9
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +4 -1
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/plugin/index.d.ts +22 -4
- package/dist/types/plugin/index.d.ts.map +1 -1
- package/dist/types/plugin/index.js +1 -0
- package/dist/types/plugin/index.js.map +1 -1
- package/dist/types/provider/chat.d.ts +5 -0
- package/dist/types/provider/chat.d.ts.map +1 -1
- package/dist/types/provider/config.d.ts +8 -3
- package/dist/types/provider/config.d.ts.map +1 -1
- package/dist/types/provider/stream.d.ts +39 -0
- package/dist/types/provider/stream.d.ts.map +1 -1
- package/dist/types/sandbox/index.d.ts +1 -1
- package/dist/types/session/events.d.ts +14 -3
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/tool/index.d.ts +171 -91
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/types/toolset/index.d.ts +10 -40
- package/dist/types/toolset/index.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/advisory/history.ts +27 -2
- package/src/advisory/index.ts +1 -1
- package/src/advisory/registry.ts +33 -0
- package/src/agents/AGENTS.md +14 -7
- package/src/agents/PipelineAgent.ts +2 -303
- package/src/agents/QueryAgent.ts +269 -0
- package/src/agents/ReactiveAgent.ts +6 -216
- package/src/agents/RouterAgent.ts +2 -337
- package/src/agents/SupervisorAgent.ts +3 -476
- package/src/agents/defineAgent.ts +13 -2
- package/src/agents/examples/PipelineAgent.ts +302 -0
- package/src/agents/examples/RouterAgent.ts +338 -0
- package/src/agents/examples/SupervisorAgent.ts +472 -0
- package/src/agents/explore.ts +6 -3
- package/src/agents/forward-options.ts +37 -0
- package/src/agents/index.ts +2 -0
- package/src/agents/runAgent.ts +144 -37
- package/src/authorization/command-line.ts +2 -2
- package/src/authorization/gate.ts +46 -5
- package/src/authorization/program.ts +773 -0
- package/src/authorization/reexec-wrapper.ts +589 -0
- package/src/authorization/rules.ts +36 -1
- package/src/authorization/shell-lexer.ts +136 -63
- package/src/bridge/sse/mapper.ts +6 -0
- package/src/capabilities/index.ts +157 -0
- package/src/config/registry.ts +4 -1
- package/src/connector/index.ts +9 -2
- package/src/connector/mcp/adapter.ts +58 -3
- package/src/connector/mcp/client.ts +20 -4
- package/src/connector/mcp/discovery.ts +60 -0
- package/src/connector/mcp/index.ts +13 -0
- package/src/connector/mcp/mcp-toolset.ts +515 -0
- package/src/connector/tools/index.ts +2 -2
- package/src/connector/tools/router.ts +35 -58
- package/src/directory/derive-supervisor.ts +12 -8
- package/src/directory/derive.ts +8 -5
- package/src/execution/code-runtime/types.ts +2 -2
- package/src/invariants/index.ts +4 -1
- package/src/manager/agent/lifecycle.ts +9 -0
- package/src/manager/connector/environment.ts +17 -4
- package/src/manager/connector/index.ts +2 -2
- package/src/manager/connector/tenant.ts +17 -4
- package/src/manager/index.ts +2 -2
- package/src/manager/session/attribution.ts +79 -0
- package/src/manager/session/turn-recorder.ts +211 -55
- package/src/peers/address.ts +58 -0
- package/src/peers/client.ts +202 -0
- package/src/peers/dir.ts +176 -0
- package/src/peers/endpoint.ts +564 -0
- package/src/peers/envelope.ts +121 -0
- package/src/peers/index.ts +96 -0
- package/src/peers/protocol.ts +196 -0
- package/src/peers/record.ts +56 -0
- package/src/peers/registry.ts +241 -0
- package/src/plugin/define.ts +68 -0
- package/src/plugin/index.ts +2 -0
- package/src/plugin/lifecycle.ts +286 -106
- package/src/plugin/resolver.ts +6 -3
- package/src/plugin/shell-hook.ts +21 -5
- package/src/pricing/catalogue.generated.ts +28 -4
- package/src/pricing/rates.source.json +27 -6
- package/src/probe/errors.ts +4 -1
- package/src/prompt/coding-agent-doctrine.ts +22 -10
- package/src/prompt/contributions.ts +12 -2
- package/src/prompt/index.ts +1 -0
- package/src/provider/collect-chat-completion.ts +96 -11
- package/src/provider/mock.ts +24 -6
- package/src/provider/registry.ts +4 -1
- package/src/provider/tool-call-framing.ts +226 -0
- package/src/public-runtime.ts +152 -9
- package/src/public-tools.ts +43 -5
- package/src/public-types.ts +65 -6
- package/src/read-model/registry.ts +7 -2
- package/src/registry/ManagedRegistry.ts +57 -6
- package/src/registry/collision.ts +64 -0
- package/src/registry/command/index.ts +7 -3
- package/src/registry/index.ts +3 -9
- package/src/registry/plugin/index.ts +14 -1
- package/src/registry/tool/callable.ts +36 -0
- package/src/registry/tool/execute.ts +16 -839
- package/src/registry/tool/portable.ts +59 -0
- package/src/registry/tool/presentation.ts +6 -5
- package/src/runtime/bidi/session.ts +24 -5
- package/src/runtime/query/executor/tool-call-admission.ts +288 -22
- package/src/runtime/query/executor.ts +129 -16
- package/src/runtime/query/file-evidence-replay.ts +8 -7
- package/src/runtime/query/fork/prepare.ts +6 -1
- package/src/runtime/query/guardrail-presets.ts +4 -3
- package/src/runtime/query/index.ts +199 -101
- package/src/runtime/query/iteration/index.ts +13 -3
- package/src/runtime/query/iteration/phases/compaction.ts +1 -1
- package/src/runtime/query/iteration/phases/context.ts +2 -2
- package/src/runtime/query/iteration/phases/tool-review.ts +59 -2
- package/src/runtime/query/iteration/stream-turn.ts +390 -136
- package/src/runtime/query/iteration/tool-input.ts +284 -0
- package/src/runtime/query/observation-context.ts +2 -2
- package/src/runtime/query/prelude-lease.ts +132 -0
- package/src/runtime/query/prepare-turn.ts +477 -198
- package/src/runtime/query/prompt-cache.ts +2 -2
- package/src/runtime/query/prompt.ts +4 -4
- package/src/runtime/query/resume-session.ts +42 -3
- package/src/runtime/query/review-policy.ts +190 -24
- package/src/runtime/query/tooling.ts +3 -6
- package/src/runtime/query/turn-state.ts +4 -0
- package/src/runtime/system-events.ts +246 -0
- package/src/scheduler/delegating.ts +7 -2
- package/src/skills/index.ts +1 -1
- package/src/skills/registry.ts +33 -0
- package/src/store/session-log/conformance.ts +51 -8
- package/src/store/session-log/core.ts +10 -4
- package/src/store/session-log/fold.ts +33 -7
- package/src/store/session-log/index.ts +2 -0
- package/src/test-support/toolset.ts +23 -0
- package/src/tools/builtins/bash.ts +27 -10
- package/src/tools/builtins/browser-url.ts +1 -1
- package/src/tools/builtins/computer-use-coordinates.ts +144 -0
- package/src/tools/builtins/computer-use-image.ts +278 -0
- package/src/tools/builtins/computer-use.ts +1495 -191
- package/src/tools/builtins/edit.ts +12 -2
- package/src/tools/builtins/index.ts +7 -1
- package/src/tools/builtins/json-string-hint.ts +16 -0
- package/src/tools/builtins/search-tools.ts +7 -20
- package/src/tools/builtins/skill.ts +304 -174
- package/src/tools/builtins/write-file.ts +12 -0
- package/src/tools/command-shell.ts +46 -1
- package/src/tools/coordinator/agent.ts +6 -0
- package/src/tools/coordinator/ask-user-question.ts +29 -15
- package/src/tools/coordinator/index.ts +6 -0
- package/src/tools/coordinator/question-options.ts +195 -0
- package/src/tools/defineTool.ts +38 -0
- package/src/tools/memory/search.ts +4 -1
- package/src/tools/memory/update.ts +8 -5
- package/src/tools/render-nonce.ts +69 -0
- package/src/tools/roster.ts +84 -33
- package/src/tools/schedules/present.ts +2 -0
- package/src/tools/schedules/schedule-tool.ts +238 -39
- package/src/tools/schedules/types.ts +120 -6
- package/src/tools/trusted-read-only.ts +19 -10
- package/src/tools/untrusted-envelope.ts +121 -57
- package/src/toolsets/combine.ts +181 -0
- package/src/toolsets/manager.ts +996 -0
- package/src/toolsets/source-glob.ts +22 -0
- package/src/toolsets/toolset.ts +31 -0
- package/src/toolsets/types.ts +154 -0
- package/src/toolsets/wrappers.ts +191 -0
- package/src/types/agent/base.ts +29 -16
- package/src/types/agent/index.ts +1 -0
- package/src/types/agent/pipeline.ts +2 -0
- package/src/types/agent/query.ts +129 -0
- package/src/types/agent/reactive.ts +5 -142
- package/src/types/agent/router.ts +2 -0
- package/src/types/agent/supervisor.ts +5 -2
- package/src/types/authorization/index.ts +33 -0
- package/src/types/computer-use/index.ts +202 -0
- package/src/types/connector/mcp.ts +32 -0
- package/src/types/errors/index.ts +15 -0
- package/src/types/hitl/index.ts +57 -0
- package/src/types/message/index.ts +135 -7
- package/src/types/plugin/index.ts +44 -21
- package/src/types/provider/chat.ts +5 -0
- package/src/types/provider/config.ts +8 -3
- package/src/types/provider/stream.ts +39 -0
- package/src/types/sandbox/index.ts +1 -1
- package/src/types/session/events.ts +14 -3
- package/src/types/tool/index.ts +173 -105
- package/src/types/toolset/index.ts +10 -47
- package/dist/registry/toolset/catalog.d.ts +0 -42
- package/dist/registry/toolset/catalog.d.ts.map +0 -1
- package/dist/registry/toolset/catalog.js +0 -234
- package/dist/registry/toolset/catalog.js.map +0 -1
- package/src/registry/toolset/catalog.ts +0 -308
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type SessionLogEntry,
|
|
11
11
|
type SessionLogHead,
|
|
12
12
|
SessionMessageFold,
|
|
13
|
+
withMessageId,
|
|
13
14
|
} from '../../store/session-log/index.js'
|
|
14
15
|
import type { SpillRef } from '../../store/session-log/spill.js'
|
|
15
16
|
import { getActiveSpanContext } from '../../telemetry/runtime-accessors.js'
|
|
@@ -52,6 +53,7 @@ import {
|
|
|
52
53
|
} from '../../utils/cost.js'
|
|
53
54
|
import { asCheckpointId, generateAuditEventId, generateMessageId } from '../../utils/id.js'
|
|
54
55
|
import { childSessionEnded } from '../agent/child-session.js'
|
|
56
|
+
import { assertSessionLogAttribution } from './attribution.js'
|
|
55
57
|
|
|
56
58
|
/** Which provider and model a cost is priced against. */
|
|
57
59
|
export interface PricingSubject {
|
|
@@ -66,10 +68,29 @@ export interface RecordedMessage {
|
|
|
66
68
|
readonly messageId?: MessageId
|
|
67
69
|
}
|
|
68
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Stamp (or clear) `id` on a message already living in `recorder.messages`,
|
|
73
|
+
* in place — the recorder's own bookkeeping (`#ids`, `#recorded`, `#view`)
|
|
74
|
+
* is keyed by object IDENTITY, so replacing the array element the way
|
|
75
|
+
* `withMessageId` does would desync it. `recorder.messages`/`Turn.messages`
|
|
76
|
+
* is the one place a message a HOST passed in is allowed to change under
|
|
77
|
+
* it: once the kernel records that exact object, it is stamped with the id
|
|
78
|
+
* its record was given, which is the id `BaseMessage.id` documents. A
|
|
79
|
+
* message read from the log for a DIFFERENT purpose (a fold a host did not
|
|
80
|
+
* hand in, a checkpoint restore) is never this function's object — it goes
|
|
81
|
+
* through `withMessageId`, a copy, because nothing here owns it to mutate.
|
|
82
|
+
*/
|
|
83
|
+
function stampMessageId(message: Message, id: MessageId | undefined): void {
|
|
84
|
+
if (id === undefined) delete (message as { id?: MessageId }).id
|
|
85
|
+
else (message as { id?: MessageId }).id = id
|
|
86
|
+
}
|
|
87
|
+
|
|
69
88
|
/** How {@link TurnRecorder.open} takes the session's writer lease and starts an empty log. */
|
|
70
89
|
export interface TurnRecorderOpenOptions {
|
|
71
90
|
/** A lease the caller already holds. Absent: the recorder claims one and releases it at the end. */
|
|
72
91
|
readonly lease?: SessionLease
|
|
92
|
+
/** A lease claimed by the query prelude, transferred to the recorder for release. */
|
|
93
|
+
readonly ownLease?: boolean
|
|
73
94
|
/** The holder name for a lease the recorder claims. */
|
|
74
95
|
readonly holder?: string
|
|
75
96
|
/** Lease time-to-live for a lease the recorder claims. Renewed while the turn runs. */
|
|
@@ -197,6 +218,9 @@ export class TurnRecorder {
|
|
|
197
218
|
#released = false
|
|
198
219
|
#leaseHolder = ''
|
|
199
220
|
#leaseTtlMs = DEFAULT_TURN_LEASE_TTL_MS
|
|
221
|
+
#leaseHeartbeat: ReturnType<typeof setInterval> | undefined
|
|
222
|
+
#leaseRenewal: Promise<void> = Promise.resolve()
|
|
223
|
+
#leaseRenewalError: unknown
|
|
200
224
|
#chain: Promise<void> = Promise.resolve()
|
|
201
225
|
#failure: unknown = undefined
|
|
202
226
|
#view: ViewEntry[] = []
|
|
@@ -233,7 +257,10 @@ export class TurnRecorder {
|
|
|
233
257
|
throw new NamzuError({
|
|
234
258
|
code: 'invalid_config',
|
|
235
259
|
message: `The session log belongs to session ${config.sessionLog.sessionId}, not ${config.sessionId}.`,
|
|
236
|
-
details: {
|
|
260
|
+
details: {
|
|
261
|
+
sessionId: config.sessionId,
|
|
262
|
+
logSessionId: config.sessionLog.sessionId,
|
|
263
|
+
},
|
|
237
264
|
})
|
|
238
265
|
}
|
|
239
266
|
this.#turn = {
|
|
@@ -344,7 +371,10 @@ export class TurnRecorder {
|
|
|
344
371
|
get costInfo(): CostInfo {
|
|
345
372
|
const unpriced = Math.max(0, this.tokenUsage.totalTokens - this.#turn.tokenUsage.totalTokens)
|
|
346
373
|
return unpriced > 0
|
|
347
|
-
? {
|
|
374
|
+
? {
|
|
375
|
+
...this.#turn.costInfo,
|
|
376
|
+
unpricedTokens: this.#turn.costInfo.unpricedTokens + unpriced,
|
|
377
|
+
}
|
|
348
378
|
: this.#turn.costInfo
|
|
349
379
|
}
|
|
350
380
|
|
|
@@ -570,60 +600,114 @@ export class TurnRecorder {
|
|
|
570
600
|
async open(options: TurnRecorderOpenOptions): Promise<RecordedMessage[]> {
|
|
571
601
|
if (this.#phase !== 'new') throw new Error('TurnRecorder.open was already called.')
|
|
572
602
|
this.#leaseTtlMs = options.leaseTtlMs ?? DEFAULT_TURN_LEASE_TTL_MS
|
|
573
|
-
this.#leaseHolder =
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
603
|
+
this.#leaseHolder =
|
|
604
|
+
options.holder ?? options.lease?.holder ?? `namzu:${process.pid}:${this.turnId}`
|
|
605
|
+
try {
|
|
606
|
+
if (options.lease) {
|
|
607
|
+
this.#lease = options.lease
|
|
608
|
+
this.#ownsLease = options.ownLease === true
|
|
609
|
+
}
|
|
610
|
+
// Claiming a log may repair a torn tail. Refuse a foreign owner
|
|
611
|
+
// before that mutation, then recheck under the lease below.
|
|
612
|
+
await assertSessionLogAttribution(this.log, this.#config)
|
|
613
|
+
if (!options.lease) {
|
|
614
|
+
const lease = await this.log.claim({
|
|
615
|
+
holder: this.#leaseHolder,
|
|
616
|
+
ttlMs: this.#leaseTtlMs,
|
|
617
|
+
repairTornTail: false,
|
|
618
|
+
})
|
|
619
|
+
if (lease === null) {
|
|
620
|
+
const active = await this.log.activeTurn()
|
|
621
|
+
if (active) {
|
|
622
|
+
throw new TurnInProgressError({
|
|
623
|
+
sessionId: this.sessionId,
|
|
624
|
+
activeTurnId: active.turnId,
|
|
625
|
+
state: 'running',
|
|
626
|
+
})
|
|
627
|
+
}
|
|
628
|
+
throw new NamzuError({
|
|
629
|
+
code: 'invalid_config',
|
|
630
|
+
message: `Session ${this.sessionId} is leased by another writer; wait for it to finish or pass the lease you hold.`,
|
|
631
|
+
details: { sessionId: this.sessionId },
|
|
585
632
|
})
|
|
586
633
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
634
|
+
this.#lease = lease
|
|
635
|
+
this.#ownsLease = true
|
|
636
|
+
}
|
|
637
|
+
const lease = this.#lease
|
|
638
|
+
if (!lease) throw new Error('TurnRecorder.open did not acquire a writer lease.')
|
|
639
|
+
if (this.#ownsLease) {
|
|
640
|
+
this.#leaseHeartbeat = setInterval(() => this.#queueLeaseRenewal(), this.#leaseTtlMs / 2)
|
|
641
|
+
this.#leaseHeartbeat.unref()
|
|
642
|
+
}
|
|
643
|
+
const head = await this.log.head()
|
|
644
|
+
if (head === null) {
|
|
645
|
+
this.#lastEntry = await this.log.append(lease, {
|
|
646
|
+
type: 'session_started',
|
|
647
|
+
projectId: this.projectId,
|
|
648
|
+
tenantId: this.tenantId,
|
|
649
|
+
topicId: this.topicId,
|
|
650
|
+
cwd: options.session.cwd,
|
|
651
|
+
agent: {
|
|
652
|
+
id: this.#config.agentId,
|
|
653
|
+
name: this.#config.agentName,
|
|
654
|
+
...(options.session.agentType ? { type: options.session.agentType } : {}),
|
|
655
|
+
},
|
|
656
|
+
...(options.session.origin ? { origin: options.session.origin } : {}),
|
|
657
|
+
...(options.session.forkedFrom ? { forkedFrom: options.session.forkedFrom } : {}),
|
|
591
658
|
})
|
|
659
|
+
} else {
|
|
660
|
+
await assertSessionLogAttribution(this.log, this.#config)
|
|
592
661
|
}
|
|
593
|
-
|
|
594
|
-
|
|
662
|
+
if (options.session.forkedFrom) {
|
|
663
|
+
this.#turn.forkedFrom = options.session.forkedFrom
|
|
664
|
+
}
|
|
665
|
+
this.#phase = 'open'
|
|
666
|
+
return await readFoldedHistory(this.log)
|
|
667
|
+
} catch (error) {
|
|
668
|
+
await this.release()
|
|
669
|
+
throw error
|
|
595
670
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/** Serialize timer and write-triggered renewals so release uses the latest token. */
|
|
674
|
+
#queueLeaseRenewal(): void {
|
|
675
|
+
this.#leaseRenewal = this.#leaseRenewal
|
|
676
|
+
.then(async () => {
|
|
677
|
+
if (!this.#ownsLease || this.#released || this.#leaseRenewalError !== undefined) return
|
|
678
|
+
const current = this.#lease
|
|
679
|
+
if (!current) return
|
|
680
|
+
const renewed = await this.log.claim({
|
|
681
|
+
holder: this.#leaseHolder,
|
|
682
|
+
ttlMs: this.#leaseTtlMs,
|
|
683
|
+
repairTornTail: false,
|
|
684
|
+
})
|
|
685
|
+
if (renewed === null || renewed.fence !== current.fence) {
|
|
686
|
+
if (renewed !== null) await this.log.release(renewed).catch(() => undefined)
|
|
687
|
+
throw new NamzuError({
|
|
688
|
+
code: 'invalid_config',
|
|
689
|
+
message: `Session ${this.sessionId} lost its writer lease during the turn.`,
|
|
690
|
+
details: { sessionId: this.sessionId },
|
|
691
|
+
})
|
|
692
|
+
}
|
|
693
|
+
this.#lease = renewed
|
|
694
|
+
})
|
|
695
|
+
.catch((error: unknown) => {
|
|
696
|
+
this.#leaseRenewalError ??= error
|
|
611
697
|
})
|
|
612
|
-
}
|
|
613
|
-
if (options.session.forkedFrom) {
|
|
614
|
-
this.#turn.forkedFrom = options.session.forkedFrom
|
|
615
|
-
}
|
|
616
|
-
this.#phase = 'open'
|
|
617
|
-
return readFoldedHistory(this.log)
|
|
618
698
|
}
|
|
619
699
|
|
|
620
700
|
/** Renew a lease this recorder claimed when it is past half its life. */
|
|
621
701
|
async #leaseForWrite(): Promise<SessionLease> {
|
|
622
|
-
|
|
623
|
-
if (
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
if (
|
|
702
|
+
if (!this.#lease) throw new Error('TurnRecorder.open must run before the turn writes.')
|
|
703
|
+
if (this.#ownsLease) {
|
|
704
|
+
await this.#leaseRenewal
|
|
705
|
+
if (this.#leaseRenewalError !== undefined) throw this.#leaseRenewalError
|
|
706
|
+
if (this.#lease.expiresAt - Date.now() < this.#leaseTtlMs / 2) {
|
|
707
|
+
this.#queueLeaseRenewal()
|
|
708
|
+
await this.#leaseRenewal
|
|
709
|
+
if (this.#leaseRenewalError !== undefined) throw this.#leaseRenewalError
|
|
710
|
+
}
|
|
627
711
|
}
|
|
628
712
|
return this.#lease as SessionLease
|
|
629
713
|
}
|
|
@@ -631,10 +715,12 @@ export class TurnRecorder {
|
|
|
631
715
|
/** Give up a lease the recorder claimed. Never throws. */
|
|
632
716
|
async release(): Promise<void> {
|
|
633
717
|
if (!this.#ownsLease || !this.#lease) return
|
|
634
|
-
const lease = this.#lease
|
|
635
|
-
this.#ownsLease = false
|
|
636
718
|
this.#released = true
|
|
637
|
-
|
|
719
|
+
if (this.#leaseHeartbeat !== undefined) clearInterval(this.#leaseHeartbeat)
|
|
720
|
+
this.#leaseHeartbeat = undefined
|
|
721
|
+
await this.#leaseRenewal
|
|
722
|
+
this.#ownsLease = false
|
|
723
|
+
await this.log.release(this.#lease).catch(() => undefined)
|
|
638
724
|
}
|
|
639
725
|
|
|
640
726
|
#enqueue<T>(operation: () => Promise<T>): Promise<T> {
|
|
@@ -842,7 +928,9 @@ export class TurnRecorder {
|
|
|
842
928
|
recordChildSessionEvent(
|
|
843
929
|
event: Extract<
|
|
844
930
|
SessionEvent,
|
|
845
|
-
{
|
|
931
|
+
{
|
|
932
|
+
type: 'child_session_spawned' | 'child_session_messaged' | 'child_session_idled'
|
|
933
|
+
}
|
|
846
934
|
>,
|
|
847
935
|
childLog?: SessionLog,
|
|
848
936
|
): Promise<SessionLogEntry | undefined> {
|
|
@@ -877,8 +965,12 @@ export class TurnRecorder {
|
|
|
877
965
|
if (!target?.id) return
|
|
878
966
|
const current = target.message as AssistantMessage
|
|
879
967
|
if (current.content === result) return
|
|
880
|
-
const replacement: AssistantMessage = { ...current, content: result }
|
|
881
968
|
const targetMessageId = target.id
|
|
969
|
+
const replacement: AssistantMessage = {
|
|
970
|
+
...current,
|
|
971
|
+
content: result,
|
|
972
|
+
id: targetMessageId,
|
|
973
|
+
}
|
|
882
974
|
await this.#enqueue(() =>
|
|
883
975
|
this.#append({
|
|
884
976
|
type: 'message_replaced',
|
|
@@ -911,11 +1003,15 @@ export class TurnRecorder {
|
|
|
911
1003
|
*/
|
|
912
1004
|
pushMessage(
|
|
913
1005
|
message: Message,
|
|
914
|
-
options: {
|
|
1006
|
+
options: {
|
|
1007
|
+
readonly messageId?: MessageId
|
|
1008
|
+
readonly transient?: boolean
|
|
1009
|
+
} = {},
|
|
915
1010
|
): void {
|
|
916
1011
|
if (options.messageId) {
|
|
917
1012
|
this.#ids.set(message, options.messageId)
|
|
918
1013
|
this.#recorded.set(message, options.messageId)
|
|
1014
|
+
stampMessageId(message, options.messageId)
|
|
919
1015
|
}
|
|
920
1016
|
if (options.transient) this.#transient.add(message)
|
|
921
1017
|
this.#turn.messages.push(message)
|
|
@@ -965,6 +1061,7 @@ export class TurnRecorder {
|
|
|
965
1061
|
this.#ids.set(message, id)
|
|
966
1062
|
}
|
|
967
1063
|
this.#recorded.set(message, id)
|
|
1064
|
+
stampMessageId(message, id)
|
|
968
1065
|
return id
|
|
969
1066
|
}
|
|
970
1067
|
|
|
@@ -1054,6 +1151,11 @@ export class TurnRecorder {
|
|
|
1054
1151
|
for (const entry of summaryEntries) {
|
|
1055
1152
|
entry.id = undefined
|
|
1056
1153
|
this.#ids.delete(entry.message)
|
|
1154
|
+
// A summary member is no longer individually recorded — a fresh
|
|
1155
|
+
// fold would show it with no id, so its object stops claiming one
|
|
1156
|
+
// too. `entry.message` is the same object `live` holds at this
|
|
1157
|
+
// position (built from it, above), so this is what a caller sees.
|
|
1158
|
+
stampMessageId(entry.message, undefined)
|
|
1057
1159
|
}
|
|
1058
1160
|
const summary = summaryEntries.map((entry) => entry.message)
|
|
1059
1161
|
const keptMessageIds = keptEntries.map((entry) => entry.id as MessageId)
|
|
@@ -1129,7 +1231,11 @@ export class TurnRecorder {
|
|
|
1129
1231
|
type: 'audit',
|
|
1130
1232
|
...(event.turnId ? { turnId: event.turnId } : {}),
|
|
1131
1233
|
auditId: event.id,
|
|
1132
|
-
actor: {
|
|
1234
|
+
actor: {
|
|
1235
|
+
kind: 'agent',
|
|
1236
|
+
agentId: this.#turn.metadata.agentId,
|
|
1237
|
+
tenantId: this.tenantId,
|
|
1238
|
+
},
|
|
1133
1239
|
...(input.persona !== undefined ? { persona: input.persona } : {}),
|
|
1134
1240
|
action: input.what.action,
|
|
1135
1241
|
...(input.what.tool !== undefined ? { tool: input.what.tool } : {}),
|
|
@@ -1241,19 +1347,69 @@ export async function readFoldedHistory(
|
|
|
1241
1347
|
const out: RecordedMessage[] = []
|
|
1242
1348
|
const spilled = fold.spilledSummary
|
|
1243
1349
|
if (spilled) {
|
|
1350
|
+
// `withMessageId(message, undefined)` strips any id already embedded in
|
|
1351
|
+
// the spilled JSON — same as the inline branch below, and for the same
|
|
1352
|
+
// reason `readEverRecordedMessages`'s doc comment gives: a summary
|
|
1353
|
+
// member has no record of its own. A synthesized summary never had an
|
|
1354
|
+
// id, so this is invisible there; a fork's seeded summary IS the
|
|
1355
|
+
// source session's own already-id'd messages, and without this a
|
|
1356
|
+
// spilled (large) fork's first live turn reads its fold back carrying
|
|
1357
|
+
// a DIFFERENT session's ids and fails reconciliation as foreign.
|
|
1244
1358
|
for (const message of JSON.parse(await log.readSpill(spilled.spill)) as Message[]) {
|
|
1245
|
-
out.push({ message })
|
|
1359
|
+
out.push({ message: withMessageId(message, undefined) })
|
|
1246
1360
|
}
|
|
1247
1361
|
}
|
|
1248
1362
|
for (const entry of fold.entries()) {
|
|
1249
1363
|
const message = entry.spill
|
|
1250
1364
|
? (JSON.parse(await log.readSpill(entry.spill as SpillRef)) as Message)
|
|
1251
1365
|
: entry.message
|
|
1252
|
-
out.push({
|
|
1366
|
+
out.push({
|
|
1367
|
+
message: withMessageId(message, entry.messageId),
|
|
1368
|
+
...(entry.messageId ? { messageId: entry.messageId } : {}),
|
|
1369
|
+
})
|
|
1253
1370
|
}
|
|
1254
1371
|
return out
|
|
1255
1372
|
}
|
|
1256
1373
|
|
|
1374
|
+
/**
|
|
1375
|
+
* Every message this session's log has ever recorded, keyed by the durable
|
|
1376
|
+
* id its `message` record gave it — including one a compaction has since
|
|
1377
|
+
* folded into a summary and dropped from {@link readFoldedHistory}'s
|
|
1378
|
+
* current fold. A `message_replaced` record's content wins over the message
|
|
1379
|
+
* it targets, the log's own precedence for "what this id means now."
|
|
1380
|
+
*
|
|
1381
|
+
* A compaction summary member has no entry here: it was never its own
|
|
1382
|
+
* `message` record (see {@link RecordedMessage.messageId}), so nothing can
|
|
1383
|
+
* recognise it by id — a caller's copy of it is reconciled by value instead.
|
|
1384
|
+
*/
|
|
1385
|
+
export async function readEverRecordedMessages(
|
|
1386
|
+
log: SessionLog,
|
|
1387
|
+
): Promise<ReadonlyMap<MessageId, Message>> {
|
|
1388
|
+
const latest = new Map<MessageId, { readonly content: Message; readonly spill?: SpillRef }>()
|
|
1389
|
+
for await (const entry of log.read()) {
|
|
1390
|
+
const record = entry.record as SessionRecord
|
|
1391
|
+
if (record.type === 'message') {
|
|
1392
|
+
latest.set(record.messageId, {
|
|
1393
|
+
content: record.content,
|
|
1394
|
+
...(record.spill ? { spill: record.spill } : {}),
|
|
1395
|
+
})
|
|
1396
|
+
} else if (record.type === 'message_replaced') {
|
|
1397
|
+
latest.set(record.targetMessageId, {
|
|
1398
|
+
content: record.content,
|
|
1399
|
+
...(record.spill ? { spill: record.spill } : {}),
|
|
1400
|
+
})
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
const resolved = new Map<MessageId, Message>()
|
|
1404
|
+
for (const [id, entry] of latest) {
|
|
1405
|
+
const content = entry.spill
|
|
1406
|
+
? (JSON.parse(await log.readSpill(entry.spill)) as Message)
|
|
1407
|
+
: entry.content
|
|
1408
|
+
resolved.set(id, withMessageId(content, id))
|
|
1409
|
+
}
|
|
1410
|
+
return resolved
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1257
1413
|
/**
|
|
1258
1414
|
* A session's audit trail: its `audit` records as {@link AuditEvent}s, in log
|
|
1259
1415
|
* order, each numbered among the session's audit entries. What
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Peer addresses are URIs so a later cross-machine transport can be added
|
|
3
|
+
* without redesigning the registry or the protocol: `uds:<path>` and
|
|
4
|
+
* `pipe:<name>` today, `a2a:https://…` later (design §1.1). Only the two
|
|
5
|
+
* local schemes are ever SERVED or DIALED by this package; `a2a:` addresses
|
|
6
|
+
* are recognised so a reader can tell them apart, not connected to.
|
|
7
|
+
*
|
|
8
|
+
* @experimental
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { join } from 'node:path'
|
|
12
|
+
import { peerSocketFileName } from './dir.js'
|
|
13
|
+
|
|
14
|
+
export type PeerAddress =
|
|
15
|
+
| { readonly scheme: 'uds'; readonly path: string }
|
|
16
|
+
| { readonly scheme: 'pipe'; readonly path: string }
|
|
17
|
+
| { readonly scheme: 'a2a'; readonly url: string }
|
|
18
|
+
|
|
19
|
+
export class PeerAddressError extends Error {
|
|
20
|
+
override readonly name = 'PeerAddressError'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The `uds:<path>` address for a session's socket inside a hardened runtime directory. */
|
|
24
|
+
export function udsPeerAddress(runtimeDir: string, sessionId: string): string {
|
|
25
|
+
return `uds:${join(runtimeDir, peerSocketFileName(sessionId))}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The `pipe:<name>` address for a session's Windows named pipe.
|
|
30
|
+
*
|
|
31
|
+
* `<name>` is the full pipe path Node's `net` module dials directly
|
|
32
|
+
* (`\\.\pipe\namzu-<uid-hash>-<session-short>`, design §1.1) — coded here for
|
|
33
|
+
* completeness; this package does not run its tests on win32, so the shape
|
|
34
|
+
* is reviewed rather than exercised.
|
|
35
|
+
*/
|
|
36
|
+
export function pipePeerAddress(uidHash: string, sessionShort: string): string {
|
|
37
|
+
return `pipe:\\\\.\\pipe\\namzu-${uidHash}-${sessionShort}`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Parse a peer address URI. Throws {@link PeerAddressError} on an unrecognised or empty scheme. */
|
|
41
|
+
export function parsePeerAddress(address: string): PeerAddress {
|
|
42
|
+
if (address.startsWith('uds:')) {
|
|
43
|
+
const path = address.slice('uds:'.length)
|
|
44
|
+
if (path.length === 0) throw new PeerAddressError(`Empty uds: address: ${address}`)
|
|
45
|
+
return { scheme: 'uds', path }
|
|
46
|
+
}
|
|
47
|
+
if (address.startsWith('pipe:')) {
|
|
48
|
+
const path = address.slice('pipe:'.length)
|
|
49
|
+
if (path.length === 0) throw new PeerAddressError(`Empty pipe: address: ${address}`)
|
|
50
|
+
return { scheme: 'pipe', path }
|
|
51
|
+
}
|
|
52
|
+
if (address.startsWith('a2a:')) {
|
|
53
|
+
const url = address.slice('a2a:'.length)
|
|
54
|
+
if (url.length === 0) throw new PeerAddressError(`Empty a2a: address: ${address}`)
|
|
55
|
+
return { scheme: 'a2a', url }
|
|
56
|
+
}
|
|
57
|
+
throw new PeerAddressError(`Unrecognised peer address scheme: ${address}`)
|
|
58
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A client for one connection of `namzu-peer/1`: connect, write one request
|
|
3
|
+
* line, read one response line, close. Mirrors the shape of this
|
|
4
|
+
* repository's other local control clients (`queryRunner` in
|
|
5
|
+
* `packages/cli/src/integrations/resident/runner-control.ts`,
|
|
6
|
+
* `callEndpoint` in `packages/cli/src/schedule/daemon/endpoint.ts`): an
|
|
7
|
+
* authenticated response PROVES responsiveness, and its absence never proves
|
|
8
|
+
* the peer is dead — only that this attempt could not reach it.
|
|
9
|
+
*
|
|
10
|
+
* @experimental
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { createConnection } from 'node:net'
|
|
14
|
+
import { parsePeerAddress } from './address.js'
|
|
15
|
+
import {
|
|
16
|
+
type DeliverRequest,
|
|
17
|
+
type DeliverResponse,
|
|
18
|
+
DeliverResponseSchema,
|
|
19
|
+
MAX_PEER_REQUEST_BYTES,
|
|
20
|
+
type NoticeRequest,
|
|
21
|
+
type NoticeResponse,
|
|
22
|
+
NoticeResponseSchema,
|
|
23
|
+
PEER_PROTOCOL_VERSION,
|
|
24
|
+
type PingRequest,
|
|
25
|
+
type PingResponse,
|
|
26
|
+
PingResponseSchema,
|
|
27
|
+
type SubscribeIdleRequest,
|
|
28
|
+
type SubscribeIdleResponse,
|
|
29
|
+
SubscribeIdleResponseSchema,
|
|
30
|
+
} from './protocol.js'
|
|
31
|
+
import type { PeerRecord } from './record.js'
|
|
32
|
+
|
|
33
|
+
const DEFAULT_TIMEOUT_MS = 2_000
|
|
34
|
+
|
|
35
|
+
export class PeerClientError extends Error {
|
|
36
|
+
override readonly name = 'PeerClientError'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** An authenticated reply proves responsiveness; every other outcome names why none arrived. */
|
|
40
|
+
export type PeerClientResult<T> =
|
|
41
|
+
| ({ readonly kind: 'responded' } & T)
|
|
42
|
+
| { readonly kind: 'unreachable'; readonly reason: string }
|
|
43
|
+
|
|
44
|
+
function connectPath(address: string): string {
|
|
45
|
+
const parsed = parsePeerAddress(address)
|
|
46
|
+
if (parsed.scheme === 'a2a') {
|
|
47
|
+
throw new PeerClientError(`PeerClient cannot dial an a2a: address directly: ${address}`)
|
|
48
|
+
}
|
|
49
|
+
return parsed.path
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** One request, one response, one connection. */
|
|
53
|
+
function sendPeerRequest<T>(
|
|
54
|
+
address: string,
|
|
55
|
+
request: unknown,
|
|
56
|
+
parseResponse: (value: unknown) => T,
|
|
57
|
+
timeoutMs: number,
|
|
58
|
+
): Promise<PeerClientResult<T>> {
|
|
59
|
+
return new Promise((resolve) => {
|
|
60
|
+
let settled = false
|
|
61
|
+
const finish = (result: PeerClientResult<T>): void => {
|
|
62
|
+
if (settled) return
|
|
63
|
+
settled = true
|
|
64
|
+
clearTimeout(timer)
|
|
65
|
+
socket.destroy()
|
|
66
|
+
resolve(result)
|
|
67
|
+
}
|
|
68
|
+
const unreachable = (error: unknown): void =>
|
|
69
|
+
finish({
|
|
70
|
+
kind: 'unreachable',
|
|
71
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
72
|
+
})
|
|
73
|
+
const timer = setTimeout(() => unreachable(new Error('Peer request timed out.')), timeoutMs)
|
|
74
|
+
let path: string
|
|
75
|
+
try {
|
|
76
|
+
path = connectPath(address)
|
|
77
|
+
} catch (error) {
|
|
78
|
+
clearTimeout(timer)
|
|
79
|
+
resolve({
|
|
80
|
+
kind: 'unreachable',
|
|
81
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
82
|
+
})
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
const socket = createConnection({ path })
|
|
86
|
+
let buffered = Buffer.alloc(0)
|
|
87
|
+
socket.once('error', unreachable)
|
|
88
|
+
socket.once('close', () =>
|
|
89
|
+
unreachable(new Error('Peer connection closed before a response arrived.')),
|
|
90
|
+
)
|
|
91
|
+
socket.once('connect', () => {
|
|
92
|
+
socket.write(`${JSON.stringify(request)}\n`)
|
|
93
|
+
})
|
|
94
|
+
socket.on('data', (chunk: Buffer) => {
|
|
95
|
+
if (buffered.length + chunk.length > MAX_PEER_REQUEST_BYTES) {
|
|
96
|
+
unreachable(new Error('Peer response exceeded the size limit.'))
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
buffered = Buffer.concat([buffered, chunk])
|
|
100
|
+
const newline = buffered.indexOf(10)
|
|
101
|
+
if (newline < 0) return
|
|
102
|
+
try {
|
|
103
|
+
const parsed: unknown = JSON.parse(buffered.subarray(0, newline).toString('utf8'))
|
|
104
|
+
finish({ kind: 'responded', ...parseResponse(parsed) })
|
|
105
|
+
} catch (error) {
|
|
106
|
+
unreachable(error)
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface PeerClientOptions {
|
|
113
|
+
/** Default 2000ms. */
|
|
114
|
+
readonly timeoutMs?: number
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* `ping`, `deliver`, `subscribe_idle` and `notice` over `namzu-peer/1`.
|
|
119
|
+
*
|
|
120
|
+
* `deliver`/`subscribeIdle`/`notice` read the RECIPIENT's token from the
|
|
121
|
+
* `PeerRecord` passed in — the wire's token is always the recipient's own,
|
|
122
|
+
* asserted by the caller and verified by the server (design §1.1, §1.3).
|
|
123
|
+
* `ping` takes a bare address and carries no token; see the file header for
|
|
124
|
+
* why.
|
|
125
|
+
*/
|
|
126
|
+
export class PeerClient {
|
|
127
|
+
private readonly timeoutMs: number
|
|
128
|
+
|
|
129
|
+
constructor(options: PeerClientOptions = {}) {
|
|
130
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
ping(address: string, timeoutMs = this.timeoutMs): Promise<PeerClientResult<PingResponse>> {
|
|
134
|
+
const request: PingRequest = { protocol: PEER_PROTOCOL_VERSION, op: 'ping' }
|
|
135
|
+
return sendPeerRequest(address, request, (value) => PingResponseSchema.parse(value), timeoutMs)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
deliver(
|
|
139
|
+
record: Pick<PeerRecord, 'address' | 'token'>,
|
|
140
|
+
message: Omit<DeliverRequest, 'protocol' | 'op' | 'token'>,
|
|
141
|
+
): Promise<PeerClientResult<DeliverResponse>> {
|
|
142
|
+
const request: DeliverRequest = {
|
|
143
|
+
protocol: PEER_PROTOCOL_VERSION,
|
|
144
|
+
op: 'deliver',
|
|
145
|
+
token: record.token,
|
|
146
|
+
...message,
|
|
147
|
+
}
|
|
148
|
+
return sendPeerRequest(
|
|
149
|
+
record.address,
|
|
150
|
+
request,
|
|
151
|
+
(value) => DeliverResponseSchema.parse(value),
|
|
152
|
+
this.timeoutMs,
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
subscribeIdle(
|
|
157
|
+
record: Pick<PeerRecord, 'address' | 'token'>,
|
|
158
|
+
message: Omit<SubscribeIdleRequest, 'protocol' | 'op' | 'token'>,
|
|
159
|
+
): Promise<PeerClientResult<SubscribeIdleResponse>> {
|
|
160
|
+
const request: SubscribeIdleRequest = {
|
|
161
|
+
protocol: PEER_PROTOCOL_VERSION,
|
|
162
|
+
op: 'subscribe_idle',
|
|
163
|
+
token: record.token,
|
|
164
|
+
...message,
|
|
165
|
+
}
|
|
166
|
+
return sendPeerRequest(
|
|
167
|
+
record.address,
|
|
168
|
+
request,
|
|
169
|
+
(value) => SubscribeIdleResponseSchema.parse(value),
|
|
170
|
+
this.timeoutMs,
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
notice(
|
|
175
|
+
record: Pick<PeerRecord, 'address' | 'token'>,
|
|
176
|
+
message: Omit<NoticeRequest, 'protocol' | 'op' | 'token'>,
|
|
177
|
+
): Promise<PeerClientResult<NoticeResponse>> {
|
|
178
|
+
const request: NoticeRequest = {
|
|
179
|
+
protocol: PEER_PROTOCOL_VERSION,
|
|
180
|
+
op: 'notice',
|
|
181
|
+
token: record.token,
|
|
182
|
+
...message,
|
|
183
|
+
}
|
|
184
|
+
return sendPeerRequest(
|
|
185
|
+
record.address,
|
|
186
|
+
request,
|
|
187
|
+
(value) => NoticeResponseSchema.parse(value),
|
|
188
|
+
this.timeoutMs,
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** A bare liveness probe: `true` iff an unauthenticated `ping` answers within `timeoutMs`. Used by `listLivePeers`. */
|
|
194
|
+
export function pingPeer(address: string, timeoutMs = DEFAULT_TIMEOUT_MS): Promise<boolean> {
|
|
195
|
+
const request: PingRequest = { protocol: PEER_PROTOCOL_VERSION, op: 'ping' }
|
|
196
|
+
return sendPeerRequest(
|
|
197
|
+
address,
|
|
198
|
+
request,
|
|
199
|
+
(value) => PingResponseSchema.parse(value),
|
|
200
|
+
timeoutMs,
|
|
201
|
+
).then((result) => result.kind === 'responded')
|
|
202
|
+
}
|