@ai-agent-forge/agent-forge 0.86.7 → 0.87.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 +18 -0
- package/README.md +8 -9
- package/dist/artifacts/artifact-store.d.ts.map +1 -1
- package/dist/artifacts/artifact-store.js +9 -5
- package/dist/artifacts/artifact-store.js.map +1 -1
- package/dist/bundle/.build-manifest.json +410 -371
- package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
- package/dist/bundle/chunks/chunk-BFC2BDVJ.js +13 -0
- package/dist/bundle/chunks/chunk-MOHOLL3F.js +1456 -0
- package/dist/bundle/chunks/image-resize-worker.js +12 -1
- package/dist/bundle/chunks/{virtual-modules-3IZ4MYSQ.js → virtual-modules-KZ5DRH7Q.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/client.js +1 -1
- package/dist/bundle/index.js +2 -2
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +231 -185
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts.map +1 -1
- package/dist/cli/auth-check.js +3 -2
- package/dist/cli/auth-check.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js +15 -9
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +14 -7
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/command.d.ts.map +1 -1
- package/dist/cli/experimental/command.js +6 -5
- package/dist/cli/experimental/command.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +9 -8
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/plugin-manager-controller.d.ts.map +1 -1
- package/dist/cli/plugin-manager-controller.js +2 -1
- package/dist/cli/plugin-manager-controller.js.map +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +8 -5
- package/dist/cli/serve.js.map +1 -1
- package/dist/client/remote-session.d.ts.map +1 -1
- package/dist/client/remote-session.js +16 -9
- package/dist/client/remote-session.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-capability-contract.d.ts +0 -7
- package/dist/core/agent-capability-contract.d.ts.map +1 -1
- package/dist/core/agent-capability-contract.js +72 -68
- package/dist/core/agent-capability-contract.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +5 -4
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +28 -22
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-context.d.ts.map +1 -1
- package/dist/core/agent-session-context.js +18 -13
- package/dist/core/agent-session-context.js.map +1 -1
- package/dist/core/agent-session-model.d.ts.map +1 -1
- package/dist/core/agent-session-model.js +2 -1
- package/dist/core/agent-session-model.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +3 -2
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +7 -6
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-tools.d.ts.map +1 -1
- package/dist/core/agent-session-tools.js +3 -2
- package/dist/core/agent-session-tools.js.map +1 -1
- package/dist/core/agent-session.d.ts +40 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +142 -34
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +11 -5
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +9 -6
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +2 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/embedded-sdk.d.ts.map +1 -1
- package/dist/core/embedded-sdk.js +10 -6
- package/dist/core/embedded-sdk.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +9 -4
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/extensions/agent-composition.d.ts.map +1 -1
- package/dist/core/extensions/agent-composition.js +26 -19
- package/dist/core/extensions/agent-composition.js.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.js +3 -2
- package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
- package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-lifecycle.js +20 -17
- package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
- package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-overflow-policy.js +2 -1
- package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -1
- package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-retry-policy.js +2 -1
- package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -1
- package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-skills.js +7 -6
- package/dist/core/extensions/bootstrap-skills.js.map +1 -1
- package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-tools.js +2 -1
- package/dist/core/extensions/bootstrap-tools.js.map +1 -1
- package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
- package/dist/core/extensions/capability-plugin.js +37 -13
- package/dist/core/extensions/capability-plugin.js.map +1 -1
- package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-events.js +17 -13
- package/dist/core/extensions/capability-runtime-events.js.map +1 -1
- package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-guards.js +16 -15
- package/dist/core/extensions/capability-runtime-guards.js.map +1 -1
- package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-manifest.js +52 -30
- package/dist/core/extensions/capability-runtime-manifest.js.map +1 -1
- package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-validation.js +66 -65
- package/dist/core/extensions/capability-runtime-validation.js.map +1 -1
- package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime.js +147 -127
- package/dist/core/extensions/capability-runtime.js.map +1 -1
- package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -1
- package/dist/core/extensions/compaction-memory-failure-mode.js +3 -2
- package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -1
- package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -1
- package/dist/core/extensions/context-strategy-binding.js +7 -4
- package/dist/core/extensions/context-strategy-binding.js.map +1 -1
- package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
- package/dist/core/extensions/lifecycle-catalog.js +290 -279
- package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
- package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -1
- package/dist/core/extensions/lifecycle-delivery-queue.js +3 -2
- package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -1
- package/dist/core/facade/coding-agent-facade.d.ts +6 -0
- package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
- package/dist/core/facade/coding-agent-facade.js +2 -0
- package/dist/core/facade/coding-agent-facade.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/i18n/index.d.ts +14 -0
- package/dist/core/i18n/index.d.ts.map +1 -0
- package/dist/core/i18n/index.js +67 -0
- package/dist/core/i18n/index.js.map +1 -0
- package/dist/core/i18n/locales/en/example.d.ts +7 -0
- package/dist/core/i18n/locales/en/example.d.ts.map +1 -0
- package/dist/core/i18n/locales/en/example.js +7 -0
- package/dist/core/i18n/locales/en/example.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/cli.d.ts +8 -0
- package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/cli.js +227 -0
- package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/common.d.ts +6 -0
- package/dist/core/i18n/locales/zh-cn/common.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/common.js +6 -0
- package/dist/core/i18n/locales/zh-cn/common.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +13 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js +173 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts +12 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +582 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.js +55 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts +11 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +455 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.js +191 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/example.d.ts +7 -0
- package/dist/core/i18n/locales/zh-cn/example.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/example.js +10 -0
- package/dist/core/i18n/locales/zh-cn/example.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/index.d.ts +2 -0
- package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/index.js +41 -0
- package/dist/core/i18n/locales/zh-cn/index.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts +10 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js +265 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.d.ts +11 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.js +67 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts +7 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.js +39 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts +10 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.js +15 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts +13 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +102 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts +12 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js +288 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js +79 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts +8 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.js +72 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.js.map +1 -0
- package/dist/core/keybindings.d.ts +15 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +18 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +5 -1
- package/dist/core/logger.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +8 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-install-host.d.ts.map +1 -1
- package/dist/core/package-install-host.js +4 -3
- package/dist/core/package-install-host.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +15 -10
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-resource-collection.d.ts.map +1 -1
- package/dist/core/package-resource-collection.js +2 -1
- package/dist/core/package-resource-collection.js.map +1 -1
- package/dist/core/package-source.d.ts.map +1 -1
- package/dist/core/package-source.js +3 -2
- package/dist/core/package-source.js.map +1 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +22 -13
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +6 -2
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +15 -5
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/sdk.d.ts +19 -5
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +74 -54
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +5 -2
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +2 -1
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +39 -29
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-storage.d.ts.map +1 -1
- package/dist/core/session-storage.js +3 -3
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/settings-manager.d.ts +11 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +27 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +53 -32
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +25 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +11 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +9 -4
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +3 -2
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +2 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +6 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/durable/durable-service.d.ts.map +1 -1
- package/dist/durable/durable-service.js +25 -18
- package/dist/durable/durable-service.js.map +1 -1
- package/dist/host/checkpoint-commit.d.ts.map +1 -1
- package/dist/host/checkpoint-commit.js +2 -1
- package/dist/host/checkpoint-commit.js.map +1 -1
- package/dist/host/manual-compaction.d.ts.map +1 -1
- package/dist/host/manual-compaction.js +2 -1
- package/dist/host/manual-compaction.js.map +1 -1
- package/dist/host/output-projection.d.ts +0 -13
- package/dist/host/output-projection.d.ts.map +1 -1
- package/dist/host/output-projection.js +16 -2
- package/dist/host/output-projection.js.map +1 -1
- package/dist/host/summary-retry.d.ts.map +1 -1
- package/dist/host/summary-retry.js +3 -2
- package/dist/host/summary-retry.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +94 -58
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
- package/dist/modes/interactive/components/agents-view.js +18 -15
- package/dist/modes/interactive/components/agents-view.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +6 -5
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +12 -7
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +2 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +6 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +9 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +18 -15
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +2 -1
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-editor.js +5 -4
- package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
- package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-input.js +2 -1
- package/dist/modes/interactive/components/dialog-input.js.map +1 -1
- package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-selector.js +4 -3
- package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +11 -10
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +7 -4
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +3 -2
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +12 -11
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
- package/dist/modes/interactive/components/mermaid.js +6 -2
- package/dist/modes/interactive/components/mermaid.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +28 -16
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +10 -9
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/plugin-manager-entry.js +22 -13
- package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
- package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/plugin-selection-entry.js +27 -12
- package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
- package/dist/modes/interactive/components/queue-manager-selector.d.ts +60 -0
- package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/queue-manager-selector.js +166 -0
- package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +16 -14
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +43 -31
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +113 -96
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.js +5 -4
- package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +3 -2
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +4 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +14 -5
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +2 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +11 -4
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +8 -3
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-list.js +7 -6
- package/dist/modes/interactive/components/tree-list.js.map +1 -1
- package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-render.js +28 -23
- package/dist/modes/interactive/components/tree-render.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +9 -7
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +5 -4
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
- package/dist/modes/interactive/components/workflow-view.js +36 -21
- package/dist/modes/interactive/components/workflow-view.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +2 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-auth.js +71 -40
- package/dist/modes/interactive/interactive-auth.js.map +1 -1
- package/dist/modes/interactive/interactive-commands.d.ts +1 -0
- package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-commands.js +3 -0
- package/dist/modes/interactive/interactive-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-dialog-ui.js +5 -5
- package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-format.js +34 -18
- package/dist/modes/interactive/interactive-format.js.map +1 -1
- package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-helpers.js +7 -2
- package/dist/modes/interactive/interactive-helpers.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +327 -243
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.d.ts +9 -0
- package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +79 -25
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +5 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +26 -23
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +3 -2
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +3 -2
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +28 -13
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/plugins/ecosystem/catalog.d.ts.map +1 -1
- package/dist/plugins/ecosystem/catalog.js +3 -2
- package/dist/plugins/ecosystem/catalog.js.map +1 -1
- package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
- package/dist/plugins/ecosystem/cli.js +2 -1
- package/dist/plugins/ecosystem/cli.js.map +1 -1
- package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -1
- package/dist/plugins/ecosystem/default-plugin-market.js +3 -2
- package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -1
- package/dist/plugins/ecosystem/distribution.d.ts.map +1 -1
- package/dist/plugins/ecosystem/distribution.js +2 -1
- package/dist/plugins/ecosystem/distribution.js.map +1 -1
- package/dist/plugins/ecosystem/installer.d.ts.map +1 -1
- package/dist/plugins/ecosystem/installer.js +3 -2
- package/dist/plugins/ecosystem/installer.js.map +1 -1
- package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-disk-registry-source.js +20 -17
- package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-distribution-host.js +35 -34
- package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.js +35 -34
- package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.js +9 -8
- package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-persistence.js +4 -3
- package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js +21 -5
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-trust-root.js +10 -9
- package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -1
- package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-registry-source.js +31 -30
- package/dist/plugins/ecosystem/node-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-release-package-source.js +30 -29
- package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-tar-writer.js +11 -10
- package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -1
- package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-url-package-source.js +21 -20
- package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -1
- package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -1
- package/dist/plugins/ecosystem/plugin-acquisition.js +3 -2
- package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.js +2 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -1
- package/dist/plugins/ecosystem/registry.d.ts.map +1 -1
- package/dist/plugins/ecosystem/registry.js +35 -32
- package/dist/plugins/ecosystem/registry.js.map +1 -1
- package/dist/plugins/ecosystem/resolver.d.ts.map +1 -1
- package/dist/plugins/ecosystem/resolver.js +3 -2
- package/dist/plugins/ecosystem/resolver.js.map +1 -1
- package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -1
- package/dist/plugins/ecosystem/selection-store.js +11 -10
- package/dist/plugins/ecosystem/selection-store.js.map +1 -1
- package/dist/plugins/ecosystem/selection.d.ts.map +1 -1
- package/dist/plugins/ecosystem/selection.js +8 -7
- package/dist/plugins/ecosystem/selection.js.map +1 -1
- package/dist/plugins/ecosystem/state.d.ts.map +1 -1
- package/dist/plugins/ecosystem/state.js +24 -23
- package/dist/plugins/ecosystem/state.js.map +1 -1
- package/dist/plugins/ecosystem/updates.d.ts.map +1 -1
- package/dist/plugins/ecosystem/updates.js +5 -4
- package/dist/plugins/ecosystem/updates.js.map +1 -1
- package/dist/plugins/mcp-http.d.ts +0 -17
- package/dist/plugins/mcp-http.d.ts.map +1 -1
- package/dist/plugins/mcp-http.js +30 -7
- package/dist/plugins/mcp-http.js.map +1 -1
- package/dist/plugins/plugin-supervisor.d.ts.map +1 -1
- package/dist/plugins/plugin-supervisor.js +19 -1
- package/dist/plugins/plugin-supervisor.js.map +1 -1
- package/dist/profile/first-roles.d.ts.map +1 -1
- package/dist/profile/first-roles.js +10 -1
- package/dist/profile/first-roles.js.map +1 -1
- package/dist/profile/goal-plugin.d.ts.map +1 -1
- package/dist/profile/goal-plugin.js +24 -5
- package/dist/profile/goal-plugin.js.map +1 -1
- package/dist/profile/identity.d.ts.map +1 -1
- package/dist/profile/identity.js +7 -6
- package/dist/profile/identity.js.map +1 -1
- package/dist/profile/lock.d.ts.map +1 -1
- package/dist/profile/lock.js +15 -1
- package/dist/profile/lock.js.map +1 -1
- package/dist/profile/plan-plugin.d.ts.map +1 -1
- package/dist/profile/plan-plugin.js +26 -13
- package/dist/profile/plan-plugin.js.map +1 -1
- package/dist/profile/plugin-profiles.d.ts.map +1 -1
- package/dist/profile/plugin-profiles.js +2 -1
- package/dist/profile/plugin-profiles.js.map +1 -1
- package/dist/profile/policy-manifest.d.ts.map +1 -1
- package/dist/profile/policy-manifest.js +5 -4
- package/dist/profile/policy-manifest.js.map +1 -1
- package/dist/profile/profile-registry.d.ts +0 -12
- package/dist/profile/profile-registry.d.ts.map +1 -1
- package/dist/profile/profile-registry.js +14 -1
- package/dist/profile/profile-registry.js.map +1 -1
- package/dist/profile/role-catalog.d.ts +0 -1
- package/dist/profile/role-catalog.d.ts.map +1 -1
- package/dist/profile/role-catalog.js +17 -15
- package/dist/profile/role-catalog.js.map +1 -1
- package/dist/profile/role-orchestrator.d.ts.map +1 -1
- package/dist/profile/role-orchestrator.js +8 -7
- package/dist/profile/role-orchestrator.js.map +1 -1
- package/dist/profile/role-runner.d.ts.map +1 -1
- package/dist/profile/role-runner.js +3 -2
- package/dist/profile/role-runner.js.map +1 -1
- package/dist/profile/root-facade.d.ts.map +1 -1
- package/dist/profile/root-facade.js +2 -1
- package/dist/profile/root-facade.js.map +1 -1
- package/dist/profile/skill-discovery-wiring.d.ts.map +1 -1
- package/dist/profile/skill-discovery-wiring.js +7 -2
- package/dist/profile/skill-discovery-wiring.js.map +1 -1
- package/dist/profile/state-store.d.ts.map +1 -1
- package/dist/profile/state-store.js +13 -9
- package/dist/profile/state-store.js.map +1 -1
- package/dist/profile/todo-plugin.d.ts.map +1 -1
- package/dist/profile/todo-plugin.js +9 -4
- package/dist/profile/todo-plugin.js.map +1 -1
- package/dist/profiles/builtin-suites.d.ts +13 -6
- package/dist/profiles/builtin-suites.d.ts.map +1 -1
- package/dist/profiles/builtin-suites.js +15 -6
- package/dist/profiles/builtin-suites.js.map +1 -1
- package/dist/profiles/suite-loader.d.ts +25 -1
- package/dist/profiles/suite-loader.d.ts.map +1 -1
- package/dist/profiles/suite-loader.js +34 -9
- package/dist/profiles/suite-loader.js.map +1 -1
- package/dist/remote/server-entry.d.ts.map +1 -1
- package/dist/remote/server-entry.js +3 -2
- package/dist/remote/server-entry.js.map +1 -1
- package/dist/remote/session-source.d.ts.map +1 -1
- package/dist/remote/session-source.js +8 -4
- package/dist/remote/session-source.js.map +1 -1
- package/dist/share/session-share.d.ts.map +1 -1
- package/dist/share/session-share.js +14 -2
- package/dist/share/session-share.js.map +1 -1
- package/dist/testing/plugin-testkit.d.ts.map +1 -1
- package/dist/testing/plugin-testkit.js +4 -3
- package/dist/testing/plugin-testkit.js.map +1 -1
- package/dist/testing/runtime-delivery-queue.d.ts.map +1 -1
- package/dist/testing/runtime-delivery-queue.js +2 -1
- package/dist/testing/runtime-delivery-queue.js.map +1 -1
- package/dist/testing/session-plugin-testkit.d.ts.map +1 -1
- package/dist/testing/session-plugin-testkit.js +10 -7
- package/dist/testing/session-plugin-testkit.js.map +1 -1
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js +2 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +7 -6
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js +3 -2
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +9 -8
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +23 -13
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +5 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/keybindings.md +3 -0
- package/docs/quickstart.md +1 -1
- package/docs/settings.md +1 -0
- package/docs/terminal-setup.md +2 -3
- package/docs/usage.md +6 -5
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/with-deps/plugin.json +1 -1
- package/package.json +1 -1
- package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-service.js","sourceRoot":"","sources":["../../src/durable/durable-service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Durable service MVP (7.4b) — in-memory persistence for session, operation,\n * and artifact records with a single-writer lease, crash recovery, and a\n * readiness gate.\n *\n * Scope: this is the durable *contract* slice. Storage is an in-memory Map;\n * `exportState`/`importState` are the snapshot restart boundary, and a\n * {@link DurableStoreBackend} is the log restart boundary: when one is passed\n * to {@link createDurableService}, every committed record is appended to the\n * backend log (write-ahead) and the log is replayed at construction to\n * restore state. Without a backend the service stays purely in-memory — the\n * original MVP behavior. {@link createFileDurableStoreBackend} is the JSONL\n * append-only file backend (ledger.ts pattern). Rules frozen here:\n * - Writes require the writer lease: `persist*` with any writerId other than\n * the current holder fails with `not_writer` — before the first claim,\n * while another writer holds the lease, and after a crash (until\n * `recoverWriter` takes it over).\n * - A writer recorded in an imported snapshot belonged to the process that\n * produced the snapshot and cannot be alive in this one: import enters a\n * crash-pending state where the lease stays held by the dead writer, reads\n * still work, and only `recoverWriter` can take the lease over. Readiness\n * stays `false` until it does.\n * - File writes through {@link createFileDurableStoreBackend} are\n * cross-process mutually exclusive: every persist serializes through a\n * `.lock` sibling file (same protocol as the memory ledger — exclusive\n * create, poll, stale-lock stealing, token-guarded release; wall-clock\n * timeout and staleness configurable, defaults 5 s / 60 s). The lock\n * guarantees concurrent appends do not interleave.\n * - Store-level writer lease (D-067 phase 2 S2): backends may expose an\n * optional {@link DurableStoreLeaseV1} — a TTL-based, cross-process\n * mutually-exclusive lease over the store. The file backend implements it\n * with a `.lease` sibling file (write heartbeat on every persist); the\n * service's claim/recover/release then resolve against the store, so a\n * second process observes a live foreign writer (`held`) and a crashed\n * writer's lease becomes recoverable once its TTL lapses. Without a\n * backend lease the writer lease stays process-local memory (unchanged).\n */\nimport {\n\tcloseSync,\n\tfsyncSync,\n\tmkdirSync,\n\topenSync,\n\treadFileSync,\n\tstatSync,\n\tunlinkSync,\n\twriteFileSync,\n\twriteSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { sleepSync } from \"../utils/sync-sleep.ts\";\n\n// D-075 S4 third batch: the pure contract types moved to @agent-forge/plugin-sdk\n// (`durable.ts` is the plugin-facing authority); this module re-exports them so\n// the host's historical import paths and public export face keep resolving.\n// The implementation below (writer lease, file backend, store lease) stays here.\nexport type {\n\tDurableArtifactRecordV1,\n\tDurableOperationRecordV1,\n\tDurableReadinessV1,\n\tDurableReplayDiagnosticsV1,\n\tDurableServiceV1,\n\tDurableSessionRecordV1,\n\tDurableSnapshotV1,\n\tDurableWriterClaimV1,\n\tDurableWriterRecoveryV1,\n} from \"@agent-forge/plugin-sdk\";\n\nimport type {\n\tDurableArtifactRecordV1,\n\tDurableOperationRecordV1,\n\tDurableReplayDiagnosticsV1,\n\tDurableServiceV1,\n\tDurableSessionRecordV1,\n} from \"@agent-forge/plugin-sdk\";\n\nexport type DurableServiceErrorCodeV1 = \"not_writer\";\n\nexport class DurableServiceErrorV1 extends Error {\n\treadonly code: DurableServiceErrorCodeV1;\n\n\tconstructor(code: DurableServiceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"DurableServiceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Store backend (durable 落盘): JSONL append-only log contract\n// ---------------------------------------------------------------------------\n\n/** One committed record as carried in a {@link DurableStoreBackend} log. */\nexport type DurableStoreOperationV1 =\n\t| { readonly kind: \"session\"; readonly record: DurableSessionRecordV1 }\n\t| { readonly kind: \"operation\"; readonly record: DurableOperationRecordV1 }\n\t| { readonly kind: \"artifact\"; readonly record: DurableArtifactRecordV1 };\n/** Result of {@link DurableStoreBackend.load}: replayable operations plus skip diagnostics. */\nexport interface DurableStoreLoadResultV1 {\n\t/** Valid operations in log order — replay these into a fresh service. */\n\treadonly operations: readonly DurableStoreOperationV1[];\n\t/** Malformed lines (invalid JSON or invalid records) skipped during load. */\n\treadonly corruptedLines: number;\n\t/** True when the file existed but could not be read (permissions, IO error). */\n\treadonly unreadable: boolean;\n}\n\n/**\n * Durable log backend for {@link createDurableService}. The write path\n * appends every committed record; the read path `load()`s the log at\n * construction and replays it into the fresh in-memory maps (last write per\n * id wins, matching live persist semantics). The default\n * {@link FileDurableStoreBackend} never throws on load — corruption is\n * skipped and counted — and the append path runs under a cross-process\n * `.lock` file mutex and fsyncs, so hard crashes cannot lose the most recent\n * appends and concurrent processes cannot interleave lines (a torn trailing\n * line is still skipped by the loader's corruption tolerance). The lock\n * covers file writes only: the writer lease stays process-local memory.\n */\nexport interface DurableStoreBackend {\n\t/** Appends committed operations to the durable log, in order. */\n\tpersist(operations: readonly DurableStoreOperationV1[]): void;\n\t/**\n\t * Reads the whole log and returns the replayable operations plus skip\n\t * diagnostics. A missing log is an empty backend, not an error; malformed\n\t * lines are skipped and counted — load NEVER throws.\n\t */\n\tload(): DurableStoreLoadResultV1;\n\t/** Releases backend resources. Idempotent; a no-op for the file backend. */\n\tclose(): void;\n\t/**\n\t * Optional store-level writer lease (D-067 phase 2 S2). When present, the\n\t * service resolves its claim/recover/release against it, giving\n\t * cross-process lease mutual exclusion and crash recovery by TTL; when\n\t * absent, the writer lease stays process-local memory.\n\t */\n\treadonly lease?: DurableStoreLeaseV1;\n}\n\n/** Result of {@link DurableStoreLeaseV1.claim}. */\nexport type DurableStoreLeaseClaimV1 =\n\t| { readonly status: \"claimed\" }\n\t| { readonly status: \"held\"; readonly by: string };\n\n/** Result of {@link DurableStoreLeaseV1.recover}. */\nexport type DurableStoreLeaseRecoverV1 =\n\t| { readonly status: \"recovered\"; readonly previousWriter?: string }\n\t| { readonly status: \"held\" };\n\n/**\n * Store-level writer lease: a TTL-based mutual-exclusion token over the whole\n * store, visible across processes. `renew` is the heartbeat — the holder\n * extends its TTL on every persist — and doubles as the liveness check: a\n * writer whose lease expired (or was recovered by another process) fails its\n * next renew with `not_writer`, so stale writes fail closed. All methods may\n * throw `DurableServiceErrorV1` with code `not_writer`.\n */\nexport interface DurableStoreLeaseV1 {\n\t/** Takes the lease; fails while a live foreign holder exists. Re-claim by the live holder refreshes it. */\n\tclaim(writerId: string): DurableStoreLeaseClaimV1;\n\t/** Releases the lease when held by `writerId`; free/expired leases release idempotently; a foreign holder throws. */\n\trelease(writerId: string): { readonly status: \"released\" };\n\t/** Takes over the lease of a holder whose TTL lapsed (dead process); a live foreign holder is reported as `held`. */\n\trecover(writerId: string): DurableStoreLeaseRecoverV1;\n\t/** Heartbeat: extends the holder's TTL; throws `not_writer` when the lease was lost or expired. */\n\trenew(writerId: string): void;\n}\n\n/** The standard durable log path: `<agentDir>/durable/<sessionId>.jsonl`. */\nexport function durableLogPath(agentDir: string, sessionId: string): string {\n\treturn join(agentDir, \"durable\", `${sessionId}.jsonl`);\n}\n\nfunction assertNonEmptyString(value: unknown, label: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0) throw new Error(`${label} must be a non-empty string`);\n}\n\n/**\n * Writes every byte of `data` to the fd, looping over partial `writeSync`\n * results (a short write would silently break the fsync durability promise:\n * the caller fsyncs and closes only after the full payload is handed to the\n * OS). Same pattern as the memory ledger's write path, implemented here with\n * plain node:fs primitives so the file backend needs no ledger dependency.\n */\nconst writeAllSync = (fd: number, data: string): void => {\n\tconst buffer = Buffer.from(data, \"utf8\");\n\tlet written = 0;\n\twhile (written < buffer.length) {\n\t\twritten += writeSync(fd, buffer, written, buffer.length - written);\n\t}\n};\n\n// ---------------------------------------------------------------------------\n// Cross-process persist lock (ledger.ts lock protocol, no ledger import —\n// the two implementations must stay behaviorally identical)\n// ---------------------------------------------------------------------------\n\n/** Suffix of the persistence lock sibling file (`<logPath>.lock`). */\nconst LOCK_FILE_SUFFIX = \".lock\";\n/** Suffix of the store-level writer lease sibling file (`<logPath>.lease`). */\nconst LEASE_FILE_SUFFIX = \".lease\";\n/**\n * Wall-clock wait between lock acquisition attempts. Kept as a per-file\n * constant even though the memory ledger currently uses the same 25 ms value:\n * the two lock protocols stay independent.\n */\nconst LOCK_POLL_INTERVAL_MS = 25;\n/** Default ceiling on waiting for a competing writer's lock. */\nconst DEFAULT_LOCK_TIMEOUT_MS = 5000;\n/**\n * Default age at which a lock counts as abandoned (its writer crashed while\n * holding it). Deliberately far above any live hold time (milliseconds of a\n * bounded append) and above the wait timeout, so a waiter fails loudly at the\n * timeout instead of stealing a lock that might still be held.\n */\nconst DEFAULT_STALE_LOCK_MS = 60_000;\n/**\n * Default writer-lease TTL. The holder renews on every persist (heartbeat);\n * an idle-but-alive process that never persists loses the lease after this\n * window and must `recoverWriter` before writing again. Deliberately far\n * above any test-relevant hold so production never sees surprise expiries\n * within a single persist burst; tests pass small values explicitly.\n */\nconst DEFAULT_LEASE_TTL_MS = 30_000;\n\n/**\n * Takes the cross-process persist lock shared by every durable store file\n * write: exclusive create (`wx`) is the mutex; an existing lock is polled\n * until released, stolen once its mtime exceeds `staleLockMs` (crashed\n * writer), or turned into a thrown error at the wait deadline. The lock file\n * carries a per-acquisition token so a stale-steal victim releasing late can\n * never delete the thief's fresh lock. Same protocol as the memory ledger's\n * append lock (now the memory plugin package's ledger, plugins/memory), reimplemented here to avoid module\n * coupling; the wall-clock lock is a real-time mechanism, deliberately not\n * driven by any injected deterministic `now`.\n */\nfunction acquirePersistLock(lockPath: string, lockTimeoutMs: number, staleLockMs: number): string {\n\tconst deadline = Date.now() + lockTimeoutMs;\n\tfor (;;) {\n\t\tmkdirSync(dirname(lockPath), { recursive: true });\n\t\tconst token = `${process.pid}:${Date.now()}`;\n\t\ttry {\n\t\t\tconst fd = openSync(lockPath, \"wx\");\n\t\t\ttry {\n\t\t\t\twriteFileSync(fd, token);\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t\treturn token;\n\t\t} catch (error) {\n\t\t\t// POSIX maps a lost create race to EEXIST; Windows/libuv maps the\n\t\t\t// same concurrent-create sharing violation to EPERM. Both mean the\n\t\t\t// lock file existed when we tried to create it — contend (poll /\n\t\t\t// stale-steal below). For EPERM the existence check re-stats: a\n\t\t\t// lock still there is contention, while ENOENT means the holder\n\t\t\t// released and deleted it between the failed open and this stat\n\t\t\t// (or Windows briefly left a delete-pending name that has now\n\t\t\t// gone) — the same vanished-lock window the EEXIST path tolerates,\n\t\t\t// so retry too. A stat error other than ENOENT means the EPERM was\n\t\t\t// a genuine permission failure and propagates, and the vanish path\n\t\t\t// still rethrows the original EPERM at the wait deadline: a\n\t\t\t// persistent EPERM with no lock file ever appearing is a genuine\n\t\t\t// permission failure, not a held lock.\n\t\t\tconst code = (error as NodeJS.ErrnoException).code;\n\t\t\tif (code === \"EPERM\") {\n\t\t\t\tlet vanished = false;\n\t\t\t\ttry {\n\t\t\t\t\tstatSync(lockPath);\n\t\t\t\t} catch (statError) {\n\t\t\t\t\tif ((statError as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t\t\t\t\tvanished = true;\n\t\t\t\t}\n\t\t\t\tif (vanished) {\n\t\t\t\t\tif (Date.now() >= deadline) throw error;\n\t\t\t\t\tsleepSync(LOCK_POLL_INTERVAL_MS);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (code !== \"EEXIST\") {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlet stale = false;\n\t\t\ttry {\n\t\t\t\tstale = Date.now() - statSync(lockPath).mtimeMs > staleLockMs;\n\t\t\t} catch {\n\t\t\t\t// The holder released the lock between the failed open and the\n\t\t\t\t// stat — retry the exclusive create immediately.\n\t\t\t}\n\t\t\tif (stale) {\n\t\t\t\t// A crashed writer left the lock behind: steal it. A competing\n\t\t\t\t// waiter may steal first — the next exclusive create resolves that.\n\t\t\t\ttry {\n\t\t\t\t\tunlinkSync(lockPath);\n\t\t\t\t} catch {\n\t\t\t\t\t// Already stolen — retry.\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (Date.now() >= deadline) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`durable store persist lock timeout after ${lockTimeoutMs} ms: ${lockPath} is held by another writer`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tsleepSync(LOCK_POLL_INTERVAL_MS);\n\t\t}\n\t}\n}\n\n/** Releases the persist lock, but only if our own token still owns it. */\nfunction releasePersistLock(lockPath: string, token: string): void {\n\ttry {\n\t\tif (readFileSync(lockPath, \"utf8\") === token) unlinkSync(lockPath);\n\t} catch {\n\t\t// The lock is already gone (or unreadable) — nothing to release.\n\t}\n}\n\n/**\n * Creates a JSONL append-only file backend at `path`\n * (ledger.ts pattern: one committed record per line, trailing newline so a\n * crash-truncated tail stays well-formed for the loader). Every persist\n * serializes against other processes through a `<path>.lock` sibling using\n * the memory ledger's lock protocol (exclusive create + 25 ms poll + mtime\n * stale-lock stealing + token-guarded release): `lockTimeoutMs` bounds the\n * wall-clock wait (default 5 s) and `staleLockMs` the abandoned-lock age\n * (default 60 s) — both exist so tests can exercise the timeout and steal\n * paths quickly. The lock makes concurrent appends non-interleaving.\n *\n * The backend also exposes the store-level writer lease (`<path>.lease`\n * sibling, D-067 phase 2 S2): a `{ writerId, expiresAt }` JSON file guarded\n * by the same lock protocol, with a TTL the holder renews on every persist\n * (`leaseTtlMs`, default 30 s — small values exist for tests). A crashed\n * writer's lease becomes recoverable once its TTL lapses; a live foreign\n * holder makes `claim`/`recover` report `held` and the holder's next `renew`\n * (i.e. its next persist) fail closed with `not_writer`.\n */\nexport function createFileDurableStoreBackend(options: {\n\treadonly path: string;\n\t/** Wall-clock ceiling on waiting for a competing writer's lock; default 5 s. */\n\treadonly lockTimeoutMs?: number;\n\t/** Age at which a lock counts as abandoned and is stolen; default 60 s. */\n\treadonly staleLockMs?: number;\n\t/** Writer-lease TTL; the holder renews on every persist. Default 30 s. */\n\treadonly leaseTtlMs?: number;\n}): DurableStoreBackend {\n\tassertNonEmptyString(options.path, \"Durable store path\");\n\tif (options.lockTimeoutMs !== undefined && (!Number.isFinite(options.lockTimeoutMs) || options.lockTimeoutMs <= 0)) {\n\t\tthrow new Error(\"Durable store lockTimeoutMs must be a positive number\");\n\t}\n\tif (options.staleLockMs !== undefined && (!Number.isFinite(options.staleLockMs) || options.staleLockMs <= 0)) {\n\t\tthrow new Error(\"Durable store staleLockMs must be a positive number\");\n\t}\n\tif (options.leaseTtlMs !== undefined && (!Number.isFinite(options.leaseTtlMs) || options.leaseTtlMs <= 0)) {\n\t\tthrow new Error(\"Durable store leaseTtlMs must be a positive number\");\n\t}\n\tconst path = options.path;\n\tconst lockTimeoutMs = options.lockTimeoutMs ?? DEFAULT_LOCK_TIMEOUT_MS;\n\tconst staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS;\n\tconst leaseTtlMs = options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS;\n\tconst lockPath = `${path}${LOCK_FILE_SUFFIX}`;\n\tconst leasePath = `${path}${LEASE_FILE_SUFFIX}`;\n\n\t/** Reads the lease file; missing, unreadable, or malformed content = no lease. */\n\tconst readLease = (): { readonly writerId: string; readonly expiresAt: number } | undefined => {\n\t\ttry {\n\t\t\tconst value: unknown = JSON.parse(readFileSync(leasePath, \"utf8\"));\n\t\t\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\t\t\tconst writerId = (value as { writerId?: unknown }).writerId;\n\t\t\tconst expiresAt = (value as { expiresAt?: unknown }).expiresAt;\n\t\t\tif (typeof writerId !== \"string\" || writerId.length === 0) return undefined;\n\t\t\tif (typeof expiresAt !== \"number\" || !Number.isFinite(expiresAt)) return undefined;\n\t\t\treturn { writerId, expiresAt };\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t};\n\n\t/**\n\t * Overwrites the lease file (caller holds the persist lock). Deliberately\n\t * NOT fsynced: the lease is a liveness token, not data — the worst case of\n\t * a torn post-crash write is a free lease, which the recover path handles.\n\t */\n\tconst writeLease = (writerId: string, expiresAt: number): void => {\n\t\tconst fd = openSync(leasePath, \"w\");\n\t\ttry {\n\t\t\twriteAllSync(fd, JSON.stringify({ writerId, expiresAt }));\n\t\t} finally {\n\t\t\tcloseSync(fd);\n\t\t}\n\t};\n\n\t/** True when `current` names a different writer whose TTL has not lapsed. */\n\tconst liveForeign = (\n\t\tcurrent: { readonly writerId: string; readonly expiresAt: number },\n\t\twriterId: string,\n\t): boolean => current.writerId !== writerId && Date.now() <= current.expiresAt;\n\n\tconst lease: DurableStoreLeaseV1 = {\n\t\tclaim(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current !== undefined && liveForeign(current, writerId))\n\t\t\t\t\treturn { status: \"held\", by: current.writerId };\n\t\t\t\twriteLease(writerId, Date.now() + leaseTtlMs);\n\t\t\t\treturn { status: \"claimed\" };\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\trelease(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current === undefined || current.writerId === writerId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tunlinkSync(leasePath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Already gone (or vanished between the read and the unlink).\n\t\t\t\t\t}\n\t\t\t\t\treturn { status: \"released\" };\n\t\t\t\t}\n\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\"not_writer\",\n\t\t\t\t\t`Writer ${writerId} does not hold the store lease (held by ${current.writerId})`,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\trecover(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current !== undefined && liveForeign(current, writerId)) return { status: \"held\" };\n\t\t\t\tconst previousWriter =\n\t\t\t\t\tcurrent !== undefined && current.writerId !== writerId ? current.writerId : undefined;\n\t\t\t\twriteLease(writerId, Date.now() + leaseTtlMs);\n\t\t\t\treturn previousWriter === undefined ? { status: \"recovered\" } : { status: \"recovered\", previousWriter };\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\trenew(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current === undefined || current.writerId !== writerId || Date.now() > current.expiresAt) {\n\t\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\t\"not_writer\",\n\t\t\t\t\t\t`Writer ${writerId} lost the store lease (expired or recovered by another writer)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\twriteLease(writerId, Date.now() + leaseTtlMs);\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t};\n\n\treturn {\n\t\tpersist(operations) {\n\t\t\tif (operations.length === 0) return;\n\t\t\tconst lines = operations.map((operation) => `${JSON.stringify(storeOperationEnvelope(operation))}\\n`);\n\t\t\t// Competing writers — including another server process — serialize\n\t\t\t// through the `.lock` sibling before the fsynced append, so lines from\n\t\t\t// concurrent processes never interleave (ledger.ts lock protocol).\n\t\t\t// Lock acquisition creates the parent directory, as in the ledger.\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\t// Append is fsynced before close: once persist returns, a hard\n\t\t\t\t// crash cannot lose the appended lines (open → write → fsync →\n\t\t\t\t// close, the same durability pattern as the memory ledger). A\n\t\t\t\t// failure inside the lock releases it and propagates; no\n\t\t\t\t// in-memory state of the service is touched (write-ahead).\n\t\t\t\tconst fd = openSync(path, \"a\");\n\t\t\t\ttry {\n\t\t\t\t\twriteAllSync(fd, lines.join(\"\"));\n\t\t\t\t\tfsyncSync(fd);\n\t\t\t\t} finally {\n\t\t\t\t\tcloseSync(fd);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\tload() {\n\t\t\tlet raw: string;\n\t\t\ttry {\n\t\t\t\traw = readFileSync(path, \"utf8\");\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\t\t\treturn { operations: [], corruptedLines: 0, unreadable: false };\n\t\t\t\t}\n\t\t\t\treturn { operations: [], corruptedLines: 0, unreadable: true };\n\t\t\t}\n\t\t\tconst operations: DurableStoreOperationV1[] = [];\n\t\t\tlet corruptedLines = 0;\n\t\t\tfor (const line of raw.split(\"\\n\")) {\n\t\t\t\tif (line.trim() === \"\") continue;\n\t\t\t\tconst operation = parseStoreOperationLine(line);\n\t\t\t\tif (operation === undefined) {\n\t\t\t\t\tcorruptedLines += 1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\toperations.push(operation);\n\t\t\t}\n\t\t\treturn { operations, corruptedLines, unreadable: false };\n\t\t},\n\t\tclose() {\n\t\t\t// Files are opened per append; nothing persistent to release. The\n\t\t\t// hook exists for backends that hold resources (handles, sockets).\n\t\t},\n\t\tlease,\n\t};\n}\n\n/** Flat one-line envelope: the kind discriminator plus the record fields. */\nfunction storeOperationEnvelope(operation: DurableStoreOperationV1): Record<string, unknown> {\n\treturn { kind: operation.kind, ...operation.record };\n}\n\n/** Parses one log line; undefined when it is malformed (skipped and counted). */\nfunction parseStoreOperationLine(line: string): DurableStoreOperationV1 | undefined {\n\ttry {\n\t\tconst value: unknown = JSON.parse(line);\n\t\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\t\tconst record = value as Record<string, unknown>;\n\t\tswitch (record.kind) {\n\t\t\tcase \"session\": {\n\t\t\t\tconst base = importRecordBase(record, \"sessionId\", \"Durable store session record\");\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"session\",\n\t\t\t\t\trecord: { sessionId: base.id, data: base.data, persistedAt: base.persistedAt },\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"operation\": {\n\t\t\t\tconst base = importRecordBase(record, \"operationId\", \"Durable store operation record\");\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"operation\",\n\t\t\t\t\trecord: {\n\t\t\t\t\t\toperationId: base.id,\n\t\t\t\t\t\tsessionId: importOwningSessionId(record, \"Durable store operation record\"),\n\t\t\t\t\t\tdata: base.data,\n\t\t\t\t\t\tpersistedAt: base.persistedAt,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"artifact\": {\n\t\t\t\tconst base = importRecordBase(record, \"artifactId\", \"Durable store artifact record\");\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"artifact\",\n\t\t\t\t\trecord: {\n\t\t\t\t\t\tartifactId: base.id,\n\t\t\t\t\t\tsessionId: importOwningSessionId(record, \"Durable store artifact record\"),\n\t\t\t\t\t\tdata: base.data,\n\t\t\t\t\t\tpersistedAt: base.persistedAt,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn undefined;\n\t\t}\n\t} catch {\n\t\t// Corruption tolerance: a malformed line is skipped and counted — a\n\t\t// damaged log must never fail the startup replay.\n\t\treturn undefined;\n\t}\n}\n\nexport interface DurableServiceOptionsV1 {\n\t/** Deterministic clock for `persistedAt`/`exportedAt`; defaults to `Date.now`. */\n\treadonly now?: () => number;\n\t/**\n\t * Optional durable log backend. Without it the service stays purely\n\t * in-memory (backward-compatible MVP behavior); with it every committed\n\t * record is appended to the backend log before the in-memory maps update\n\t * (write-ahead: an append failure leaves memory untouched) and the log is\n\t * replayed at construction to restore state.\n\t */\n\treadonly backend?: DurableStoreBackend;\n}\n\nfunction assertObject(value: unknown, label: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${label} must be an object`);\n\t}\n}\n\ninterface ImportedRecordV1 {\n\treadonly id: string;\n\treadonly data: unknown;\n\treadonly persistedAt: number;\n}\n\nfunction importRecordBase(\n\tvalue: Record<string, unknown>,\n\tidField: \"sessionId\" | \"operationId\" | \"artifactId\",\n\tlabel: string,\n): ImportedRecordV1 {\n\tconst id = value[idField];\n\tif (typeof id !== \"string\" || id.length === 0) throw new Error(`${label} ${idField} must be a non-empty string`);\n\tconst persistedAt = value.persistedAt;\n\tif (typeof persistedAt !== \"number\" || !Number.isFinite(persistedAt)) {\n\t\tthrow new Error(`${label} persistedAt must be a finite number`);\n\t}\n\t// Legacy (pre-单机收敛) log lines and snapshots may carry a `tenantId` key\n\t// from the removed multi-tenant machinery; it is tolerated as an ignored\n\t// extra key (D-068 增补 1), so it is simply never read here.\n\treturn { id, data: value.data, persistedAt };\n}\n\nfunction importOwningSessionId(value: Record<string, unknown>, label: string): string {\n\tconst sessionId = value.sessionId;\n\tif (typeof sessionId !== \"string\" || sessionId.length === 0) {\n\t\tthrow new Error(`${label} sessionId must be a non-empty string`);\n\t}\n\treturn sessionId;\n}\n\nexport function createDurableService(options: DurableServiceOptionsV1 = {}): DurableServiceV1 {\n\tconst now = options.now ?? (() => Date.now());\n\tconst sessions = new Map<string, DurableSessionRecordV1>();\n\tconst operations = new Map<string, DurableOperationRecordV1>();\n\tconst artifacts = new Map<string, DurableArtifactRecordV1>();\n\n\t/** Current lease holder; `null` when unclaimed or crash-pending. */\n\tlet holder: string | null = null;\n\t/** Writer found dead in a restored snapshot; blocks claims and writes until recovered. */\n\tlet crashPending: string | null = null;\n\n\t// Startup replay (durable 落盘): with a backend, the log is the source of\n\t// truth for records — replay restores the maps with last-write-wins, the\n\t// same semantics as live persists. With a backend lease (D-067 phase 2\n\t// S2) the writer lease resolves against the store (cross-process mutual\n\t// exclusion, TTL crash recovery); without one it stays process-local.\n\tconst backend = options.backend;\n\tconst backendLease = backend?.lease;\n\tlet replay: DurableReplayDiagnosticsV1 = { corruptedLines: 0, unreadable: false };\n\tif (backend) {\n\t\tconst loaded = backend.load();\n\t\tfor (const operation of loaded.operations) {\n\t\t\tswitch (operation.kind) {\n\t\t\t\tcase \"session\":\n\t\t\t\t\tsessions.set(operation.record.sessionId, operation.record);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"operation\":\n\t\t\t\t\toperations.set(operation.record.operationId, operation.record);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"artifact\":\n\t\t\t\t\tartifacts.set(operation.record.artifactId, operation.record);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treplay = { corruptedLines: loaded.corruptedLines, unreadable: loaded.unreadable };\n\t}\n\n\t/** Write-ahead log append; an append failure leaves the maps untouched. */\n\tconst logOperation = (operation: DurableStoreOperationV1): void => {\n\t\tif (backend) backend.persist([operation]);\n\t};\n\n\tfunction requireWriter(writerId: string): void {\n\t\tif (holder !== writerId) {\n\t\t\tthrow new DurableServiceErrorV1(\"not_writer\", `Writer ${writerId} does not hold the writer lease`);\n\t\t}\n\t\t// Store-level heartbeat + liveness check (D-067 phase 2 S2): another\n\t\t// process recovering our expired lease fail-closes this write instead\n\t\t// of letting a stale writer interleave records.\n\t\tbackendLease?.renew(writerId);\n\t}\n\n\treturn {\n\t\tpersistSession(input) {\n\t\t\trequireWriter(input.writerId);\n\t\t\tconst record: DurableSessionRecordV1 = {\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tdata: input.data,\n\t\t\t\tpersistedAt: now(),\n\t\t\t};\n\t\t\tlogOperation({ kind: \"session\", record });\n\t\t\tsessions.set(input.sessionId, record);\n\t\t\treturn record;\n\t\t},\n\t\tloadSession(input) {\n\t\t\treturn sessions.get(input.sessionId);\n\t\t},\n\t\tpersistOperation(input) {\n\t\t\trequireWriter(input.writerId);\n\t\t\tconst record: DurableOperationRecordV1 = {\n\t\t\t\toperationId: input.operationId,\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tdata: input.data,\n\t\t\t\tpersistedAt: now(),\n\t\t\t};\n\t\t\tlogOperation({ kind: \"operation\", record });\n\t\t\toperations.set(input.operationId, record);\n\t\t\treturn record;\n\t\t},\n\t\tloadOperation(input) {\n\t\t\treturn operations.get(input.operationId);\n\t\t},\n\t\tpersistArtifact(input) {\n\t\t\trequireWriter(input.writerId);\n\t\t\tconst record: DurableArtifactRecordV1 = {\n\t\t\t\tartifactId: input.artifactId,\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tdata: input.data,\n\t\t\t\tpersistedAt: now(),\n\t\t\t};\n\t\t\tlogOperation({ kind: \"artifact\", record });\n\t\t\tartifacts.set(input.artifactId, record);\n\t\t\treturn record;\n\t\t},\n\t\tloadArtifact(input) {\n\t\t\treturn artifacts.get(input.artifactId);\n\t\t},\n\t\tlistSessions() {\n\t\t\treturn (\n\t\t\t\t[...sessions.values()]\n\t\t\t\t\t// v8 ignore next -- sessionId 是 Map 键恒唯一,相等比较路径不可达\n\t\t\t\t\t.sort((a, b) => (a.sessionId < b.sessionId ? -1 : a.sessionId > b.sessionId ? 1 : 0))\n\t\t\t);\n\t\t},\n\t\tclaimWriter(writerId) {\n\t\t\tif (crashPending !== null) return { status: \"held\", by: crashPending };\n\t\t\tif (backendLease === undefined) {\n\t\t\t\tif (holder !== null && holder !== writerId) return { status: \"held\", by: holder };\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"claimed\" };\n\t\t\t}\n\t\t\tconst result = backendLease.claim(writerId);\n\t\t\tif (result.status === \"claimed\") {\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"claimed\" };\n\t\t\t}\n\t\t\treturn { status: \"held\", by: result.by };\n\t\t},\n\t\treleaseWriter(writerId) {\n\t\t\tif (crashPending !== null) {\n\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\"not_writer\",\n\t\t\t\t\t`Writer ${writerId} cannot release a crashed lease; recover it instead`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (backendLease === undefined) {\n\t\t\t\tif (holder !== null && holder !== writerId) {\n\t\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\t\"not_writer\",\n\t\t\t\t\t\t`Writer ${writerId} does not hold the writer lease (held by ${holder})`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tholder = null;\n\t\t\t\treturn { status: \"released\" };\n\t\t\t}\n\t\t\tconst result = backendLease.release(writerId);\n\t\t\tholder = null;\n\t\t\treturn result;\n\t\t},\n\t\trecoverWriter(writerId) {\n\t\t\tif (crashPending !== null) {\n\t\t\t\tconst previousWriter = crashPending;\n\t\t\t\tcrashPending = null;\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"recovered\", previousWriter };\n\t\t\t}\n\t\t\tif (backendLease === undefined) {\n\t\t\t\tif (holder !== null && holder !== writerId) return { status: \"held\" };\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"recovered\" };\n\t\t\t}\n\t\t\tconst result = backendLease.recover(writerId);\n\t\t\tif (result.status === \"recovered\") {\n\t\t\t\tholder = writerId;\n\t\t\t\treturn result.previousWriter === undefined\n\t\t\t\t\t? { status: \"recovered\" }\n\t\t\t\t\t: { status: \"recovered\", previousWriter: result.previousWriter };\n\t\t\t}\n\t\t\treturn { status: \"held\" };\n\t\t},\n\t\treadiness() {\n\t\t\tif (crashPending !== null) {\n\t\t\t\treturn { ready: false, reason: `writer crash is pending recovery: ${crashPending}` };\n\t\t\t}\n\t\t\tif (holder === null) {\n\t\t\t\treturn { ready: false, reason: \"no writer has claimed the lease\" };\n\t\t\t}\n\t\t\treturn { ready: true };\n\t\t},\n\t\texportState() {\n\t\t\treturn {\n\t\t\t\tversion: 1 as const,\n\t\t\t\texportedAt: now(),\n\t\t\t\tsessions: [...sessions.values()],\n\t\t\t\toperations: [...operations.values()],\n\t\t\t\tartifacts: [...artifacts.values()],\n\t\t\t\twriter: { holder, crashPending },\n\t\t\t};\n\t\t},\n\t\timportState(snapshot) {\n\t\t\tassertObject(snapshot, \"Durable snapshot\");\n\t\t\tif (snapshot.version !== 1) {\n\t\t\t\tthrow new Error(`Unsupported durable snapshot version: ${String(snapshot.version)}`);\n\t\t\t}\n\t\t\tfor (const field of [\"sessions\", \"operations\", \"artifacts\"] as const) {\n\t\t\t\tif (!Array.isArray(snapshot[field])) throw new Error(`Durable snapshot ${field} must be an array`);\n\t\t\t}\n\t\t\tconst writer = snapshot.writer;\n\t\t\tassertObject(writer, \"Durable snapshot writer\");\n\t\t\tconst snapshotHolder = writer.holder;\n\t\t\tconst snapshotCrashPending = writer.crashPending;\n\t\t\tif (snapshotHolder !== null && typeof snapshotHolder !== \"string\") {\n\t\t\t\tthrow new Error(\"Durable snapshot writer holder must be a string or null\");\n\t\t\t}\n\t\t\tif (snapshotCrashPending !== null && typeof snapshotCrashPending !== \"string\") {\n\t\t\t\tthrow new Error(\"Durable snapshot writer crashPending must be a string or null\");\n\t\t\t}\n\n\t\t\tconst importedSessions = new Map<string, DurableSessionRecordV1>();\n\t\t\tfor (const raw of snapshot.sessions as unknown[]) {\n\t\t\t\tassertObject(raw, \"Durable snapshot session\");\n\t\t\t\tconst record = importRecordBase(raw, \"sessionId\", \"Durable snapshot session\");\n\t\t\t\timportedSessions.set(record.id, {\n\t\t\t\t\tsessionId: record.id,\n\t\t\t\t\tdata: record.data,\n\t\t\t\t\tpersistedAt: record.persistedAt,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst importedOperations = new Map<string, DurableOperationRecordV1>();\n\t\t\tfor (const raw of snapshot.operations as unknown[]) {\n\t\t\t\tassertObject(raw, \"Durable snapshot operation\");\n\t\t\t\tconst record = importRecordBase(raw, \"operationId\", \"Durable snapshot operation\");\n\t\t\t\timportedOperations.set(record.id, {\n\t\t\t\t\toperationId: record.id,\n\t\t\t\t\tsessionId: importOwningSessionId(raw, \"Durable snapshot operation\"),\n\t\t\t\t\tdata: record.data,\n\t\t\t\t\tpersistedAt: record.persistedAt,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst importedArtifacts = new Map<string, DurableArtifactRecordV1>();\n\t\t\tfor (const raw of snapshot.artifacts as unknown[]) {\n\t\t\t\tassertObject(raw, \"Durable snapshot artifact\");\n\t\t\t\tconst record = importRecordBase(raw, \"artifactId\", \"Durable snapshot artifact\");\n\t\t\t\timportedArtifacts.set(record.id, {\n\t\t\t\t\tartifactId: record.id,\n\t\t\t\t\tsessionId: importOwningSessionId(raw, \"Durable snapshot artifact\"),\n\t\t\t\t\tdata: record.data,\n\t\t\t\t\tpersistedAt: record.persistedAt,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsessions.clear();\n\t\t\tfor (const [id, record] of importedSessions) sessions.set(id, record);\n\t\t\toperations.clear();\n\t\t\tfor (const [id, record] of importedOperations) operations.set(id, record);\n\t\t\tartifacts.clear();\n\t\t\tfor (const [id, record] of importedArtifacts) artifacts.set(id, record);\n\n\t\t\t// A writer recorded in the snapshot belonged to the process that\n\t\t\t// produced it; it cannot be alive in this one, so its lease needs\n\t\t\t// recovery before anyone may write again.\n\t\t\tholder = null;\n\t\t\tcrashPending = snapshotHolder ?? snapshotCrashPending;\n\t\t},\n\t\treplayDiagnostics() {\n\t\t\treturn replay;\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"durable-service.js","sourceRoot":"","sources":["../../src/durable/durable-service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Durable service MVP (7.4b) — in-memory persistence for session, operation,\n * and artifact records with a single-writer lease, crash recovery, and a\n * readiness gate.\n *\n * Scope: this is the durable *contract* slice. Storage is an in-memory Map;\n * `exportState`/`importState` are the snapshot restart boundary, and a\n * {@link DurableStoreBackend} is the log restart boundary: when one is passed\n * to {@link createDurableService}, every committed record is appended to the\n * backend log (write-ahead) and the log is replayed at construction to\n * restore state. Without a backend the service stays purely in-memory — the\n * original MVP behavior. {@link createFileDurableStoreBackend} is the JSONL\n * append-only file backend (ledger.ts pattern). Rules frozen here:\n * - Writes require the writer lease: `persist*` with any writerId other than\n * the current holder fails with `not_writer` — before the first claim,\n * while another writer holds the lease, and after a crash (until\n * `recoverWriter` takes it over).\n * - A writer recorded in an imported snapshot belonged to the process that\n * produced the snapshot and cannot be alive in this one: import enters a\n * crash-pending state where the lease stays held by the dead writer, reads\n * still work, and only `recoverWriter` can take the lease over. Readiness\n * stays `false` until it does.\n * - File writes through {@link createFileDurableStoreBackend} are\n * cross-process mutually exclusive: every persist serializes through a\n * `.lock` sibling file (same protocol as the memory ledger — exclusive\n * create, poll, stale-lock stealing, token-guarded release; wall-clock\n * timeout and staleness configurable, defaults 5 s / 60 s). The lock\n * guarantees concurrent appends do not interleave.\n * - Store-level writer lease (D-067 phase 2 S2): backends may expose an\n * optional {@link DurableStoreLeaseV1} — a TTL-based, cross-process\n * mutually-exclusive lease over the store. The file backend implements it\n * with a `.lease` sibling file (write heartbeat on every persist); the\n * service's claim/recover/release then resolve against the store, so a\n * second process observes a live foreign writer (`held`) and a crashed\n * writer's lease becomes recoverable once its TTL lapses. Without a\n * backend lease the writer lease stays process-local memory (unchanged).\n */\nimport {\n\tcloseSync,\n\tfsyncSync,\n\tmkdirSync,\n\topenSync,\n\treadFileSync,\n\tstatSync,\n\tunlinkSync,\n\twriteFileSync,\n\twriteSync,\n} from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { sleepSync } from \"../utils/sync-sleep.ts\";\n\n// D-075 S4 third batch: the pure contract types moved to @agent-forge/plugin-sdk\n// (`durable.ts` is the plugin-facing authority); this module re-exports them so\n// the host's historical import paths and public export face keep resolving.\n// The implementation below (writer lease, file backend, store lease) stays here.\nexport type {\n\tDurableArtifactRecordV1,\n\tDurableOperationRecordV1,\n\tDurableReadinessV1,\n\tDurableReplayDiagnosticsV1,\n\tDurableServiceV1,\n\tDurableSessionRecordV1,\n\tDurableSnapshotV1,\n\tDurableWriterClaimV1,\n\tDurableWriterRecoveryV1,\n} from \"@agent-forge/plugin-sdk\";\n\nimport type {\n\tDurableArtifactRecordV1,\n\tDurableOperationRecordV1,\n\tDurableReplayDiagnosticsV1,\n\tDurableServiceV1,\n\tDurableSessionRecordV1,\n} from \"@agent-forge/plugin-sdk\";\nimport { t } from \"../core/i18n/index.ts\";\n\nexport type DurableServiceErrorCodeV1 = \"not_writer\";\n\nexport class DurableServiceErrorV1 extends Error {\n\treadonly code: DurableServiceErrorCodeV1;\n\n\tconstructor(code: DurableServiceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"DurableServiceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Store backend (durable 落盘): JSONL append-only log contract\n// ---------------------------------------------------------------------------\n\n/** One committed record as carried in a {@link DurableStoreBackend} log. */\nexport type DurableStoreOperationV1 =\n\t| { readonly kind: \"session\"; readonly record: DurableSessionRecordV1 }\n\t| { readonly kind: \"operation\"; readonly record: DurableOperationRecordV1 }\n\t| { readonly kind: \"artifact\"; readonly record: DurableArtifactRecordV1 };\n/** Result of {@link DurableStoreBackend.load}: replayable operations plus skip diagnostics. */\nexport interface DurableStoreLoadResultV1 {\n\t/** Valid operations in log order — replay these into a fresh service. */\n\treadonly operations: readonly DurableStoreOperationV1[];\n\t/** Malformed lines (invalid JSON or invalid records) skipped during load. */\n\treadonly corruptedLines: number;\n\t/** True when the file existed but could not be read (permissions, IO error). */\n\treadonly unreadable: boolean;\n}\n\n/**\n * Durable log backend for {@link createDurableService}. The write path\n * appends every committed record; the read path `load()`s the log at\n * construction and replays it into the fresh in-memory maps (last write per\n * id wins, matching live persist semantics). The default\n * {@link FileDurableStoreBackend} never throws on load — corruption is\n * skipped and counted — and the append path runs under a cross-process\n * `.lock` file mutex and fsyncs, so hard crashes cannot lose the most recent\n * appends and concurrent processes cannot interleave lines (a torn trailing\n * line is still skipped by the loader's corruption tolerance). The lock\n * covers file writes only: the writer lease stays process-local memory.\n */\nexport interface DurableStoreBackend {\n\t/** Appends committed operations to the durable log, in order. */\n\tpersist(operations: readonly DurableStoreOperationV1[]): void;\n\t/**\n\t * Reads the whole log and returns the replayable operations plus skip\n\t * diagnostics. A missing log is an empty backend, not an error; malformed\n\t * lines are skipped and counted — load NEVER throws.\n\t */\n\tload(): DurableStoreLoadResultV1;\n\t/** Releases backend resources. Idempotent; a no-op for the file backend. */\n\tclose(): void;\n\t/**\n\t * Optional store-level writer lease (D-067 phase 2 S2). When present, the\n\t * service resolves its claim/recover/release against it, giving\n\t * cross-process lease mutual exclusion and crash recovery by TTL; when\n\t * absent, the writer lease stays process-local memory.\n\t */\n\treadonly lease?: DurableStoreLeaseV1;\n}\n\n/** Result of {@link DurableStoreLeaseV1.claim}. */\nexport type DurableStoreLeaseClaimV1 =\n\t| { readonly status: \"claimed\" }\n\t| { readonly status: \"held\"; readonly by: string };\n\n/** Result of {@link DurableStoreLeaseV1.recover}. */\nexport type DurableStoreLeaseRecoverV1 =\n\t| { readonly status: \"recovered\"; readonly previousWriter?: string }\n\t| { readonly status: \"held\" };\n\n/**\n * Store-level writer lease: a TTL-based mutual-exclusion token over the whole\n * store, visible across processes. `renew` is the heartbeat — the holder\n * extends its TTL on every persist — and doubles as the liveness check: a\n * writer whose lease expired (or was recovered by another process) fails its\n * next renew with `not_writer`, so stale writes fail closed. All methods may\n * throw `DurableServiceErrorV1` with code `not_writer`.\n */\nexport interface DurableStoreLeaseV1 {\n\t/** Takes the lease; fails while a live foreign holder exists. Re-claim by the live holder refreshes it. */\n\tclaim(writerId: string): DurableStoreLeaseClaimV1;\n\t/** Releases the lease when held by `writerId`; free/expired leases release idempotently; a foreign holder throws. */\n\trelease(writerId: string): { readonly status: \"released\" };\n\t/** Takes over the lease of a holder whose TTL lapsed (dead process); a live foreign holder is reported as `held`. */\n\trecover(writerId: string): DurableStoreLeaseRecoverV1;\n\t/** Heartbeat: extends the holder's TTL; throws `not_writer` when the lease was lost or expired. */\n\trenew(writerId: string): void;\n}\n\n/** The standard durable log path: `<agentDir>/durable/<sessionId>.jsonl`. */\nexport function durableLogPath(agentDir: string, sessionId: string): string {\n\treturn join(agentDir, \"durable\", `${sessionId}.jsonl`);\n}\n\nfunction assertNonEmptyString(value: unknown, label: string): asserts value is string {\n\tif (typeof value !== \"string\" || value.trim().length === 0)\n\t\tthrow new Error(t(\"{label} must be a non-empty string\", { label }));\n}\n\n/**\n * Writes every byte of `data` to the fd, looping over partial `writeSync`\n * results (a short write would silently break the fsync durability promise:\n * the caller fsyncs and closes only after the full payload is handed to the\n * OS). Same pattern as the memory ledger's write path, implemented here with\n * plain node:fs primitives so the file backend needs no ledger dependency.\n */\nconst writeAllSync = (fd: number, data: string): void => {\n\tconst buffer = Buffer.from(data, \"utf8\");\n\tlet written = 0;\n\twhile (written < buffer.length) {\n\t\twritten += writeSync(fd, buffer, written, buffer.length - written);\n\t}\n};\n\n// ---------------------------------------------------------------------------\n// Cross-process persist lock (ledger.ts lock protocol, no ledger import —\n// the two implementations must stay behaviorally identical)\n// ---------------------------------------------------------------------------\n\n/** Suffix of the persistence lock sibling file (`<logPath>.lock`). */\nconst LOCK_FILE_SUFFIX = \".lock\";\n/** Suffix of the store-level writer lease sibling file (`<logPath>.lease`). */\nconst LEASE_FILE_SUFFIX = \".lease\";\n/**\n * Wall-clock wait between lock acquisition attempts. Kept as a per-file\n * constant even though the memory ledger currently uses the same 25 ms value:\n * the two lock protocols stay independent.\n */\nconst LOCK_POLL_INTERVAL_MS = 25;\n/** Default ceiling on waiting for a competing writer's lock. */\nconst DEFAULT_LOCK_TIMEOUT_MS = 5000;\n/**\n * Default age at which a lock counts as abandoned (its writer crashed while\n * holding it). Deliberately far above any live hold time (milliseconds of a\n * bounded append) and above the wait timeout, so a waiter fails loudly at the\n * timeout instead of stealing a lock that might still be held.\n */\nconst DEFAULT_STALE_LOCK_MS = 60_000;\n/**\n * Default writer-lease TTL. The holder renews on every persist (heartbeat);\n * an idle-but-alive process that never persists loses the lease after this\n * window and must `recoverWriter` before writing again. Deliberately far\n * above any test-relevant hold so production never sees surprise expiries\n * within a single persist burst; tests pass small values explicitly.\n */\nconst DEFAULT_LEASE_TTL_MS = 30_000;\n\n/**\n * Takes the cross-process persist lock shared by every durable store file\n * write: exclusive create (`wx`) is the mutex; an existing lock is polled\n * until released, stolen once its mtime exceeds `staleLockMs` (crashed\n * writer), or turned into a thrown error at the wait deadline. The lock file\n * carries a per-acquisition token so a stale-steal victim releasing late can\n * never delete the thief's fresh lock. Same protocol as the memory ledger's\n * append lock (now the memory plugin package's ledger, plugins/memory), reimplemented here to avoid module\n * coupling; the wall-clock lock is a real-time mechanism, deliberately not\n * driven by any injected deterministic `now`.\n */\nfunction acquirePersistLock(lockPath: string, lockTimeoutMs: number, staleLockMs: number): string {\n\tconst deadline = Date.now() + lockTimeoutMs;\n\tfor (;;) {\n\t\tmkdirSync(dirname(lockPath), { recursive: true });\n\t\tconst token = `${process.pid}:${Date.now()}`;\n\t\ttry {\n\t\t\tconst fd = openSync(lockPath, \"wx\");\n\t\t\ttry {\n\t\t\t\twriteFileSync(fd, token);\n\t\t\t} finally {\n\t\t\t\tcloseSync(fd);\n\t\t\t}\n\t\t\treturn token;\n\t\t} catch (error) {\n\t\t\t// POSIX maps a lost create race to EEXIST; Windows/libuv maps the\n\t\t\t// same concurrent-create sharing violation to EPERM. Both mean the\n\t\t\t// lock file existed when we tried to create it — contend (poll /\n\t\t\t// stale-steal below). For EPERM the existence check re-stats: a\n\t\t\t// lock still there is contention, while ENOENT means the holder\n\t\t\t// released and deleted it between the failed open and this stat\n\t\t\t// (or Windows briefly left a delete-pending name that has now\n\t\t\t// gone) — the same vanished-lock window the EEXIST path tolerates,\n\t\t\t// so retry too. A stat error other than ENOENT means the EPERM was\n\t\t\t// a genuine permission failure and propagates, and the vanish path\n\t\t\t// still rethrows the original EPERM at the wait deadline: a\n\t\t\t// persistent EPERM with no lock file ever appearing is a genuine\n\t\t\t// permission failure, not a held lock.\n\t\t\tconst code = (error as NodeJS.ErrnoException).code;\n\t\t\tif (code === \"EPERM\") {\n\t\t\t\tlet vanished = false;\n\t\t\t\ttry {\n\t\t\t\t\tstatSync(lockPath);\n\t\t\t\t} catch (statError) {\n\t\t\t\t\tif ((statError as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n\t\t\t\t\tvanished = true;\n\t\t\t\t}\n\t\t\t\tif (vanished) {\n\t\t\t\t\tif (Date.now() >= deadline) throw error;\n\t\t\t\t\tsleepSync(LOCK_POLL_INTERVAL_MS);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t} else if (code !== \"EEXIST\") {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tlet stale = false;\n\t\t\ttry {\n\t\t\t\tstale = Date.now() - statSync(lockPath).mtimeMs > staleLockMs;\n\t\t\t} catch {\n\t\t\t\t// The holder released the lock between the failed open and the\n\t\t\t\t// stat — retry the exclusive create immediately.\n\t\t\t}\n\t\t\tif (stale) {\n\t\t\t\t// A crashed writer left the lock behind: steal it. A competing\n\t\t\t\t// waiter may steal first — the next exclusive create resolves that.\n\t\t\t\ttry {\n\t\t\t\t\tunlinkSync(lockPath);\n\t\t\t\t} catch {\n\t\t\t\t\t// Already stolen — retry.\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (Date.now() >= deadline) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tt(\"durable store persist lock timeout after {timeoutMs} ms: {lockPath} is held by another writer\", {\n\t\t\t\t\t\ttimeoutMs: lockTimeoutMs,\n\t\t\t\t\t\tlockPath,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tsleepSync(LOCK_POLL_INTERVAL_MS);\n\t\t}\n\t}\n}\n\n/** Releases the persist lock, but only if our own token still owns it. */\nfunction releasePersistLock(lockPath: string, token: string): void {\n\ttry {\n\t\tif (readFileSync(lockPath, \"utf8\") === token) unlinkSync(lockPath);\n\t} catch {\n\t\t// The lock is already gone (or unreadable) — nothing to release.\n\t}\n}\n\n/**\n * Creates a JSONL append-only file backend at `path`\n * (ledger.ts pattern: one committed record per line, trailing newline so a\n * crash-truncated tail stays well-formed for the loader). Every persist\n * serializes against other processes through a `<path>.lock` sibling using\n * the memory ledger's lock protocol (exclusive create + 25 ms poll + mtime\n * stale-lock stealing + token-guarded release): `lockTimeoutMs` bounds the\n * wall-clock wait (default 5 s) and `staleLockMs` the abandoned-lock age\n * (default 60 s) — both exist so tests can exercise the timeout and steal\n * paths quickly. The lock makes concurrent appends non-interleaving.\n *\n * The backend also exposes the store-level writer lease (`<path>.lease`\n * sibling, D-067 phase 2 S2): a `{ writerId, expiresAt }` JSON file guarded\n * by the same lock protocol, with a TTL the holder renews on every persist\n * (`leaseTtlMs`, default 30 s — small values exist for tests). A crashed\n * writer's lease becomes recoverable once its TTL lapses; a live foreign\n * holder makes `claim`/`recover` report `held` and the holder's next `renew`\n * (i.e. its next persist) fail closed with `not_writer`.\n */\nexport function createFileDurableStoreBackend(options: {\n\treadonly path: string;\n\t/** Wall-clock ceiling on waiting for a competing writer's lock; default 5 s. */\n\treadonly lockTimeoutMs?: number;\n\t/** Age at which a lock counts as abandoned and is stolen; default 60 s. */\n\treadonly staleLockMs?: number;\n\t/** Writer-lease TTL; the holder renews on every persist. Default 30 s. */\n\treadonly leaseTtlMs?: number;\n}): DurableStoreBackend {\n\tassertNonEmptyString(options.path, \"Durable store path\");\n\tif (options.lockTimeoutMs !== undefined && (!Number.isFinite(options.lockTimeoutMs) || options.lockTimeoutMs <= 0)) {\n\t\tthrow new Error(t(\"Durable store lockTimeoutMs must be a positive number\"));\n\t}\n\tif (options.staleLockMs !== undefined && (!Number.isFinite(options.staleLockMs) || options.staleLockMs <= 0)) {\n\t\tthrow new Error(t(\"Durable store staleLockMs must be a positive number\"));\n\t}\n\tif (options.leaseTtlMs !== undefined && (!Number.isFinite(options.leaseTtlMs) || options.leaseTtlMs <= 0)) {\n\t\tthrow new Error(t(\"Durable store leaseTtlMs must be a positive number\"));\n\t}\n\tconst path = options.path;\n\tconst lockTimeoutMs = options.lockTimeoutMs ?? DEFAULT_LOCK_TIMEOUT_MS;\n\tconst staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS;\n\tconst leaseTtlMs = options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS;\n\tconst lockPath = `${path}${LOCK_FILE_SUFFIX}`;\n\tconst leasePath = `${path}${LEASE_FILE_SUFFIX}`;\n\n\t/** Reads the lease file; missing, unreadable, or malformed content = no lease. */\n\tconst readLease = (): { readonly writerId: string; readonly expiresAt: number } | undefined => {\n\t\ttry {\n\t\t\tconst value: unknown = JSON.parse(readFileSync(leasePath, \"utf8\"));\n\t\t\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\t\t\tconst writerId = (value as { writerId?: unknown }).writerId;\n\t\t\tconst expiresAt = (value as { expiresAt?: unknown }).expiresAt;\n\t\t\tif (typeof writerId !== \"string\" || writerId.length === 0) return undefined;\n\t\t\tif (typeof expiresAt !== \"number\" || !Number.isFinite(expiresAt)) return undefined;\n\t\t\treturn { writerId, expiresAt };\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t};\n\n\t/**\n\t * Overwrites the lease file (caller holds the persist lock). Deliberately\n\t * NOT fsynced: the lease is a liveness token, not data — the worst case of\n\t * a torn post-crash write is a free lease, which the recover path handles.\n\t */\n\tconst writeLease = (writerId: string, expiresAt: number): void => {\n\t\tconst fd = openSync(leasePath, \"w\");\n\t\ttry {\n\t\t\twriteAllSync(fd, JSON.stringify({ writerId, expiresAt }));\n\t\t} finally {\n\t\t\tcloseSync(fd);\n\t\t}\n\t};\n\n\t/** True when `current` names a different writer whose TTL has not lapsed. */\n\tconst liveForeign = (\n\t\tcurrent: { readonly writerId: string; readonly expiresAt: number },\n\t\twriterId: string,\n\t): boolean => current.writerId !== writerId && Date.now() <= current.expiresAt;\n\n\tconst lease: DurableStoreLeaseV1 = {\n\t\tclaim(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current !== undefined && liveForeign(current, writerId))\n\t\t\t\t\treturn { status: \"held\", by: current.writerId };\n\t\t\t\twriteLease(writerId, Date.now() + leaseTtlMs);\n\t\t\t\treturn { status: \"claimed\" };\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\trelease(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current === undefined || current.writerId === writerId) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tunlinkSync(leasePath);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Already gone (or vanished between the read and the unlink).\n\t\t\t\t\t}\n\t\t\t\t\treturn { status: \"released\" };\n\t\t\t\t}\n\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\"not_writer\",\n\t\t\t\t\tt(\"Writer {writerId} does not hold the store lease (held by {holder})\", {\n\t\t\t\t\t\twriterId,\n\t\t\t\t\t\tholder: current.writerId,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\trecover(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current !== undefined && liveForeign(current, writerId)) return { status: \"held\" };\n\t\t\t\tconst previousWriter =\n\t\t\t\t\tcurrent !== undefined && current.writerId !== writerId ? current.writerId : undefined;\n\t\t\t\twriteLease(writerId, Date.now() + leaseTtlMs);\n\t\t\t\treturn previousWriter === undefined ? { status: \"recovered\" } : { status: \"recovered\", previousWriter };\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\trenew(writerId) {\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\tconst current = readLease();\n\t\t\t\tif (current === undefined || current.writerId !== writerId || Date.now() > current.expiresAt) {\n\t\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\t\"not_writer\",\n\t\t\t\t\t\tt(\"Writer {writerId} lost the store lease (expired or recovered by another writer)\", { writerId }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\twriteLease(writerId, Date.now() + leaseTtlMs);\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t};\n\n\treturn {\n\t\tpersist(operations) {\n\t\t\tif (operations.length === 0) return;\n\t\t\tconst lines = operations.map((operation) => `${JSON.stringify(storeOperationEnvelope(operation))}\\n`);\n\t\t\t// Competing writers — including another server process — serialize\n\t\t\t// through the `.lock` sibling before the fsynced append, so lines from\n\t\t\t// concurrent processes never interleave (ledger.ts lock protocol).\n\t\t\t// Lock acquisition creates the parent directory, as in the ledger.\n\t\t\tconst token = acquirePersistLock(lockPath, lockTimeoutMs, staleLockMs);\n\t\t\ttry {\n\t\t\t\t// Append is fsynced before close: once persist returns, a hard\n\t\t\t\t// crash cannot lose the appended lines (open → write → fsync →\n\t\t\t\t// close, the same durability pattern as the memory ledger). A\n\t\t\t\t// failure inside the lock releases it and propagates; no\n\t\t\t\t// in-memory state of the service is touched (write-ahead).\n\t\t\t\tconst fd = openSync(path, \"a\");\n\t\t\t\ttry {\n\t\t\t\t\twriteAllSync(fd, lines.join(\"\"));\n\t\t\t\t\tfsyncSync(fd);\n\t\t\t\t} finally {\n\t\t\t\t\tcloseSync(fd);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\treleasePersistLock(lockPath, token);\n\t\t\t}\n\t\t},\n\t\tload() {\n\t\t\tlet raw: string;\n\t\t\ttry {\n\t\t\t\traw = readFileSync(path, \"utf8\");\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\t\t\treturn { operations: [], corruptedLines: 0, unreadable: false };\n\t\t\t\t}\n\t\t\t\treturn { operations: [], corruptedLines: 0, unreadable: true };\n\t\t\t}\n\t\t\tconst operations: DurableStoreOperationV1[] = [];\n\t\t\tlet corruptedLines = 0;\n\t\t\tfor (const line of raw.split(\"\\n\")) {\n\t\t\t\tif (line.trim() === \"\") continue;\n\t\t\t\tconst operation = parseStoreOperationLine(line);\n\t\t\t\tif (operation === undefined) {\n\t\t\t\t\tcorruptedLines += 1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\toperations.push(operation);\n\t\t\t}\n\t\t\treturn { operations, corruptedLines, unreadable: false };\n\t\t},\n\t\tclose() {\n\t\t\t// Files are opened per append; nothing persistent to release. The\n\t\t\t// hook exists for backends that hold resources (handles, sockets).\n\t\t},\n\t\tlease,\n\t};\n}\n\n/** Flat one-line envelope: the kind discriminator plus the record fields. */\nfunction storeOperationEnvelope(operation: DurableStoreOperationV1): Record<string, unknown> {\n\treturn { kind: operation.kind, ...operation.record };\n}\n\n/** Parses one log line; undefined when it is malformed (skipped and counted). */\nfunction parseStoreOperationLine(line: string): DurableStoreOperationV1 | undefined {\n\ttry {\n\t\tconst value: unknown = JSON.parse(line);\n\t\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) return undefined;\n\t\tconst record = value as Record<string, unknown>;\n\t\tswitch (record.kind) {\n\t\t\tcase \"session\": {\n\t\t\t\tconst base = importRecordBase(record, \"sessionId\", \"Durable store session record\");\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"session\",\n\t\t\t\t\trecord: { sessionId: base.id, data: base.data, persistedAt: base.persistedAt },\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"operation\": {\n\t\t\t\tconst base = importRecordBase(record, \"operationId\", \"Durable store operation record\");\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"operation\",\n\t\t\t\t\trecord: {\n\t\t\t\t\t\toperationId: base.id,\n\t\t\t\t\t\tsessionId: importOwningSessionId(record, \"Durable store operation record\"),\n\t\t\t\t\t\tdata: base.data,\n\t\t\t\t\t\tpersistedAt: base.persistedAt,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"artifact\": {\n\t\t\t\tconst base = importRecordBase(record, \"artifactId\", \"Durable store artifact record\");\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"artifact\",\n\t\t\t\t\trecord: {\n\t\t\t\t\t\tartifactId: base.id,\n\t\t\t\t\t\tsessionId: importOwningSessionId(record, \"Durable store artifact record\"),\n\t\t\t\t\t\tdata: base.data,\n\t\t\t\t\t\tpersistedAt: base.persistedAt,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn undefined;\n\t\t}\n\t} catch {\n\t\t// Corruption tolerance: a malformed line is skipped and counted — a\n\t\t// damaged log must never fail the startup replay.\n\t\treturn undefined;\n\t}\n}\n\nexport interface DurableServiceOptionsV1 {\n\t/** Deterministic clock for `persistedAt`/`exportedAt`; defaults to `Date.now`. */\n\treadonly now?: () => number;\n\t/**\n\t * Optional durable log backend. Without it the service stays purely\n\t * in-memory (backward-compatible MVP behavior); with it every committed\n\t * record is appended to the backend log before the in-memory maps update\n\t * (write-ahead: an append failure leaves memory untouched) and the log is\n\t * replayed at construction to restore state.\n\t */\n\treadonly backend?: DurableStoreBackend;\n}\n\nfunction assertObject(value: unknown, label: string): asserts value is Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(t(\"{label} must be an object\", { label }));\n\t}\n}\n\ninterface ImportedRecordV1 {\n\treadonly id: string;\n\treadonly data: unknown;\n\treadonly persistedAt: number;\n}\n\nfunction importRecordBase(\n\tvalue: Record<string, unknown>,\n\tidField: \"sessionId\" | \"operationId\" | \"artifactId\",\n\tlabel: string,\n): ImportedRecordV1 {\n\tconst id = value[idField];\n\tif (typeof id !== \"string\" || id.length === 0)\n\t\tthrow new Error(t(\"{label} {idField} must be a non-empty string\", { label, idField }));\n\tconst persistedAt = value.persistedAt;\n\tif (typeof persistedAt !== \"number\" || !Number.isFinite(persistedAt)) {\n\t\tthrow new Error(t(\"{label} persistedAt must be a finite number\", { label }));\n\t}\n\t// Legacy (pre-单机收敛) log lines and snapshots may carry a `tenantId` key\n\t// from the removed multi-tenant machinery; it is tolerated as an ignored\n\t// extra key (D-068 增补 1), so it is simply never read here.\n\treturn { id, data: value.data, persistedAt };\n}\n\nfunction importOwningSessionId(value: Record<string, unknown>, label: string): string {\n\tconst sessionId = value.sessionId;\n\tif (typeof sessionId !== \"string\" || sessionId.length === 0) {\n\t\tthrow new Error(t(\"{label} sessionId must be a non-empty string\", { label }));\n\t}\n\treturn sessionId;\n}\n\nexport function createDurableService(options: DurableServiceOptionsV1 = {}): DurableServiceV1 {\n\tconst now = options.now ?? (() => Date.now());\n\tconst sessions = new Map<string, DurableSessionRecordV1>();\n\tconst operations = new Map<string, DurableOperationRecordV1>();\n\tconst artifacts = new Map<string, DurableArtifactRecordV1>();\n\n\t/** Current lease holder; `null` when unclaimed or crash-pending. */\n\tlet holder: string | null = null;\n\t/** Writer found dead in a restored snapshot; blocks claims and writes until recovered. */\n\tlet crashPending: string | null = null;\n\n\t// Startup replay (durable 落盘): with a backend, the log is the source of\n\t// truth for records — replay restores the maps with last-write-wins, the\n\t// same semantics as live persists. With a backend lease (D-067 phase 2\n\t// S2) the writer lease resolves against the store (cross-process mutual\n\t// exclusion, TTL crash recovery); without one it stays process-local.\n\tconst backend = options.backend;\n\tconst backendLease = backend?.lease;\n\tlet replay: DurableReplayDiagnosticsV1 = { corruptedLines: 0, unreadable: false };\n\tif (backend) {\n\t\tconst loaded = backend.load();\n\t\tfor (const operation of loaded.operations) {\n\t\t\tswitch (operation.kind) {\n\t\t\t\tcase \"session\":\n\t\t\t\t\tsessions.set(operation.record.sessionId, operation.record);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"operation\":\n\t\t\t\t\toperations.set(operation.record.operationId, operation.record);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"artifact\":\n\t\t\t\t\tartifacts.set(operation.record.artifactId, operation.record);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treplay = { corruptedLines: loaded.corruptedLines, unreadable: loaded.unreadable };\n\t}\n\n\t/** Write-ahead log append; an append failure leaves the maps untouched. */\n\tconst logOperation = (operation: DurableStoreOperationV1): void => {\n\t\tif (backend) backend.persist([operation]);\n\t};\n\n\tfunction requireWriter(writerId: string): void {\n\t\tif (holder !== writerId) {\n\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\"not_writer\",\n\t\t\t\tt(\"Writer {writerId} does not hold the writer lease\", { writerId }),\n\t\t\t);\n\t\t}\n\t\t// Store-level heartbeat + liveness check (D-067 phase 2 S2): another\n\t\t// process recovering our expired lease fail-closes this write instead\n\t\t// of letting a stale writer interleave records.\n\t\tbackendLease?.renew(writerId);\n\t}\n\n\treturn {\n\t\tpersistSession(input) {\n\t\t\trequireWriter(input.writerId);\n\t\t\tconst record: DurableSessionRecordV1 = {\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tdata: input.data,\n\t\t\t\tpersistedAt: now(),\n\t\t\t};\n\t\t\tlogOperation({ kind: \"session\", record });\n\t\t\tsessions.set(input.sessionId, record);\n\t\t\treturn record;\n\t\t},\n\t\tloadSession(input) {\n\t\t\treturn sessions.get(input.sessionId);\n\t\t},\n\t\tpersistOperation(input) {\n\t\t\trequireWriter(input.writerId);\n\t\t\tconst record: DurableOperationRecordV1 = {\n\t\t\t\toperationId: input.operationId,\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tdata: input.data,\n\t\t\t\tpersistedAt: now(),\n\t\t\t};\n\t\t\tlogOperation({ kind: \"operation\", record });\n\t\t\toperations.set(input.operationId, record);\n\t\t\treturn record;\n\t\t},\n\t\tloadOperation(input) {\n\t\t\treturn operations.get(input.operationId);\n\t\t},\n\t\tpersistArtifact(input) {\n\t\t\trequireWriter(input.writerId);\n\t\t\tconst record: DurableArtifactRecordV1 = {\n\t\t\t\tartifactId: input.artifactId,\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tdata: input.data,\n\t\t\t\tpersistedAt: now(),\n\t\t\t};\n\t\t\tlogOperation({ kind: \"artifact\", record });\n\t\t\tartifacts.set(input.artifactId, record);\n\t\t\treturn record;\n\t\t},\n\t\tloadArtifact(input) {\n\t\t\treturn artifacts.get(input.artifactId);\n\t\t},\n\t\tlistSessions() {\n\t\t\treturn (\n\t\t\t\t[...sessions.values()]\n\t\t\t\t\t// v8 ignore next -- sessionId 是 Map 键恒唯一,相等比较路径不可达\n\t\t\t\t\t.sort((a, b) => (a.sessionId < b.sessionId ? -1 : a.sessionId > b.sessionId ? 1 : 0))\n\t\t\t);\n\t\t},\n\t\tclaimWriter(writerId) {\n\t\t\tif (crashPending !== null) return { status: \"held\", by: crashPending };\n\t\t\tif (backendLease === undefined) {\n\t\t\t\tif (holder !== null && holder !== writerId) return { status: \"held\", by: holder };\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"claimed\" };\n\t\t\t}\n\t\t\tconst result = backendLease.claim(writerId);\n\t\t\tif (result.status === \"claimed\") {\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"claimed\" };\n\t\t\t}\n\t\t\treturn { status: \"held\", by: result.by };\n\t\t},\n\t\treleaseWriter(writerId) {\n\t\t\tif (crashPending !== null) {\n\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\"not_writer\",\n\t\t\t\t\tt(\"Writer {writerId} cannot release a crashed lease; recover it instead\", { writerId }),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (backendLease === undefined) {\n\t\t\t\tif (holder !== null && holder !== writerId) {\n\t\t\t\t\tthrow new DurableServiceErrorV1(\n\t\t\t\t\t\t\"not_writer\",\n\t\t\t\t\t\tt(\"Writer {writerId} does not hold the writer lease (held by {holder})\", { writerId, holder }),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tholder = null;\n\t\t\t\treturn { status: \"released\" };\n\t\t\t}\n\t\t\tconst result = backendLease.release(writerId);\n\t\t\tholder = null;\n\t\t\treturn result;\n\t\t},\n\t\trecoverWriter(writerId) {\n\t\t\tif (crashPending !== null) {\n\t\t\t\tconst previousWriter = crashPending;\n\t\t\t\tcrashPending = null;\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"recovered\", previousWriter };\n\t\t\t}\n\t\t\tif (backendLease === undefined) {\n\t\t\t\tif (holder !== null && holder !== writerId) return { status: \"held\" };\n\t\t\t\tholder = writerId;\n\t\t\t\treturn { status: \"recovered\" };\n\t\t\t}\n\t\t\tconst result = backendLease.recover(writerId);\n\t\t\tif (result.status === \"recovered\") {\n\t\t\t\tholder = writerId;\n\t\t\t\treturn result.previousWriter === undefined\n\t\t\t\t\t? { status: \"recovered\" }\n\t\t\t\t\t: { status: \"recovered\", previousWriter: result.previousWriter };\n\t\t\t}\n\t\t\treturn { status: \"held\" };\n\t\t},\n\t\treadiness() {\n\t\t\tif (crashPending !== null) {\n\t\t\t\treturn { ready: false, reason: `writer crash is pending recovery: ${crashPending}` };\n\t\t\t}\n\t\t\tif (holder === null) {\n\t\t\t\treturn { ready: false, reason: \"no writer has claimed the lease\" };\n\t\t\t}\n\t\t\treturn { ready: true };\n\t\t},\n\t\texportState() {\n\t\t\treturn {\n\t\t\t\tversion: 1 as const,\n\t\t\t\texportedAt: now(),\n\t\t\t\tsessions: [...sessions.values()],\n\t\t\t\toperations: [...operations.values()],\n\t\t\t\tartifacts: [...artifacts.values()],\n\t\t\t\twriter: { holder, crashPending },\n\t\t\t};\n\t\t},\n\t\timportState(snapshot) {\n\t\t\tassertObject(snapshot, \"Durable snapshot\");\n\t\t\tif (snapshot.version !== 1) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tt(\"Unsupported durable snapshot version: {version}\", { version: String(snapshot.version) }),\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const field of [\"sessions\", \"operations\", \"artifacts\"] as const) {\n\t\t\t\tif (!Array.isArray(snapshot[field]))\n\t\t\t\t\tthrow new Error(t(\"Durable snapshot {field} must be an array\", { field }));\n\t\t\t}\n\t\t\tconst writer = snapshot.writer;\n\t\t\tassertObject(writer, \"Durable snapshot writer\");\n\t\t\tconst snapshotHolder = writer.holder;\n\t\t\tconst snapshotCrashPending = writer.crashPending;\n\t\t\tif (snapshotHolder !== null && typeof snapshotHolder !== \"string\") {\n\t\t\t\tthrow new Error(t(\"Durable snapshot writer holder must be a string or null\"));\n\t\t\t}\n\t\t\tif (snapshotCrashPending !== null && typeof snapshotCrashPending !== \"string\") {\n\t\t\t\tthrow new Error(t(\"Durable snapshot writer crashPending must be a string or null\"));\n\t\t\t}\n\n\t\t\tconst importedSessions = new Map<string, DurableSessionRecordV1>();\n\t\t\tfor (const raw of snapshot.sessions as unknown[]) {\n\t\t\t\tassertObject(raw, \"Durable snapshot session\");\n\t\t\t\tconst record = importRecordBase(raw, \"sessionId\", \"Durable snapshot session\");\n\t\t\t\timportedSessions.set(record.id, {\n\t\t\t\t\tsessionId: record.id,\n\t\t\t\t\tdata: record.data,\n\t\t\t\t\tpersistedAt: record.persistedAt,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst importedOperations = new Map<string, DurableOperationRecordV1>();\n\t\t\tfor (const raw of snapshot.operations as unknown[]) {\n\t\t\t\tassertObject(raw, \"Durable snapshot operation\");\n\t\t\t\tconst record = importRecordBase(raw, \"operationId\", \"Durable snapshot operation\");\n\t\t\t\timportedOperations.set(record.id, {\n\t\t\t\t\toperationId: record.id,\n\t\t\t\t\tsessionId: importOwningSessionId(raw, \"Durable snapshot operation\"),\n\t\t\t\t\tdata: record.data,\n\t\t\t\t\tpersistedAt: record.persistedAt,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst importedArtifacts = new Map<string, DurableArtifactRecordV1>();\n\t\t\tfor (const raw of snapshot.artifacts as unknown[]) {\n\t\t\t\tassertObject(raw, \"Durable snapshot artifact\");\n\t\t\t\tconst record = importRecordBase(raw, \"artifactId\", \"Durable snapshot artifact\");\n\t\t\t\timportedArtifacts.set(record.id, {\n\t\t\t\t\tartifactId: record.id,\n\t\t\t\t\tsessionId: importOwningSessionId(raw, \"Durable snapshot artifact\"),\n\t\t\t\t\tdata: record.data,\n\t\t\t\t\tpersistedAt: record.persistedAt,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsessions.clear();\n\t\t\tfor (const [id, record] of importedSessions) sessions.set(id, record);\n\t\t\toperations.clear();\n\t\t\tfor (const [id, record] of importedOperations) operations.set(id, record);\n\t\t\tartifacts.clear();\n\t\t\tfor (const [id, record] of importedArtifacts) artifacts.set(id, record);\n\n\t\t\t// A writer recorded in the snapshot belonged to the process that\n\t\t\t// produced it; it cannot be alive in this one, so its lease needs\n\t\t\t// recovery before anyone may write again.\n\t\t\tholder = null;\n\t\t\tcrashPending = snapshotHolder ?? snapshotCrashPending;\n\t\t},\n\t\treplayDiagnostics() {\n\t\t\treturn replay;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint-commit.d.ts","sourceRoot":"","sources":["../../src/host/checkpoint-commit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"checkpoint-commit.d.ts","sourceRoot":"","sources":["../../src/host/checkpoint-commit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,MAAM,iBAAiB,GAC1B;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAAE;AAChE,uFAAuF;GACrF;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAC5B;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACpC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,MAAM,WAAW,2BAA2B;IAC3C,KAAK,CAAC,KAAK,EAAE;QACZ,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;KAC5B,GAAG,iBAAiB,CAAC;IACtB,WAAW,CAAC,KAAK,EAAE;QAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;KAC/D,GAAG,mBAAmB,CAAC;IACxB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,eAAe,GAAG,mBAAmB,CAAA;KAAE,CAAC;IACrG,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,qBAAqB,IAAI,SAAS,MAAM,EAAE,CAAC;CAC3C;AASD,wBAAgB,+BAA+B,CAC9C,OAAO,GAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/C,2BAA2B,CAsE7B","sourcesContent":["/**\n * Host checkpoint/commit (2A.1) — the revision-guarded, idempotent,\n * two-phase write primitive the execution loop uses to persist session\n * context.\n *\n * Phase 1 (`stage`): the writer declares an operation against an expected\n * revision. Stale expectations are rejected with the current revision.\n * Phase 2 (`commitStage`): the payload is applied exactly once through the\n * caller's apply callback ONLY if the revision still matches; the revision\n * advances strictly after a successful apply.\n *\n * No path ever leaves a half commit: stale → revision untouched; duplicate\n * operationId → the first committed result is returned verbatim (never\n * re-applied); write failure → staged entry dropped, revision untouched;\n * cancellation → the staged entry is cancelled and can never commit.\n * Everything is deterministic and replayable. Summary policies, auto\n * compaction, retry, and branch migration are later 2A slices.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface HostStagedWriteV1 {\n\treadonly token: string;\n\treadonly operationId: string;\n\treadonly expectedRevision: number;\n\treadonly currentRevision: number;\n}\n\nexport type HostStageResultV1 =\n\t| { readonly status: \"staged\"; readonly staged: HostStagedWriteV1 }\n\t| { readonly status: \"stale\"; readonly currentRevision: number }\n\t/** The operationId already committed; the first result is echoed, never re-applied. */\n\t| { readonly status: \"duplicate\"; readonly revision: number };\n\nexport type HostCommitOutcomeV1 =\n\t| { readonly status: \"committed\"; readonly revision: number }\n\t| { readonly status: \"stale\"; readonly currentRevision: number }\n\t| { readonly status: \"write_failed\"; readonly reason: string }\n\t| { readonly status: \"cancelled\" }\n\t| { readonly status: \"unknown_token\" }\n\t| { readonly status: \"duplicate\"; readonly revision: number };\n\nexport interface HostCheckpointCoordinatorV1 {\n\tstage(input: {\n\t\treadonly operationId: string;\n\t\treadonly expectedRevision: number;\n\t\treadonly payload: JsonValue;\n\t}): HostStageResultV1;\n\tcommitStage(input: {\n\t\treadonly token: string;\n\t\treadonly apply: (payload: JsonValue, revision: number) => void;\n\t}): HostCommitOutcomeV1;\n\tcancelStage(token: string): { readonly status: \"cancelled\" | \"unknown_token\" | \"already_committed\" };\n\treadonly currentRevision: number;\n\tcommittedOperationIds(): readonly string[];\n}\n\ninterface StagedEntry {\n\toperationId: string;\n\texpectedRevision: number;\n\tpayload: JsonValue;\n\tstate: \"staged\" | \"cancelled\";\n}\n\nexport function createHostCheckpointCoordinator(\n\toptions: { readonly startRevision?: number } = {},\n): HostCheckpointCoordinatorV1 {\n\tlet revision = options.startRevision ?? 0;\n\tconst staged = new Map<string, StagedEntry>();\n\tconst committed = new Map<string, number>();\n\tlet tokenSequence = 0;\n\n\treturn {\n\t\tget currentRevision() {\n\t\t\treturn revision;\n\t\t},\n\t\tstage(input) {\n\t\t\tif (typeof input.operationId !== \"string\" || input.operationId.trim().length === 0) {\n\t\t\t\tthrow new Error(t(\"Checkpoint operationId must be a non-empty string\"));\n\t\t\t}\n\t\t\tconst appliedRevision = committed.get(input.operationId);\n\t\t\tif (appliedRevision !== undefined) {\n\t\t\t\treturn { status: \"duplicate\", revision: appliedRevision };\n\t\t\t}\n\t\t\tif (input.expectedRevision !== revision) {\n\t\t\t\treturn { status: \"stale\", currentRevision: revision };\n\t\t\t}\n\t\t\ttokenSequence += 1;\n\t\t\tconst token = `ckpt-${tokenSequence}`;\n\t\t\tconst entry: StagedEntry = {\n\t\t\t\toperationId: input.operationId,\n\t\t\t\texpectedRevision: input.expectedRevision,\n\t\t\t\tpayload: input.payload,\n\t\t\t\tstate: \"staged\",\n\t\t\t};\n\t\t\tstaged.set(token, entry);\n\t\t\treturn {\n\t\t\t\tstatus: \"staged\",\n\t\t\t\tstaged: {\n\t\t\t\t\ttoken,\n\t\t\t\t\toperationId: input.operationId,\n\t\t\t\t\texpectedRevision: input.expectedRevision,\n\t\t\t\t\tcurrentRevision: revision,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tcommitStage({ token, apply }) {\n\t\t\tconst entry = staged.get(token);\n\t\t\tif (!entry) return { status: \"unknown_token\" };\n\t\t\tif (entry.state === \"cancelled\") return { status: \"cancelled\" };\n\t\t\tif (entry.expectedRevision !== revision) {\n\t\t\t\tstaged.delete(token);\n\t\t\t\treturn { status: \"stale\", currentRevision: revision };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tapply(entry.payload, revision + 1);\n\t\t\t} catch (error) {\n\t\t\t\tstaged.delete(token);\n\t\t\t\treturn { status: \"write_failed\", reason: error instanceof Error ? error.message : String(error) };\n\t\t\t}\n\t\t\trevision += 1;\n\t\t\tcommitted.set(entry.operationId, revision);\n\t\t\tstaged.delete(token);\n\t\t\treturn { status: \"committed\", revision };\n\t\t},\n\t\tcancelStage(token) {\n\t\t\tconst entry = staged.get(token);\n\t\t\tif (!entry) return { status: \"unknown_token\" };\n\t\t\tif (committed.has(entry.operationId)) return { status: \"already_committed\" };\n\t\t\tentry.state = \"cancelled\";\n\t\t\treturn { status: \"cancelled\" };\n\t\t},\n\t\tcommittedOperationIds() {\n\t\t\treturn Object.freeze([...committed.keys()].sort());\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t } from "../core/i18n/index.js";
|
|
1
2
|
export function createHostCheckpointCoordinator(options = {}) {
|
|
2
3
|
let revision = options.startRevision ?? 0;
|
|
3
4
|
const staged = new Map();
|
|
@@ -9,7 +10,7 @@ export function createHostCheckpointCoordinator(options = {}) {
|
|
|
9
10
|
},
|
|
10
11
|
stage(input) {
|
|
11
12
|
if (typeof input.operationId !== "string" || input.operationId.trim().length === 0) {
|
|
12
|
-
throw new Error("Checkpoint operationId must be a non-empty string");
|
|
13
|
+
throw new Error(t("Checkpoint operationId must be a non-empty string"));
|
|
13
14
|
}
|
|
14
15
|
const appliedRevision = committed.get(input.operationId);
|
|
15
16
|
if (appliedRevision !== undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint-commit.js","sourceRoot":"","sources":["../../src/host/checkpoint-commit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"checkpoint-commit.js","sourceRoot":"","sources":["../../src/host/checkpoint-commit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host checkpoint/commit (2A.1) — the revision-guarded, idempotent,\n * two-phase write primitive the execution loop uses to persist session\n * context.\n *\n * Phase 1 (`stage`): the writer declares an operation against an expected\n * revision. Stale expectations are rejected with the current revision.\n * Phase 2 (`commitStage`): the payload is applied exactly once through the\n * caller's apply callback ONLY if the revision still matches; the revision\n * advances strictly after a successful apply.\n *\n * No path ever leaves a half commit: stale → revision untouched; duplicate\n * operationId → the first committed result is returned verbatim (never\n * re-applied); write failure → staged entry dropped, revision untouched;\n * cancellation → the staged entry is cancelled and can never commit.\n * Everything is deterministic and replayable. Summary policies, auto\n * compaction, retry, and branch migration are later 2A slices.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface HostStagedWriteV1 {\n\treadonly token: string;\n\treadonly operationId: string;\n\treadonly expectedRevision: number;\n\treadonly currentRevision: number;\n}\n\nexport type HostStageResultV1 =\n\t| { readonly status: \"staged\"; readonly staged: HostStagedWriteV1 }\n\t| { readonly status: \"stale\"; readonly currentRevision: number }\n\t/** The operationId already committed; the first result is echoed, never re-applied. */\n\t| { readonly status: \"duplicate\"; readonly revision: number };\n\nexport type HostCommitOutcomeV1 =\n\t| { readonly status: \"committed\"; readonly revision: number }\n\t| { readonly status: \"stale\"; readonly currentRevision: number }\n\t| { readonly status: \"write_failed\"; readonly reason: string }\n\t| { readonly status: \"cancelled\" }\n\t| { readonly status: \"unknown_token\" }\n\t| { readonly status: \"duplicate\"; readonly revision: number };\n\nexport interface HostCheckpointCoordinatorV1 {\n\tstage(input: {\n\t\treadonly operationId: string;\n\t\treadonly expectedRevision: number;\n\t\treadonly payload: JsonValue;\n\t}): HostStageResultV1;\n\tcommitStage(input: {\n\t\treadonly token: string;\n\t\treadonly apply: (payload: JsonValue, revision: number) => void;\n\t}): HostCommitOutcomeV1;\n\tcancelStage(token: string): { readonly status: \"cancelled\" | \"unknown_token\" | \"already_committed\" };\n\treadonly currentRevision: number;\n\tcommittedOperationIds(): readonly string[];\n}\n\ninterface StagedEntry {\n\toperationId: string;\n\texpectedRevision: number;\n\tpayload: JsonValue;\n\tstate: \"staged\" | \"cancelled\";\n}\n\nexport function createHostCheckpointCoordinator(\n\toptions: { readonly startRevision?: number } = {},\n): HostCheckpointCoordinatorV1 {\n\tlet revision = options.startRevision ?? 0;\n\tconst staged = new Map<string, StagedEntry>();\n\tconst committed = new Map<string, number>();\n\tlet tokenSequence = 0;\n\n\treturn {\n\t\tget currentRevision() {\n\t\t\treturn revision;\n\t\t},\n\t\tstage(input) {\n\t\t\tif (typeof input.operationId !== \"string\" || input.operationId.trim().length === 0) {\n\t\t\t\tthrow new Error(t(\"Checkpoint operationId must be a non-empty string\"));\n\t\t\t}\n\t\t\tconst appliedRevision = committed.get(input.operationId);\n\t\t\tif (appliedRevision !== undefined) {\n\t\t\t\treturn { status: \"duplicate\", revision: appliedRevision };\n\t\t\t}\n\t\t\tif (input.expectedRevision !== revision) {\n\t\t\t\treturn { status: \"stale\", currentRevision: revision };\n\t\t\t}\n\t\t\ttokenSequence += 1;\n\t\t\tconst token = `ckpt-${tokenSequence}`;\n\t\t\tconst entry: StagedEntry = {\n\t\t\t\toperationId: input.operationId,\n\t\t\t\texpectedRevision: input.expectedRevision,\n\t\t\t\tpayload: input.payload,\n\t\t\t\tstate: \"staged\",\n\t\t\t};\n\t\t\tstaged.set(token, entry);\n\t\t\treturn {\n\t\t\t\tstatus: \"staged\",\n\t\t\t\tstaged: {\n\t\t\t\t\ttoken,\n\t\t\t\t\toperationId: input.operationId,\n\t\t\t\t\texpectedRevision: input.expectedRevision,\n\t\t\t\t\tcurrentRevision: revision,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tcommitStage({ token, apply }) {\n\t\t\tconst entry = staged.get(token);\n\t\t\tif (!entry) return { status: \"unknown_token\" };\n\t\t\tif (entry.state === \"cancelled\") return { status: \"cancelled\" };\n\t\t\tif (entry.expectedRevision !== revision) {\n\t\t\t\tstaged.delete(token);\n\t\t\t\treturn { status: \"stale\", currentRevision: revision };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tapply(entry.payload, revision + 1);\n\t\t\t} catch (error) {\n\t\t\t\tstaged.delete(token);\n\t\t\t\treturn { status: \"write_failed\", reason: error instanceof Error ? error.message : String(error) };\n\t\t\t}\n\t\t\trevision += 1;\n\t\t\tcommitted.set(entry.operationId, revision);\n\t\t\tstaged.delete(token);\n\t\t\treturn { status: \"committed\", revision };\n\t\t},\n\t\tcancelStage(token) {\n\t\t\tconst entry = staged.get(token);\n\t\t\tif (!entry) return { status: \"unknown_token\" };\n\t\t\tif (committed.has(entry.operationId)) return { status: \"already_committed\" };\n\t\t\tentry.state = \"cancelled\";\n\t\t\treturn { status: \"cancelled\" };\n\t\t},\n\t\tcommittedOperationIds() {\n\t\t\treturn Object.freeze([...committed.keys()].sort());\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manual-compaction.d.ts","sourceRoot":"","sources":["../../src/host/manual-compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"manual-compaction.d.ts","sourceRoot":"","sources":["../../src/host/manual-compaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAE1E,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,aAAa,CAAC;AAE7D,MAAM,MAAM,yBAAyB,GAClC;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAA;CAAE,GACxF;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9D;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IAC1C,4EAA4E;IAC5E,iBAAiB,CAAC,KAAK,EAAE;QACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,SAAS,CAAC;KACpC,GAAG,yBAAyB,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAC;CACxC;AAED,wBAAgB,8BAA8B,CAAC,OAAO,EAAE;IACvD,QAAQ,CAAC,WAAW,EAAE,2BAA2B,CAAC;CAClD,GAAG,0BAA0B,CA4D7B","sourcesContent":["/**\n * Manual compaction executor (2A.2) — the host primitive that lets a PLUGIN\n * decide when compaction happens and what the summary contains, while the\n * kernel side only provides the model/session/commit primitives (here: the\n * 2A.1 checkpoint coordinator).\n *\n * The executor owns no summarization policy: the requesting plugin supplies\n * the deterministic `summarize` callback. The executor sequences the\n * operation through the checkpoint coordinator (stage → summarize → commit),\n * so a stale revision, a failing summary, or a concurrent compaction can\n * never produce a half commit. Auto compaction, overflow recovery, retry,\n * and tree/branch migration are later 2A slices.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\nimport type { HostCheckpointCoordinatorV1 } from \"./checkpoint-commit.ts\";\n\nexport type ManualCompactionStateV1 = \"idle\" | \"in_progress\";\n\nexport type ManualCompactionOutcomeV1 =\n\t| { readonly status: \"completed\"; readonly revision: number; readonly summary: JsonValue }\n\t| { readonly status: \"stale\"; readonly currentRevision: number }\n\t| { readonly status: \"summary_failed\"; readonly reason: string }\n\t| { readonly status: \"busy\"; readonly currentOperationId: string };\n\nexport interface ManualCompactionExecutorV1 {\n\t/** Plugin-driven entry point: the plugin decides timing AND the summary. */\n\trequestCompaction(input: {\n\t\treadonly pluginId: string;\n\t\treadonly operationId: string;\n\t\treadonly summarize: () => JsonValue;\n\t}): ManualCompactionOutcomeV1;\n\treadonly state: ManualCompactionStateV1;\n}\n\nexport function createManualCompactionExecutor(options: {\n\treadonly coordinator: HostCheckpointCoordinatorV1;\n}): ManualCompactionExecutorV1 {\n\tconst coordinator = options.coordinator;\n\tlet state: ManualCompactionStateV1 = \"idle\";\n\tlet currentOperationId: string | undefined;\n\n\treturn {\n\t\tget state() {\n\t\t\treturn state;\n\t\t},\n\t\trequestCompaction(input) {\n\t\t\tif (state === \"in_progress\") {\n\t\t\t\t// v8 ignore next -- state 与 currentOperationId 同步赋值,busy 时必有 operationId\n\t\t\t\treturn { status: \"busy\", currentOperationId: currentOperationId ?? \"unknown\" };\n\t\t\t}\n\t\t\tif (input.pluginId.trim().length === 0) {\n\t\t\t\tthrow new Error(t(\"Compaction pluginId must be a non-empty string\"));\n\t\t\t}\n\t\t\tstate = \"in_progress\";\n\t\t\tcurrentOperationId = input.operationId;\n\t\t\ttry {\n\t\t\t\t// Stage against the current revision; a concurrent commit makes this stale.\n\t\t\t\tconst staged = coordinator.stage({\n\t\t\t\t\toperationId: input.operationId,\n\t\t\t\t\texpectedRevision: coordinator.currentRevision,\n\t\t\t\t\tpayload: null,\n\t\t\t\t});\n\t\t\t\tif (staged.status === \"stale\") {\n\t\t\t\t\treturn { status: \"stale\", currentRevision: staged.currentRevision };\n\t\t\t\t}\n\t\t\t\tif (staged.status === \"duplicate\") {\n\t\t\t\t\treturn { status: \"completed\", revision: staged.revision, summary: { duplicate: true } };\n\t\t\t\t}\n\t\t\t\t// Plugin-owned summarization; the executor knows nothing of the content.\n\t\t\t\tlet summary: JsonValue;\n\t\t\t\ttry {\n\t\t\t\t\tsummary = input.summarize();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcoordinator.cancelStage(staged.staged.token);\n\t\t\t\t\treturn { status: \"summary_failed\", reason: error instanceof Error ? error.message : String(error) };\n\t\t\t\t}\n\t\t\t\tconst outcome = coordinator.commitStage({\n\t\t\t\t\ttoken: staged.staged.token,\n\t\t\t\t\tapply: (payload, revision) => {\n\t\t\t\t\t\tvoid payload;\n\t\t\t\t\t\tvoid revision;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (outcome.status === \"stale\") {\n\t\t\t\t\treturn { status: \"stale\", currentRevision: outcome.currentRevision };\n\t\t\t\t}\n\t\t\t\tif (outcome.status === \"committed\") {\n\t\t\t\t\treturn { status: \"completed\", revision: outcome.revision, summary };\n\t\t\t\t}\n\t\t\t\treturn { status: \"summary_failed\", reason: `Unexpected checkpoint outcome: ${outcome.status}` };\n\t\t\t} finally {\n\t\t\t\tstate = \"idle\";\n\t\t\t\tcurrentOperationId = undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t } from "../core/i18n/index.js";
|
|
1
2
|
export function createManualCompactionExecutor(options) {
|
|
2
3
|
const coordinator = options.coordinator;
|
|
3
4
|
let state = "idle";
|
|
@@ -12,7 +13,7 @@ export function createManualCompactionExecutor(options) {
|
|
|
12
13
|
return { status: "busy", currentOperationId: currentOperationId ?? "unknown" };
|
|
13
14
|
}
|
|
14
15
|
if (input.pluginId.trim().length === 0) {
|
|
15
|
-
throw new Error("Compaction pluginId must be a non-empty string");
|
|
16
|
+
throw new Error(t("Compaction pluginId must be a non-empty string"));
|
|
16
17
|
}
|
|
17
18
|
state = "in_progress";
|
|
18
19
|
currentOperationId = input.operationId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manual-compaction.js","sourceRoot":"","sources":["../../src/host/manual-compaction.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manual-compaction.js","sourceRoot":"","sources":["../../src/host/manual-compaction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Manual compaction executor (2A.2) — the host primitive that lets a PLUGIN\n * decide when compaction happens and what the summary contains, while the\n * kernel side only provides the model/session/commit primitives (here: the\n * 2A.1 checkpoint coordinator).\n *\n * The executor owns no summarization policy: the requesting plugin supplies\n * the deterministic `summarize` callback. The executor sequences the\n * operation through the checkpoint coordinator (stage → summarize → commit),\n * so a stale revision, a failing summary, or a concurrent compaction can\n * never produce a half commit. Auto compaction, overflow recovery, retry,\n * and tree/branch migration are later 2A slices.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\nimport type { HostCheckpointCoordinatorV1 } from \"./checkpoint-commit.ts\";\n\nexport type ManualCompactionStateV1 = \"idle\" | \"in_progress\";\n\nexport type ManualCompactionOutcomeV1 =\n\t| { readonly status: \"completed\"; readonly revision: number; readonly summary: JsonValue }\n\t| { readonly status: \"stale\"; readonly currentRevision: number }\n\t| { readonly status: \"summary_failed\"; readonly reason: string }\n\t| { readonly status: \"busy\"; readonly currentOperationId: string };\n\nexport interface ManualCompactionExecutorV1 {\n\t/** Plugin-driven entry point: the plugin decides timing AND the summary. */\n\trequestCompaction(input: {\n\t\treadonly pluginId: string;\n\t\treadonly operationId: string;\n\t\treadonly summarize: () => JsonValue;\n\t}): ManualCompactionOutcomeV1;\n\treadonly state: ManualCompactionStateV1;\n}\n\nexport function createManualCompactionExecutor(options: {\n\treadonly coordinator: HostCheckpointCoordinatorV1;\n}): ManualCompactionExecutorV1 {\n\tconst coordinator = options.coordinator;\n\tlet state: ManualCompactionStateV1 = \"idle\";\n\tlet currentOperationId: string | undefined;\n\n\treturn {\n\t\tget state() {\n\t\t\treturn state;\n\t\t},\n\t\trequestCompaction(input) {\n\t\t\tif (state === \"in_progress\") {\n\t\t\t\t// v8 ignore next -- state 与 currentOperationId 同步赋值,busy 时必有 operationId\n\t\t\t\treturn { status: \"busy\", currentOperationId: currentOperationId ?? \"unknown\" };\n\t\t\t}\n\t\t\tif (input.pluginId.trim().length === 0) {\n\t\t\t\tthrow new Error(t(\"Compaction pluginId must be a non-empty string\"));\n\t\t\t}\n\t\t\tstate = \"in_progress\";\n\t\t\tcurrentOperationId = input.operationId;\n\t\t\ttry {\n\t\t\t\t// Stage against the current revision; a concurrent commit makes this stale.\n\t\t\t\tconst staged = coordinator.stage({\n\t\t\t\t\toperationId: input.operationId,\n\t\t\t\t\texpectedRevision: coordinator.currentRevision,\n\t\t\t\t\tpayload: null,\n\t\t\t\t});\n\t\t\t\tif (staged.status === \"stale\") {\n\t\t\t\t\treturn { status: \"stale\", currentRevision: staged.currentRevision };\n\t\t\t\t}\n\t\t\t\tif (staged.status === \"duplicate\") {\n\t\t\t\t\treturn { status: \"completed\", revision: staged.revision, summary: { duplicate: true } };\n\t\t\t\t}\n\t\t\t\t// Plugin-owned summarization; the executor knows nothing of the content.\n\t\t\t\tlet summary: JsonValue;\n\t\t\t\ttry {\n\t\t\t\t\tsummary = input.summarize();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcoordinator.cancelStage(staged.staged.token);\n\t\t\t\t\treturn { status: \"summary_failed\", reason: error instanceof Error ? error.message : String(error) };\n\t\t\t\t}\n\t\t\t\tconst outcome = coordinator.commitStage({\n\t\t\t\t\ttoken: staged.staged.token,\n\t\t\t\t\tapply: (payload, revision) => {\n\t\t\t\t\t\tvoid payload;\n\t\t\t\t\t\tvoid revision;\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (outcome.status === \"stale\") {\n\t\t\t\t\treturn { status: \"stale\", currentRevision: outcome.currentRevision };\n\t\t\t\t}\n\t\t\t\tif (outcome.status === \"committed\") {\n\t\t\t\t\treturn { status: \"completed\", revision: outcome.revision, summary };\n\t\t\t\t}\n\t\t\t\treturn { status: \"summary_failed\", reason: `Unexpected checkpoint outcome: ${outcome.status}` };\n\t\t\t} finally {\n\t\t\t\tstate = \"idle\";\n\t\t\t\tcurrentOperationId = undefined;\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,16 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Host output projection (2.6b) — projects kernel events into consistent
|
|
3
|
-
* host-facing output records with trace/correlation identity and structured
|
|
4
|
-
* errors.
|
|
5
|
-
*
|
|
6
|
-
* Every projected record carries the turn's `traceId`; tool calls and their
|
|
7
|
-
* results share the call's `correlationId`; errors become structured
|
|
8
|
-
* diagnostics (channel, severity, code) instead of raw throws; and the
|
|
9
|
-
* record order matches the event order. Events without a traceId are
|
|
10
|
-
* rejected explicitly — an unattributable output can never reach the host.
|
|
11
|
-
* The projection is deterministic and replayable. The TUI renderer itself
|
|
12
|
-
* is out of scope.
|
|
13
|
-
*/
|
|
14
1
|
export type HostOutputChannelV1 = "message" | "tool" | "diagnostic" | "lifecycle";
|
|
15
2
|
export type HostOutputSeverityV1 = "info" | "ok" | "warn" | "error";
|
|
16
3
|
export interface HostOutputRecordV1 {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output-projection.d.ts","sourceRoot":"","sources":["../../src/host/output-projection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"output-projection.d.ts","sourceRoot":"","sources":["../../src/host/output-projection.ts"],"names":[],"mappings":"AAeA,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,GAAG,WAAW,CAAC;AAClF,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACvG;IACA,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CACzB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACxB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACxB,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErG,MAAM,WAAW,qBAAqB;IACrC,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,kBAAkB,EAAE,CAAC;CACvE;AAaD,wBAAgB,yBAAyB,IAAI,qBAAqB,CA8DjE","sourcesContent":["/**\n * Host output projection (2.6b) — projects kernel events into consistent\n * host-facing output records with trace/correlation identity and structured\n * errors.\n *\n * Every projected record carries the turn's `traceId`; tool calls and their\n * results share the call's `correlationId`; errors become structured\n * diagnostics (channel, severity, code) instead of raw throws; and the\n * record order matches the event order. Events without a traceId are\n * rejected explicitly — an unattributable output can never reach the host.\n * The projection is deterministic and replayable. The TUI renderer itself\n * is out of scope.\n */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport type HostOutputChannelV1 = \"message\" | \"tool\" | \"diagnostic\" | \"lifecycle\";\nexport type HostOutputSeverityV1 = \"info\" | \"ok\" | \"warn\" | \"error\";\n\nexport interface HostOutputRecordV1 {\n\treadonly channel: HostOutputChannelV1;\n\treadonly severity: HostOutputSeverityV1;\n\treadonly traceId: string;\n\treadonly correlationId?: string;\n\treadonly at: number;\n\treadonly summary: string;\n\treadonly code?: string;\n\treadonly detail?: string;\n}\n\nexport type HostEventV1 =\n\t| { readonly kind: \"model_output\"; readonly traceId: string; readonly at: number; readonly text: string }\n\t| {\n\t\t\treadonly kind: \"tool_call\";\n\t\t\treadonly traceId: string;\n\t\t\treadonly at: number;\n\t\t\treadonly callId: string;\n\t\t\treadonly toolName: string;\n\t }\n\t| {\n\t\t\treadonly kind: \"tool_result\";\n\t\t\treadonly traceId: string;\n\t\t\treadonly at: number;\n\t\t\treadonly callId: string;\n\t\t\treadonly toolName: string;\n\t\t\treadonly ok: boolean;\n\t\t\treadonly detail?: string;\n\t }\n\t| {\n\t\t\treadonly kind: \"error\";\n\t\t\treadonly traceId: string;\n\t\t\treadonly at: number;\n\t\t\treadonly name: string;\n\t\t\treadonly message: string;\n\t }\n\t| { readonly kind: \"phase\"; readonly traceId: string; readonly at: number; readonly phase: string };\n\nexport interface HostOutputProjectorV1 {\n\tproject(events: readonly HostEventV1[]): readonly HostOutputRecordV1[];\n}\n\n/** Deterministic error-code mapping for diagnostics. */\nfunction diagnosticCode(name: string): string {\n\tconst table: readonly (readonly [string, string])[] = [\n\t\t[\"AbortError\", \"cancelled\"],\n\t\t[\"TimeoutError\", \"timeout\"],\n\t\t[\"TypeError\", \"invalid_input\"],\n\t\t[\"RangeError\", \"out_of_range\"],\n\t];\n\treturn table.find(([matching]) => matching === name)?.[1] ?? \"internal_error\";\n}\n\nexport function createHostOutputProjector(): HostOutputProjectorV1 {\n\treturn {\n\t\tproject(events) {\n\t\t\treturn events.map((event) => {\n\t\t\t\tif (!event.traceId) {\n\t\t\t\t\tthrow new Error(t(\"Host output projection requires a traceId on every event\"));\n\t\t\t\t}\n\t\t\t\tswitch (event.kind) {\n\t\t\t\t\tcase \"model_output\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"message\" as const,\n\t\t\t\t\t\t\tseverity: \"info\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: event.text,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"tool_call\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"tool\" as const,\n\t\t\t\t\t\t\tseverity: \"info\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tcorrelationId: event.callId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: `tool ${event.toolName} called`,\n\t\t\t\t\t\t\tcode: event.toolName,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"tool_result\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"tool\" as const,\n\t\t\t\t\t\t\tseverity: event.ok ? (\"ok\" as const) : (\"error\" as const),\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tcorrelationId: event.callId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: `tool ${event.toolName} ${event.ok ? \"succeeded\" : \"failed\"}`,\n\t\t\t\t\t\t\tcode: event.toolName,\n\t\t\t\t\t\t\t...(event.detail === undefined ? {} : { detail: event.detail }),\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"diagnostic\" as const,\n\t\t\t\t\t\t\tseverity: \"error\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: event.message,\n\t\t\t\t\t\t\tcode: diagnosticCode(event.name),\n\t\t\t\t\t\t\tdetail: event.name,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"phase\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"lifecycle\" as const,\n\t\t\t\t\t\t\tseverity: \"info\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: `phase: ${event.phase}`,\n\t\t\t\t\t\t\tcode: event.phase,\n\t\t\t\t\t\t};\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error(t(\"Unsupported host event reached the projector\"));\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host output projection (2.6b) — projects kernel events into consistent
|
|
3
|
+
* host-facing output records with trace/correlation identity and structured
|
|
4
|
+
* errors.
|
|
5
|
+
*
|
|
6
|
+
* Every projected record carries the turn's `traceId`; tool calls and their
|
|
7
|
+
* results share the call's `correlationId`; errors become structured
|
|
8
|
+
* diagnostics (channel, severity, code) instead of raw throws; and the
|
|
9
|
+
* record order matches the event order. Events without a traceId are
|
|
10
|
+
* rejected explicitly — an unattributable output can never reach the host.
|
|
11
|
+
* The projection is deterministic and replayable. The TUI renderer itself
|
|
12
|
+
* is out of scope.
|
|
13
|
+
*/
|
|
14
|
+
import { t } from "../core/i18n/index.js";
|
|
1
15
|
/** Deterministic error-code mapping for diagnostics. */
|
|
2
16
|
function diagnosticCode(name) {
|
|
3
17
|
const table = [
|
|
@@ -13,7 +27,7 @@ export function createHostOutputProjector() {
|
|
|
13
27
|
project(events) {
|
|
14
28
|
return events.map((event) => {
|
|
15
29
|
if (!event.traceId) {
|
|
16
|
-
throw new Error("Host output projection requires a traceId on every event");
|
|
30
|
+
throw new Error(t("Host output projection requires a traceId on every event"));
|
|
17
31
|
}
|
|
18
32
|
switch (event.kind) {
|
|
19
33
|
case "model_output":
|
|
@@ -65,7 +79,7 @@ export function createHostOutputProjector() {
|
|
|
65
79
|
code: event.phase,
|
|
66
80
|
};
|
|
67
81
|
default:
|
|
68
|
-
throw new Error("Unsupported host event reached the projector");
|
|
82
|
+
throw new Error(t("Unsupported host event reached the projector"));
|
|
69
83
|
}
|
|
70
84
|
});
|
|
71
85
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output-projection.js","sourceRoot":"","sources":["../../src/host/output-projection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"output-projection.js","sourceRoot":"","sources":["../../src/host/output-projection.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host output projection (2.6b) — projects kernel events into consistent\n * host-facing output records with trace/correlation identity and structured\n * errors.\n *\n * Every projected record carries the turn's `traceId`; tool calls and their\n * results share the call's `correlationId`; errors become structured\n * diagnostics (channel, severity, code) instead of raw throws; and the\n * record order matches the event order. Events without a traceId are\n * rejected explicitly — an unattributable output can never reach the host.\n * The projection is deterministic and replayable. The TUI renderer itself\n * is out of scope.\n */\nimport { t } from \"../core/i18n/index.ts\";\n\nexport type HostOutputChannelV1 = \"message\" | \"tool\" | \"diagnostic\" | \"lifecycle\";\nexport type HostOutputSeverityV1 = \"info\" | \"ok\" | \"warn\" | \"error\";\n\nexport interface HostOutputRecordV1 {\n\treadonly channel: HostOutputChannelV1;\n\treadonly severity: HostOutputSeverityV1;\n\treadonly traceId: string;\n\treadonly correlationId?: string;\n\treadonly at: number;\n\treadonly summary: string;\n\treadonly code?: string;\n\treadonly detail?: string;\n}\n\nexport type HostEventV1 =\n\t| { readonly kind: \"model_output\"; readonly traceId: string; readonly at: number; readonly text: string }\n\t| {\n\t\t\treadonly kind: \"tool_call\";\n\t\t\treadonly traceId: string;\n\t\t\treadonly at: number;\n\t\t\treadonly callId: string;\n\t\t\treadonly toolName: string;\n\t }\n\t| {\n\t\t\treadonly kind: \"tool_result\";\n\t\t\treadonly traceId: string;\n\t\t\treadonly at: number;\n\t\t\treadonly callId: string;\n\t\t\treadonly toolName: string;\n\t\t\treadonly ok: boolean;\n\t\t\treadonly detail?: string;\n\t }\n\t| {\n\t\t\treadonly kind: \"error\";\n\t\t\treadonly traceId: string;\n\t\t\treadonly at: number;\n\t\t\treadonly name: string;\n\t\t\treadonly message: string;\n\t }\n\t| { readonly kind: \"phase\"; readonly traceId: string; readonly at: number; readonly phase: string };\n\nexport interface HostOutputProjectorV1 {\n\tproject(events: readonly HostEventV1[]): readonly HostOutputRecordV1[];\n}\n\n/** Deterministic error-code mapping for diagnostics. */\nfunction diagnosticCode(name: string): string {\n\tconst table: readonly (readonly [string, string])[] = [\n\t\t[\"AbortError\", \"cancelled\"],\n\t\t[\"TimeoutError\", \"timeout\"],\n\t\t[\"TypeError\", \"invalid_input\"],\n\t\t[\"RangeError\", \"out_of_range\"],\n\t];\n\treturn table.find(([matching]) => matching === name)?.[1] ?? \"internal_error\";\n}\n\nexport function createHostOutputProjector(): HostOutputProjectorV1 {\n\treturn {\n\t\tproject(events) {\n\t\t\treturn events.map((event) => {\n\t\t\t\tif (!event.traceId) {\n\t\t\t\t\tthrow new Error(t(\"Host output projection requires a traceId on every event\"));\n\t\t\t\t}\n\t\t\t\tswitch (event.kind) {\n\t\t\t\t\tcase \"model_output\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"message\" as const,\n\t\t\t\t\t\t\tseverity: \"info\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: event.text,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"tool_call\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"tool\" as const,\n\t\t\t\t\t\t\tseverity: \"info\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tcorrelationId: event.callId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: `tool ${event.toolName} called`,\n\t\t\t\t\t\t\tcode: event.toolName,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"tool_result\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"tool\" as const,\n\t\t\t\t\t\t\tseverity: event.ok ? (\"ok\" as const) : (\"error\" as const),\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tcorrelationId: event.callId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: `tool ${event.toolName} ${event.ok ? \"succeeded\" : \"failed\"}`,\n\t\t\t\t\t\t\tcode: event.toolName,\n\t\t\t\t\t\t\t...(event.detail === undefined ? {} : { detail: event.detail }),\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"diagnostic\" as const,\n\t\t\t\t\t\t\tseverity: \"error\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: event.message,\n\t\t\t\t\t\t\tcode: diagnosticCode(event.name),\n\t\t\t\t\t\t\tdetail: event.name,\n\t\t\t\t\t\t};\n\t\t\t\t\tcase \"phase\":\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tchannel: \"lifecycle\" as const,\n\t\t\t\t\t\t\tseverity: \"info\" as const,\n\t\t\t\t\t\t\ttraceId: event.traceId,\n\t\t\t\t\t\t\tat: event.at,\n\t\t\t\t\t\t\tsummary: `phase: ${event.phase}`,\n\t\t\t\t\t\t\tcode: event.phase,\n\t\t\t\t\t\t};\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error(t(\"Unsupported host event reached the projector\"));\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
|