@ai-agent-forge/agent-forge 0.86.7 → 0.88.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 +45 -0
- package/README.md +10 -11
- 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 +430 -413
- package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
- package/dist/bundle/chunks/chunk-HLJEVRWP.js +13 -0
- package/dist/bundle/chunks/chunk-YGHQME4V.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 +17 -4
- 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 +5 -3
- 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 +6 -10
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +35 -133
- 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-internal.d.ts +0 -6
- package/dist/core/agent-session-internal.d.ts.map +1 -1
- package/dist/core/agent-session-internal.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 -3
- 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 -22
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +147 -67
- 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-compaction-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-compaction-policy.js +0 -34
- package/dist/core/extensions/bootstrap-compaction-policy.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 +4 -3
- 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/extensions/provider-failover.d.ts +7 -3
- package/dist/core/extensions/provider-failover.d.ts.map +1 -1
- package/dist/core/extensions/provider-failover.js +9 -8
- package/dist/core/extensions/provider-failover.js.map +1 -1
- package/dist/core/facade/coding-agent-facade.d.ts +6 -6
- package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
- package/dist/core/facade/coding-agent-facade.js +2 -3
- 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 +229 -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 +267 -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 +286 -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-config.d.ts +0 -1
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +9 -1
- package/dist/core/model-config.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 +11 -7
- 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 +2 -2
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +29 -21
- 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 +27 -5
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +80 -55
- 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 +20 -20
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +47 -59
- 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 +97 -60
- 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 +0 -2
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -10
- 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 +4 -6
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +115 -120
- 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 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +350 -279
- 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 +0 -8
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +3 -14
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +0 -9
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +0 -19
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.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 +9 -2
- package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js +44 -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/plugin-bootstrap.d.ts +9 -1
- package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
- package/dist/plugins/ecosystem/plugin-bootstrap.js +5 -0
- package/dist/plugins/ecosystem/plugin-bootstrap.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/photon.d.ts +2 -2
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js +2 -2
- package/dist/utils/photon.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/compaction.md +1 -3
- package/docs/docs.json +4 -0
- package/docs/index.md +1 -0
- package/docs/keybindings.md +3 -0
- package/docs/mcp.md +103 -0
- package/docs/models.md +14 -22
- package/docs/providers.md +0 -1
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +1 -26
- package/docs/sdk.md +4 -6
- package/docs/settings.md +10 -12
- package/docs/skills.md +1 -9
- package/docs/terminal-setup.md +2 -3
- package/docs/usage.md +7 -6
- 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/examples/sdk/10-settings.ts +2 -4
- package/examples/sdk/12-full-control.ts +1 -2
- package/package.json +1 -3
- package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
- package/dist/core/extensions/microcompact.d.ts +0 -80
- package/dist/core/extensions/microcompact.d.ts.map +0 -1
- package/dist/core/extensions/microcompact.js +0 -134
- package/dist/core/extensions/microcompact.js.map +0 -1
- package/dist/server/create-harness.d.ts +0 -26
- package/dist/server/create-harness.d.ts.map +0 -1
- package/dist/server/create-harness.js +0 -106
- package/dist/server/create-harness.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../../src/remote/server-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Remote entry assembly: one function that wires the coding-agent session\n * source, the durable journal, and the server boundary into a started\n * `PiServer` handle.\n *\n * The CLI remote entry (`--serve <port>`, src/cli/serve.ts) is a thin wrapper\n * over this function: it supplies the loopback TCP listener, process signal\n * handling, and default error logging, while this entry owns the session\n * source, the durable journal, and the default model catalog. Hosts that need\n * custom listeners or auth use `assembleCodingAgentServer` directly.\n *\n * Defaults: the durable journal lives in the agent config directory\n * (`<agentDir>/remote-server-journal.jsonl`), never in the process cwd, so two\n * servers started from different directories but sharing one agentDir\n * journalize the same session timeline. The default model catalog is built\n * from the real agent model runtime (same agentDir domain as the session\n * source), so `list` reports models whose provider auth is configured and\n * `resolve` applies the local CLI resolution semantics: the ref must exist in\n * the catalog and its provider must have configured auth.\n *\n * Retry boundary: the gate advances only after a successful append so a failed\n * write can be retried; advancing before the write would permanently drop that\n * revision's boundary snapshot on the next same-revision broadcast.\n *\n * Journal boundary: the journal keeps snapshots at durable revision boundaries\n * only. Streaming intermediate states persist no SessionManager entry, so\n * their snapshots are not journaled (wire broadcasts are unaffected); after a\n * restart, replay converges to the same state as a local session reopen.\n *\n * Trust boundary: the expected deployment is loopback listeners with no default\n * authentication, and the session source accepts whatever `cwd` a client\n * submits — a local process can drive the agent in any directory. This entry\n * is therefore only safe in a single-user local trust environment; multi-tenant\n * authentication and workspace path restrictions are later slices (the CLI\n * offers an opt-in `--serve-workspace-root` boundary).\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { ModelMetadata, ModelRef, ServerEvent } from \"@agent-forge/protocol\";\nimport {\n\ttype DurableSessionEventJournal,\n\tFileDurableSessionEventJournal,\n\ttype PiServer,\n\ttype PiServerListener,\n\ttoProtocolModelMetadata,\n} from \"@agent-forge/server\";\nimport { getAgentDir } from \"../config.ts\";\nimport { ModelRuntime } from \"../core/model-runtime.ts\";\nimport {\n\tassembleCodingAgentServer,\n\ttype CodingAgentServerAssemblyOptions,\n\ttype CodingAgentServerModels,\n\ttype CodingAgentServerSessionSource,\n} from \"./server-assembly.ts\";\nimport { createFileSessionSource, type FileSessionSourceOptions } from \"./session-source.ts\";\n\n/**\n * Stable host-level writer identity for the default durable writer lease\n * (D-067 phase 2 S2): persisted under the agent dir and reused across\n * process restarts, so a restarted server re-claims its own still-live store\n * lease instantly (same writer id = the lease's idempotent refresh) instead\n * of waiting out a dead predecessor's TTL. Distinct nodes sharing one store\n * must each pin their own id via `options.writerId`.\n */\nexport function readOrCreateWriterId(agentDir: string): string {\n\tconst path = join(agentDir, \"durable\", \"writer-id\");\n\ttry {\n\t\tconst existing = readFileSync(path, \"utf8\").trim();\n\t\tif (existing !== \"\") return existing;\n\t} catch {\n\t\t// First start (or unreadable file): fall through and mint a fresh id.\n\t}\n\tconst id = randomUUID();\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, id);\n\treturn id;\n}\n\n/** Options for the programmatic remote server entry. */\nexport interface StartCodingAgentRemoteServerOptions {\n\t/** Session source; built from `sessionSourceOptions` when omitted. */\n\treadonly sessions?: CodingAgentServerSessionSource;\n\t/** Session source configuration, used when `sessions` is not supplied. */\n\treadonly sessionSourceOptions?: FileSessionSourceOptions;\n\t/**\n\t * Path to the durable journal JSONL file. Defaults to\n\t * `<agentDir>/remote-server-journal.jsonl`, derived from\n\t * `sessionSourceOptions.agentDir` (or the default agent dir), so the\n\t * journal never lands in the process cwd and servers sharing one agentDir\n\t * share one session timeline.\n\t */\n\treadonly journalPath?: string;\n\t/** Pre-built journal; overrides `journalPath`. The revision gate still applies. */\n\treadonly journal?: FileDurableSessionEventJournal;\n\t/**\n\t * Model catalog for `listModels` and `set_model` resolution. Defaults to\n\t * the real agent model runtime for the same agentDir domain as the session\n\t * source: `list` returns models whose provider auth is configured;\n\t * `resolve` requires the ref to exist in the catalog and its provider to\n\t * have configured auth (local CLI semantics).\n\t */\n\treadonly models?: CodingAgentServerModels;\n\t/** Transport listeners (loopback in tests; unix socket or TCP later). */\n\treadonly listeners: readonly PiServerListener[];\n\t/** Optional auth hook, passed through to `assembleCodingAgentServer`. */\n\treadonly authenticate?: CodingAgentServerAssemblyOptions[\"authenticate\"];\n\t/** Optional authorization hook, passed through unchanged. */\n\treadonly authorize?: CodingAgentServerAssemblyOptions[\"authorize\"];\n\t/** Optional server id. */\n\treadonly serverId?: string;\n\t/**\n\t * Durable service backing the server `operations`/`artifacts` surfaces.\n\t * Omission keeps those surfaces unconfigured: operations answer\n\t * `durable_unavailable` and artifacts answer `not_implemented`.\n\t */\n\treadonly durable?: CodingAgentServerAssemblyOptions[\"durable\"];\n\t/**\n\t * Writer id claimed on the durable service. Hosts that also inject the same\n\t * store into the session source (`sessionSourceOptions.agentTaskResults`)\n\t * pass the same id here so the server and the sessions share one writer.\n\t */\n\treadonly writerId?: CodingAgentServerAssemblyOptions[\"writerId\"];\n\t/** Executors for submitted operation types; unknown types terminate as rejected. */\n\treadonly operationExecutors?: CodingAgentServerAssemblyOptions[\"operationExecutors\"];\n\t/** Optional internal-error sink, passed through to `assembleCodingAgentServer`. */\n\treadonly onError?: CodingAgentServerAssemblyOptions[\"onError\"];\n}\n\n/** A started remote server handle. */\nexport interface CodingAgentRemoteServerHandle {\n\t/** The underlying `PiServer` for advanced control. */\n\treadonly server: PiServer;\n\t/** Human-readable listener addresses after startup. */\n\treadonly addresses: readonly string[];\n\t/** Stops the server, closes listeners, and flushes the journal. */\n\tclose(): Promise<void>;\n}\n\n/**\n * Journal decorator that journals snapshots only at durable revision\n * boundaries. The server appends a full snapshot for every runtime event, but\n * streaming intermediate states persist no SessionManager entry: their\n * snapshot revision does not advance. This gate drops `session_snapshot`\n * appends whose revision did not advance past the last journaled one for that\n * session, so per-chunk streaming updates no longer multiply journal entries\n * on disk. Wire broadcasts are unaffected (they flow through the server, not\n * the journal); `session_progress` and `session_removed` events pass through\n * unchanged. After a restart, replay converges to the same state as a local\n * session reopen: the latest snapshot at or before each persisted revision.\n *\n * Retry boundary: the gate advances only after a successful append so a failed\n * write can be retried. Because the server broadcasts snapshots\n * fire-and-forget, several same-revision appends can be in flight at once; a\n * synchronous in-flight claim (taken before the first await, like the old\n * pre-advance) keeps those duplicates dropped while the revision stays\n * retryable until one append actually lands.\n */\nclass RevisionGatedSessionJournal implements DurableSessionEventJournal {\n\t/** Last durably journaled revision per session id. */\n\tprivate readonly lastJournaledRevision = new Map<string, number>();\n\t/** Revisions whose append is currently in flight, keyed by `sessionId\\0revision`. */\n\tprivate readonly inFlightRevisions = new Set<string>();\n\tprivate readonly inner: DurableSessionEventJournal;\n\n\tconstructor(inner: DurableSessionEventJournal) {\n\t\tthis.inner = inner;\n\t}\n\n\tasync append(sessionId: string, event: ServerEvent): Promise<number> {\n\t\tif (event.type === \"session_snapshot\") {\n\t\t\tconst revision = event.snapshot.revision;\n\t\t\t// An empty map reads as -Infinity so the first snapshot is always\n\t\t\t// journaled, including the pre-first-entry revision 0. The first\n\t\t\t// snapshot after a revision advance is never missed: the gate only\n\t\t\t// drops revisions that are <= the last durably journaled one, plus\n\t\t\t// concurrent duplicates of a revision still being written.\n\t\t\tconst key = `${sessionId}\\0${revision}`;\n\t\t\tif (\n\t\t\t\trevision <= (this.lastJournaledRevision.get(sessionId) ?? Number.NEGATIVE_INFINITY) ||\n\t\t\t\tthis.inFlightRevisions.has(key)\n\t\t\t) {\n\t\t\t\t// No record was written; the server discards the snapshot append\n\t\t\t\t// cursor, so 0 (\"no record\") is safe to return here.\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t// Synchronous claim before the first await: concurrent same-revision\n\t\t\t// appends are dropped without waiting on the write.\n\t\t\tthis.inFlightRevisions.add(key);\n\t\t\ttry {\n\t\t\t\tconst cursor = await this.inner.append(sessionId, event);\n\t\t\t\t// Advance only after a successful append so a failed write can be\n\t\t\t\t// retried; an earlier revision completing late must not regress\n\t\t\t\t// the high-water mark of a later committed one.\n\t\t\t\tif (revision > (this.lastJournaledRevision.get(sessionId) ?? Number.NEGATIVE_INFINITY)) {\n\t\t\t\t\tthis.lastJournaledRevision.set(sessionId, revision);\n\t\t\t\t}\n\t\t\t\treturn cursor;\n\t\t\t} finally {\n\t\t\t\t// Release the claim on success and failure alike: on failure the\n\t\t\t\t// next same-revision broadcast retries the append instead of it\n\t\t\t\t// being dropped as already journaled.\n\t\t\t\tthis.inFlightRevisions.delete(key);\n\t\t\t}\n\t\t}\n\t\treturn this.inner.append(sessionId, event);\n\t}\n\n\treplay(\n\t\tsessionId: string,\n\t\tafterCursor: number,\n\t\tlimit: number,\n\t): Promise<{\n\t\treadonly events: readonly { readonly cursor: number; readonly event: ServerEvent }[];\n\t\treadonly nextCursor: number;\n\t\treadonly complete: boolean;\n\t\treadonly gap: boolean;\n\t}> {\n\t\treturn this.inner.replay(sessionId, afterCursor, limit);\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.inner.close();\n\t}\n}\n\n/**\n * Default model catalog built from the real agent model runtime, mirroring how\n * `createAgentSession` builds one from `agentDir`. `list` projects the models\n * whose provider auth is configured (the local CLI `--list-models` semantics).\n * `resolve` mirrors local model restoration: the ref must exist in the catalog\n * and its provider must have configured auth; anything else fails with a\n * plain `Error` that the server boundary maps to `invalid_request`.\n *\n * Boundary: the catalog is a startup-time snapshot. Provider auth added while\n * the server runs is not reflected in `list` results (new sessions can still\n * resolve such models, since `resolve` checks auth on demand); hosts needing a\n * fresh catalog rebuild the server.\n */\nfunction createDefaultServerModels(modelRuntime: ModelRuntime): CodingAgentServerModels {\n\treturn {\n\t\tlist: async (): Promise<readonly ModelMetadata[]> => {\n\t\t\tconst available = await modelRuntime.getAvailable();\n\t\t\treturn available.map((model) =>\n\t\t\t\ttoProtocolModelMetadata(model, modelRuntime.hasConfiguredAuth(model.provider)),\n\t\t\t);\n\t\t},\n\t\tresolve: async (ref: ModelRef) => {\n\t\t\tconst model = modelRuntime.getModel(ref.provider, ref.id);\n\t\t\t// checkAuth resolves the provider's configured auth on demand, so\n\t\t\t// resolution does not depend on whether an availability refresh\n\t\t\t// (getAvailable) already populated the auth snapshot.\n\t\t\tconst auth = model === undefined ? undefined : await modelRuntime.checkAuth(ref.provider);\n\t\t\tif (model === undefined || auth === undefined) {\n\t\t\t\tthrow new Error(`Unknown or unavailable model: ${ref.provider}/${ref.id}`);\n\t\t\t}\n\t\t\treturn model;\n\t\t},\n\t};\n}\n\n/**\n * Assembles and starts a coding-agent remote server: session source + durable\n * journal + transport listeners behind the public server boundary.\n */\nexport async function startCodingAgentRemoteServer(\n\toptions: StartCodingAgentRemoteServerOptions,\n): Promise<CodingAgentRemoteServerHandle> {\n\tconst sessionSourceOptions: FileSessionSourceOptions | undefined = options.sessionSourceOptions;\n\tconst sessions =\n\t\toptions.sessions ??\n\t\t(sessionSourceOptions === undefined ? undefined : createFileSessionSource(sessionSourceOptions));\n\tif (sessions === undefined) {\n\t\tthrow new Error(\"Remote server requires a session source or sessionSourceOptions\");\n\t}\n\n\t// Default journal domain: the agent config directory the session source\n\t// resolves against (explicit agentDir, else the default agent dir) — never\n\t// the process cwd. Two servers sharing one agentDir therefore share one\n\t// journal for the same sessions, independent of where they were started.\n\tconst agentDir = sessionSourceOptions?.agentDir ?? getAgentDir();\n\tconst journal = new RevisionGatedSessionJournal(\n\t\toptions.journal ??\n\t\t\tnew FileDurableSessionEventJournal(options.journalPath ?? join(agentDir, \"remote-server-journal.jsonl\")),\n\t);\n\t// Default writer identity (D-067 phase 2 S2): stable per agent-dir domain\n\t// (persisted beside the durable log), so a restarted server re-claims its\n\t// own still-live store lease instantly — same writer id = the lease's\n\t// idempotent refresh — instead of being locked out by its dead\n\t// predecessor's TTL. Distinct nodes sharing one store must each pin their\n\t// own writer id via `options.writerId`.\n\tconst writerId = options.writerId ?? readOrCreateWriterId(agentDir);\n\n\t// Default model catalog: build a real runtime from the same agentDir\n\t// domain, mirroring `createAgentSession`'s authPath/modelsPath resolution.\n\tconst models: CodingAgentServerModels =\n\t\toptions.models ??\n\t\tcreateDefaultServerModels(\n\t\t\tawait ModelRuntime.create(\n\t\t\t\tsessionSourceOptions?.agentDir === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tauthPath: join(sessionSourceOptions.agentDir, \"auth.json\"),\n\t\t\t\t\t\t\tmodelsPath: join(sessionSourceOptions.agentDir, \"models.json\"),\n\t\t\t\t\t\t},\n\t\t\t),\n\t\t);\n\n\tconst { server, service } = assembleCodingAgentServer({\n\t\tsessions,\n\t\tmodels,\n\t\tlisteners: options.listeners,\n\t\tjournal,\n\t\t...(options.authenticate === undefined ? {} : { authenticate: options.authenticate }),\n\t\t...(options.authorize === undefined ? {} : { authorize: options.authorize }),\n\t\t...(options.serverId === undefined ? {} : { serverId: options.serverId }),\n\t\t...(options.onError === undefined ? {} : { onError: options.onError }),\n\t\t...(options.durable === undefined ? {} : { durable: options.durable }),\n\t\t...(writerId === undefined ? {} : { writerId }),\n\t\t...(options.operationExecutors === undefined ? {} : { operationExecutors: options.operationExecutors }),\n\t});\n\n\tawait server.start();\n\n\treturn {\n\t\tserver,\n\t\taddresses: server.addresses,\n\t\tclose: async () => {\n\t\t\t// Graceful shutdown releases the store writer lease (D-067 phase 2\n\t\t\t// S2) so a successor process can claim immediately; crash recovery\n\t\t\t// stays the lease-TTL path. Best-effort: shutdown never fails on a\n\t\t\t// release error.\n\t\t\ttry {\n\t\t\t\tservice.releaseWriterLease();\n\t\t\t} catch {\n\t\t\t\t// Release failures surface nowhere at shutdown.\n\t\t\t}\n\t\t\tawait server.close();\n\t\t\tawait journal.close();\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server-entry.js","sourceRoot":"","sources":["../../src/remote/server-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Remote entry assembly: one function that wires the coding-agent session\n * source, the durable journal, and the server boundary into a started\n * `PiServer` handle.\n *\n * The CLI remote entry (`--serve <port>`, src/cli/serve.ts) is a thin wrapper\n * over this function: it supplies the loopback TCP listener, process signal\n * handling, and default error logging, while this entry owns the session\n * source, the durable journal, and the default model catalog. Hosts that need\n * custom listeners or auth use `assembleCodingAgentServer` directly.\n *\n * Defaults: the durable journal lives in the agent config directory\n * (`<agentDir>/remote-server-journal.jsonl`), never in the process cwd, so two\n * servers started from different directories but sharing one agentDir\n * journalize the same session timeline. The default model catalog is built\n * from the real agent model runtime (same agentDir domain as the session\n * source), so `list` reports models whose provider auth is configured and\n * `resolve` applies the local CLI resolution semantics: the ref must exist in\n * the catalog and its provider must have configured auth.\n *\n * Retry boundary: the gate advances only after a successful append so a failed\n * write can be retried; advancing before the write would permanently drop that\n * revision's boundary snapshot on the next same-revision broadcast.\n *\n * Journal boundary: the journal keeps snapshots at durable revision boundaries\n * only. Streaming intermediate states persist no SessionManager entry, so\n * their snapshots are not journaled (wire broadcasts are unaffected); after a\n * restart, replay converges to the same state as a local session reopen.\n *\n * Trust boundary: the expected deployment is loopback listeners with no default\n * authentication, and the session source accepts whatever `cwd` a client\n * submits — a local process can drive the agent in any directory. This entry\n * is therefore only safe in a single-user local trust environment; multi-tenant\n * authentication and workspace path restrictions are later slices (the CLI\n * offers an opt-in `--serve-workspace-root` boundary).\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { ModelMetadata, ModelRef, ServerEvent } from \"@agent-forge/protocol\";\nimport {\n\ttype DurableSessionEventJournal,\n\tFileDurableSessionEventJournal,\n\ttype PiServer,\n\ttype PiServerListener,\n\ttoProtocolModelMetadata,\n} from \"@agent-forge/server\";\nimport { getAgentDir } from \"../config.ts\";\nimport { t } from \"../core/i18n/index.ts\";\nimport { ModelRuntime } from \"../core/model-runtime.ts\";\nimport {\n\tassembleCodingAgentServer,\n\ttype CodingAgentServerAssemblyOptions,\n\ttype CodingAgentServerModels,\n\ttype CodingAgentServerSessionSource,\n} from \"./server-assembly.ts\";\nimport { createFileSessionSource, type FileSessionSourceOptions } from \"./session-source.ts\";\n\n/**\n * Stable host-level writer identity for the default durable writer lease\n * (D-067 phase 2 S2): persisted under the agent dir and reused across\n * process restarts, so a restarted server re-claims its own still-live store\n * lease instantly (same writer id = the lease's idempotent refresh) instead\n * of waiting out a dead predecessor's TTL. Distinct nodes sharing one store\n * must each pin their own id via `options.writerId`.\n */\nexport function readOrCreateWriterId(agentDir: string): string {\n\tconst path = join(agentDir, \"durable\", \"writer-id\");\n\ttry {\n\t\tconst existing = readFileSync(path, \"utf8\").trim();\n\t\tif (existing !== \"\") return existing;\n\t} catch {\n\t\t// First start (or unreadable file): fall through and mint a fresh id.\n\t}\n\tconst id = randomUUID();\n\tmkdirSync(dirname(path), { recursive: true });\n\twriteFileSync(path, id);\n\treturn id;\n}\n\n/** Options for the programmatic remote server entry. */\nexport interface StartCodingAgentRemoteServerOptions {\n\t/** Session source; built from `sessionSourceOptions` when omitted. */\n\treadonly sessions?: CodingAgentServerSessionSource;\n\t/** Session source configuration, used when `sessions` is not supplied. */\n\treadonly sessionSourceOptions?: FileSessionSourceOptions;\n\t/**\n\t * Path to the durable journal JSONL file. Defaults to\n\t * `<agentDir>/remote-server-journal.jsonl`, derived from\n\t * `sessionSourceOptions.agentDir` (or the default agent dir), so the\n\t * journal never lands in the process cwd and servers sharing one agentDir\n\t * share one session timeline.\n\t */\n\treadonly journalPath?: string;\n\t/** Pre-built journal; overrides `journalPath`. The revision gate still applies. */\n\treadonly journal?: FileDurableSessionEventJournal;\n\t/**\n\t * Model catalog for `listModels` and `set_model` resolution. Defaults to\n\t * the real agent model runtime for the same agentDir domain as the session\n\t * source: `list` returns models whose provider auth is configured;\n\t * `resolve` requires the ref to exist in the catalog and its provider to\n\t * have configured auth (local CLI semantics).\n\t */\n\treadonly models?: CodingAgentServerModels;\n\t/** Transport listeners (loopback in tests; unix socket or TCP later). */\n\treadonly listeners: readonly PiServerListener[];\n\t/** Optional auth hook, passed through to `assembleCodingAgentServer`. */\n\treadonly authenticate?: CodingAgentServerAssemblyOptions[\"authenticate\"];\n\t/** Optional authorization hook, passed through unchanged. */\n\treadonly authorize?: CodingAgentServerAssemblyOptions[\"authorize\"];\n\t/** Optional server id. */\n\treadonly serverId?: string;\n\t/**\n\t * Durable service backing the server `operations`/`artifacts` surfaces.\n\t * Omission keeps those surfaces unconfigured: operations answer\n\t * `durable_unavailable` and artifacts answer `not_implemented`.\n\t */\n\treadonly durable?: CodingAgentServerAssemblyOptions[\"durable\"];\n\t/**\n\t * Writer id claimed on the durable service. Hosts that also inject the same\n\t * store into the session source (`sessionSourceOptions.agentTaskResults`)\n\t * pass the same id here so the server and the sessions share one writer.\n\t */\n\treadonly writerId?: CodingAgentServerAssemblyOptions[\"writerId\"];\n\t/** Executors for submitted operation types; unknown types terminate as rejected. */\n\treadonly operationExecutors?: CodingAgentServerAssemblyOptions[\"operationExecutors\"];\n\t/** Optional internal-error sink, passed through to `assembleCodingAgentServer`. */\n\treadonly onError?: CodingAgentServerAssemblyOptions[\"onError\"];\n}\n\n/** A started remote server handle. */\nexport interface CodingAgentRemoteServerHandle {\n\t/** The underlying `PiServer` for advanced control. */\n\treadonly server: PiServer;\n\t/** Human-readable listener addresses after startup. */\n\treadonly addresses: readonly string[];\n\t/** Stops the server, closes listeners, and flushes the journal. */\n\tclose(): Promise<void>;\n}\n\n/**\n * Journal decorator that journals snapshots only at durable revision\n * boundaries. The server appends a full snapshot for every runtime event, but\n * streaming intermediate states persist no SessionManager entry: their\n * snapshot revision does not advance. This gate drops `session_snapshot`\n * appends whose revision did not advance past the last journaled one for that\n * session, so per-chunk streaming updates no longer multiply journal entries\n * on disk. Wire broadcasts are unaffected (they flow through the server, not\n * the journal); `session_progress` and `session_removed` events pass through\n * unchanged. After a restart, replay converges to the same state as a local\n * session reopen: the latest snapshot at or before each persisted revision.\n *\n * Retry boundary: the gate advances only after a successful append so a failed\n * write can be retried. Because the server broadcasts snapshots\n * fire-and-forget, several same-revision appends can be in flight at once; a\n * synchronous in-flight claim (taken before the first await, like the old\n * pre-advance) keeps those duplicates dropped while the revision stays\n * retryable until one append actually lands.\n */\nclass RevisionGatedSessionJournal implements DurableSessionEventJournal {\n\t/** Last durably journaled revision per session id. */\n\tprivate readonly lastJournaledRevision = new Map<string, number>();\n\t/** Revisions whose append is currently in flight, keyed by `sessionId\\0revision`. */\n\tprivate readonly inFlightRevisions = new Set<string>();\n\tprivate readonly inner: DurableSessionEventJournal;\n\n\tconstructor(inner: DurableSessionEventJournal) {\n\t\tthis.inner = inner;\n\t}\n\n\tasync append(sessionId: string, event: ServerEvent): Promise<number> {\n\t\tif (event.type === \"session_snapshot\") {\n\t\t\tconst revision = event.snapshot.revision;\n\t\t\t// An empty map reads as -Infinity so the first snapshot is always\n\t\t\t// journaled, including the pre-first-entry revision 0. The first\n\t\t\t// snapshot after a revision advance is never missed: the gate only\n\t\t\t// drops revisions that are <= the last durably journaled one, plus\n\t\t\t// concurrent duplicates of a revision still being written.\n\t\t\tconst key = `${sessionId}\\0${revision}`;\n\t\t\tif (\n\t\t\t\trevision <= (this.lastJournaledRevision.get(sessionId) ?? Number.NEGATIVE_INFINITY) ||\n\t\t\t\tthis.inFlightRevisions.has(key)\n\t\t\t) {\n\t\t\t\t// No record was written; the server discards the snapshot append\n\t\t\t\t// cursor, so 0 (\"no record\") is safe to return here.\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\t// Synchronous claim before the first await: concurrent same-revision\n\t\t\t// appends are dropped without waiting on the write.\n\t\t\tthis.inFlightRevisions.add(key);\n\t\t\ttry {\n\t\t\t\tconst cursor = await this.inner.append(sessionId, event);\n\t\t\t\t// Advance only after a successful append so a failed write can be\n\t\t\t\t// retried; an earlier revision completing late must not regress\n\t\t\t\t// the high-water mark of a later committed one.\n\t\t\t\tif (revision > (this.lastJournaledRevision.get(sessionId) ?? Number.NEGATIVE_INFINITY)) {\n\t\t\t\t\tthis.lastJournaledRevision.set(sessionId, revision);\n\t\t\t\t}\n\t\t\t\treturn cursor;\n\t\t\t} finally {\n\t\t\t\t// Release the claim on success and failure alike: on failure the\n\t\t\t\t// next same-revision broadcast retries the append instead of it\n\t\t\t\t// being dropped as already journaled.\n\t\t\t\tthis.inFlightRevisions.delete(key);\n\t\t\t}\n\t\t}\n\t\treturn this.inner.append(sessionId, event);\n\t}\n\n\treplay(\n\t\tsessionId: string,\n\t\tafterCursor: number,\n\t\tlimit: number,\n\t): Promise<{\n\t\treadonly events: readonly { readonly cursor: number; readonly event: ServerEvent }[];\n\t\treadonly nextCursor: number;\n\t\treadonly complete: boolean;\n\t\treadonly gap: boolean;\n\t}> {\n\t\treturn this.inner.replay(sessionId, afterCursor, limit);\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.inner.close();\n\t}\n}\n\n/**\n * Default model catalog built from the real agent model runtime, mirroring how\n * `createAgentSession` builds one from `agentDir`. `list` projects the models\n * whose provider auth is configured (the local CLI `--list-models` semantics).\n * `resolve` mirrors local model restoration: the ref must exist in the catalog\n * and its provider must have configured auth; anything else fails with a\n * plain `Error` that the server boundary maps to `invalid_request`.\n *\n * Boundary: the catalog is a startup-time snapshot. Provider auth added while\n * the server runs is not reflected in `list` results (new sessions can still\n * resolve such models, since `resolve` checks auth on demand); hosts needing a\n * fresh catalog rebuild the server.\n */\nfunction createDefaultServerModels(modelRuntime: ModelRuntime): CodingAgentServerModels {\n\treturn {\n\t\tlist: async (): Promise<readonly ModelMetadata[]> => {\n\t\t\tconst available = await modelRuntime.getAvailable();\n\t\t\treturn available.map((model) =>\n\t\t\t\ttoProtocolModelMetadata(model, modelRuntime.hasConfiguredAuth(model.provider)),\n\t\t\t);\n\t\t},\n\t\tresolve: async (ref: ModelRef) => {\n\t\t\tconst model = modelRuntime.getModel(ref.provider, ref.id);\n\t\t\t// checkAuth resolves the provider's configured auth on demand, so\n\t\t\t// resolution does not depend on whether an availability refresh\n\t\t\t// (getAvailable) already populated the auth snapshot.\n\t\t\tconst auth = model === undefined ? undefined : await modelRuntime.checkAuth(ref.provider);\n\t\t\tif (model === undefined || auth === undefined) {\n\t\t\t\tthrow new Error(t(\"Unknown or unavailable model: {provider}/{id}\", { provider: ref.provider, id: ref.id }));\n\t\t\t}\n\t\t\treturn model;\n\t\t},\n\t};\n}\n\n/**\n * Assembles and starts a coding-agent remote server: session source + durable\n * journal + transport listeners behind the public server boundary.\n */\nexport async function startCodingAgentRemoteServer(\n\toptions: StartCodingAgentRemoteServerOptions,\n): Promise<CodingAgentRemoteServerHandle> {\n\tconst sessionSourceOptions: FileSessionSourceOptions | undefined = options.sessionSourceOptions;\n\tconst sessions =\n\t\toptions.sessions ??\n\t\t(sessionSourceOptions === undefined ? undefined : createFileSessionSource(sessionSourceOptions));\n\tif (sessions === undefined) {\n\t\tthrow new Error(t(\"Remote server requires a session source or sessionSourceOptions\"));\n\t}\n\n\t// Default journal domain: the agent config directory the session source\n\t// resolves against (explicit agentDir, else the default agent dir) — never\n\t// the process cwd. Two servers sharing one agentDir therefore share one\n\t// journal for the same sessions, independent of where they were started.\n\tconst agentDir = sessionSourceOptions?.agentDir ?? getAgentDir();\n\tconst journal = new RevisionGatedSessionJournal(\n\t\toptions.journal ??\n\t\t\tnew FileDurableSessionEventJournal(options.journalPath ?? join(agentDir, \"remote-server-journal.jsonl\")),\n\t);\n\t// Default writer identity (D-067 phase 2 S2): stable per agent-dir domain\n\t// (persisted beside the durable log), so a restarted server re-claims its\n\t// own still-live store lease instantly — same writer id = the lease's\n\t// idempotent refresh — instead of being locked out by its dead\n\t// predecessor's TTL. Distinct nodes sharing one store must each pin their\n\t// own writer id via `options.writerId`.\n\tconst writerId = options.writerId ?? readOrCreateWriterId(agentDir);\n\n\t// Default model catalog: build a real runtime from the same agentDir\n\t// domain, mirroring `createAgentSession`'s authPath/modelsPath resolution.\n\tconst models: CodingAgentServerModels =\n\t\toptions.models ??\n\t\tcreateDefaultServerModels(\n\t\t\tawait ModelRuntime.create(\n\t\t\t\tsessionSourceOptions?.agentDir === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tauthPath: join(sessionSourceOptions.agentDir, \"auth.json\"),\n\t\t\t\t\t\t\tmodelsPath: join(sessionSourceOptions.agentDir, \"models.json\"),\n\t\t\t\t\t\t},\n\t\t\t),\n\t\t);\n\n\tconst { server, service } = assembleCodingAgentServer({\n\t\tsessions,\n\t\tmodels,\n\t\tlisteners: options.listeners,\n\t\tjournal,\n\t\t...(options.authenticate === undefined ? {} : { authenticate: options.authenticate }),\n\t\t...(options.authorize === undefined ? {} : { authorize: options.authorize }),\n\t\t...(options.serverId === undefined ? {} : { serverId: options.serverId }),\n\t\t...(options.onError === undefined ? {} : { onError: options.onError }),\n\t\t...(options.durable === undefined ? {} : { durable: options.durable }),\n\t\t...(writerId === undefined ? {} : { writerId }),\n\t\t...(options.operationExecutors === undefined ? {} : { operationExecutors: options.operationExecutors }),\n\t});\n\n\tawait server.start();\n\n\treturn {\n\t\tserver,\n\t\taddresses: server.addresses,\n\t\tclose: async () => {\n\t\t\t// Graceful shutdown releases the store writer lease (D-067 phase 2\n\t\t\t// S2) so a successor process can claim immediately; crash recovery\n\t\t\t// stays the lease-TTL path. Best-effort: shutdown never fails on a\n\t\t\t// release error.\n\t\t\ttry {\n\t\t\t\tservice.releaseWriterLease();\n\t\t\t} catch {\n\t\t\t\t// Release failures surface nowhere at shutdown.\n\t\t\t}\n\t\t\tawait server.close();\n\t\t\tawait journal.close();\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-source.d.ts","sourceRoot":"","sources":["../../src/remote/session-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,8BAA8B,EAAgC,MAAM,sBAAsB,CAAC;AAEzG,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACxC,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,2CAA2C;IAC3C,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C,iUAAiU;IACjU,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE;QAC3B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF;;;;OAIG;IACH,QAAQ,CAAC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IAClD;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,gBAAgB,CAAC;CAC/F;AA8GD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,8BAA8B,CAwDzG","sourcesContent":["/**\n * Production `CodingAgentServerSessionSource` backed by the `SessionManager`\n * file-based persistence and `createAgentSession` from the SDK.\n *\n * Owns the mapping between server descriptors and on-disk `.jsonl` session\n * files. Each `open()` call reconstructs a full `AgentSession` whose messages\n * are rebuilt from the JSONL entries, producing a transcript and durable\n * revision identical to an in-process session.\n *\n * Honest boundary: model runtime, auth, tool suite, and extensions are resolved\n * at `open`/`create` time from the host-provided `agentDir` and the session's\n * own working directory (`descriptor.cwd` at create; the recorded cwd at open,\n * with the host-level fallback for legacy cwd-less files).\n * The source does not cache or pool sessions.\n */\n\nimport { stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { StreamFn } from \"@agent-forge/agent-core\";\nimport type { CredentialStore } from \"@agent-forge/ai\";\nimport type { Api, Model } from \"@agent-forge/ai/compat\";\nimport type { ThinkingLevel } from \"@agent-forge/protocol\";\nimport type { AgentSession } from \"../core/agent-session.ts\";\nimport type { AgentTaskAdapter } from \"../core/extensions/public-api.ts\";\nimport type { HostLogger } from \"../core/logger.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\nimport { createAgentSession } from \"../core/sdk.ts\";\nimport { type SessionInfo, SessionManager } from \"../core/session-manager.ts\";\nimport type { SessionStorageProvider } from \"../core/session-storage.ts\";\nimport type { SettingsManager } from \"../core/settings-manager.ts\";\nimport type { DurableServiceV1 } from \"../durable/durable-service.ts\";\nimport type { CodingAgentServerSessionSource, CodingAgentSessionDescriptor } from \"./server-assembly.ts\";\n\n/** Configuration for a file-backed session source. */\nexport interface FileSessionSourceOptions {\n\t/** Absolute path to the sessions directory containing `.jsonl` files. */\n\treadonly sessionsDir: string;\n\t/**\n\t * Fallback working directory. Opens of legacy session files that recorded\n\t * no cwd (`SessionInfo.cwd` is `\"\"`) run here, and so do creates whose\n\t * descriptor carries no cwd. Sessions always prefer their own cwd:\n\t * `descriptor.cwd` at create, the recorded cwd at open.\n\t */\n\treadonly cwd: string;\n\t/** Absolute path to the agent config directory (defaults to `~/.agent-forge/agent`). */\n\treadonly agentDir?: string;\n\t/** Optional pre-built model runtime; created from `agentDir` when omitted. */\n\treadonly modelRuntime?: ModelRuntime;\n\t/** Optional explicit stream function (faux providers in tests). */\n\treadonly streamFn?: StreamFn;\n\t/** Optional explicit model to attach on creation. */\n\treadonly model?: Model<Api>;\n\t/** Optional thinking level for new sessions. */\n\treadonly thinkingLevel?: ThinkingLevel;\n\t/** Optional pre-built settings manager. */\n\treadonly settingsManager?: SettingsManager;\n\t/** Opt-in workspace boundary: when provided, `create` rejects descriptors whose resolved cwd is not inside one of these roots. The check is purely lexical (`path.resolve` normalization); symlinks are not resolved. Omit for unrestricted local-trust operation; `open` is not gated (it reopens sessions already on disk). */\n\treadonly workspaceRoots?: readonly string[];\n\t/**\n\t * Storage seam for the session records (D-067 phase 1). Defaults to the\n\t * local JSONL file protocol; hosts may inject an alternative provider and\n\t * every session this source builds uses it.\n\t */\n\treadonly storage?: SessionStorageProvider;\n\t/**\n\t * Credential storage for the model runtime each session builds (D-067\n\t * phase 1): forwarded to the default `ModelRuntime` construction. Ignored\n\t * when `modelRuntime` is supplied explicitly. Defaults to the file at\n\t * `<agentDir>/auth.json`.\n\t */\n\treadonly credentials?: CredentialStore;\n\t/**\n\t * Host-process logger forwarded into every session this source builds\n\t * (D-067 phase 1 seam: serve sessions previously had no logger at all —\n\t * the SDK treats an absent logger as an explicit no-op).\n\t */\n\treadonly hostLogger?: HostLogger;\n\t/**\n\t * Durable replay channel for agent task terminal outcomes, forwarded into\n\t * every session this source builds (agent-result-replay-v1). The host owns\n\t * the store and the writer claim; the writerId must be the same one the\n\t * server assembly claims so a single writer serves the whole process.\n\t */\n\treadonly agentTaskResults?: {\n\t\treadonly store: DurableServiceV1;\n\t\treadonly writerId: string;\n\t};\n\t/**\n\t * 本进程自身入口可信(承载退役切片 2):转发给每个会话的装配域,delegate 在未\n\t * 显式配置池且 self-invocation 可解析时自动池化——serve 装配用它给会话一个\n\t * 委派载体。SDK 嵌入方不传则委派面不注册。\n\t */\n\treadonly subagentPoolFromSelfInvocation?: boolean;\n\t/**\n\t * Per-session agent task carrier factory(承载退役切片 2):source 装配的每个\n\t * 会话没有默认子任务 creator;SDK 嵌入方可用它按会话绑定父身份注入 in-process\n\t * 或池化 adapter(生产 serve 走 `subagentPoolFromSelfInvocation`)。\n\t */\n\treadonly createAgentTaskAdapter?: (parent: { readonly sessionId: string }) => AgentTaskAdapter;\n}\n\n/**\n * Maps a `SessionInfo` from `SessionManager.listAll` to a\n * `CodingAgentSessionDescriptor` visible to the server boundary.\n */\nfunction infoToDescriptor(info: SessionInfo): CodingAgentSessionDescriptor {\n\treturn {\n\t\tid: info.id,\n\t\t...(info.name === undefined ? {} : { name: info.name }),\n\t\t// Legacy session files recorded no cwd (empty string); omit the field\n\t\t// like `name` instead of leaking a protocol-invalid empty cwd.\n\t\t...(info.cwd === \"\" ? {} : { cwd: info.cwd }),\n\t\t// Profile lock recorded in the header at creation; omit the keys when\n\t\t// absent so descriptors keep the protocol's optional-field semantics\n\t\t// and reopened-session snapshots echo exactly what was persisted.\n\t\t...(info.profileId === undefined ? {} : { profileId: info.profileId }),\n\t\t...(info.profileVersion === undefined ? {} : { profileVersion: info.profileVersion }),\n\t\tcreatedAt: info.created.getTime(),\n\t\tupdatedAt: info.modified.getTime(),\n\t};\n}\n\n/**\n * Shared logic to reconstruct an `AgentSession` from an existing\n * `SessionManager` instance (used by both `create` and `open`). `cwd` is the\n * session's own working directory — the one the descriptor recorded at create\n * (or the recorded cwd at open) — and drives tool ctx, resource discovery, and\n * the agents.md chain for this session regardless of the host-level fallback.\n * Optional `overrides` carry per-session descriptor values; they win over the\n * host-level `options` defaults.\n */\nasync function buildSession(\n\tsessionManager: SessionManager,\n\toptions: FileSessionSourceOptions,\n\tcwd: string,\n\toverrides?: { readonly model?: Model<Api>; readonly thinkingLevel?: ThinkingLevel },\n): Promise<AgentSession> {\n\tconst model = overrides?.model ?? options.model;\n\tconst thinkingLevel = overrides?.thinkingLevel ?? options.thinkingLevel;\n\tconst { session } = await createAgentSession({\n\t\tcwd,\n\t\t...(options.agentDir === undefined ? {} : { agentDir: options.agentDir }),\n\t\tsessionManager,\n\t\t...(options.modelRuntime === undefined ? {} : { modelRuntime: options.modelRuntime }),\n\t\t...(options.streamFn === undefined ? {} : { streamFn: options.streamFn }),\n\t\t...(model === undefined ? {} : { model }),\n\t\t...(thinkingLevel === undefined ? {} : { thinkingLevel }),\n\t\t...(options.settingsManager === undefined ? {} : { settingsManager: options.settingsManager }),\n\t\t...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n\t\t...(options.hostLogger === undefined ? {} : { hostLogger: options.hostLogger }),\n\t\t...(options.agentTaskResults === undefined ? {} : { agentTaskResults: options.agentTaskResults }),\n\t\t...(options.subagentPoolFromSelfInvocation === undefined\n\t\t\t? {}\n\t\t\t: { subagentPoolFromSelfInvocation: options.subagentPoolFromSelfInvocation }),\n\t\t...(options.createAgentTaskAdapter === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tagentTaskAdapter: options.createAgentTaskAdapter({ sessionId: sessionManager.getSessionId() }),\n\t\t\t\t}),\n\t});\n\treturn session;\n}\n\n/**\n * Enforces the opt-in workspace boundary for `create`. Both the root and the\n * final cwd are resolved first; the cwd is inside when it is the root itself\n * or a descendant. On win32 `path.relative` compares case-insensitively by\n * platform default and yields an absolute path across drive letters, which\n * fails the containment check naturally. Throws a plain `Error` (matching the\n * existing session-source convention) so the server boundary maps it to a\n * request-class protocol error with the original message.\n */\nfunction assertWithinWorkspaceRoots(cwd: string, roots: readonly string[] | undefined): void {\n\tif (roots === undefined) return;\n\tconst resolvedCwd = resolve(cwd);\n\tfor (const root of roots) {\n\t\tconst resolvedRoot = resolve(root);\n\t\tconst rel = relative(resolvedRoot, resolvedCwd);\n\t\t// `rel === \"\"` means the cwd is the root itself, which is allowed. The\n\t\t// escape check is segment-precise so in-root entries that merely start\n\t\t// with \"..\" (e.g. `..foo`) are not mistaken for parent escapes.\n\t\tif (rel === \"\" || (!isAbsolute(rel) && rel !== \"..\" && !rel.startsWith(`..${sep}`))) return;\n\t}\n\tthrow new Error(\n\t\t`cwd \"${resolvedCwd}\" is outside the configured workspace roots: [${roots.map((root) => resolve(root)).join(\", \")}]`,\n\t);\n}\n\n/**\n * `create` targets a fresh session workspace, so a missing or non-directory\n * cwd must fail the create with a clear, path-bearing error instead of\n * producing a session whose tools fail on their first relative access.\n * `open` re-opens sessions already recorded on disk and is not gated. The\n * plain `Error` matches the session-source convention; the server boundary\n * maps it to an `invalid_request` protocol error with the original message.\n */\nasync function assertCwdIsDirectory(cwd: string): Promise<void> {\n\tconst stats = await stat(cwd).catch((error: unknown) => {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t});\n\tif (stats === undefined) {\n\t\tthrow new Error(`Cannot create session: cwd does not exist: ${cwd}`);\n\t}\n\tif (!stats.isDirectory()) {\n\t\tthrow new Error(`Cannot create session: cwd is not a directory: ${cwd}`);\n\t}\n}\n\n/**\n * Creates a production `CodingAgentServerSessionSource` backed by on-disk\n * `.jsonl` session files in `sessionsDir`.\n */\nexport function createFileSessionSource(options: FileSessionSourceOptions): CodingAgentServerSessionSource {\n\tconst sessionsDir = resolve(options.sessionsDir);\n\n\treturn {\n\t\tasync list(): Promise<readonly CodingAgentSessionDescriptor[]> {\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\treturn infos.map(infoToDescriptor);\n\t\t},\n\n\t\t/**\n\t\t * Creates a session in the descriptor cwd (or the host-level fallback).\n\t\t * The final cwd must be inside the configured workspace roots (when\n\t\t * provided) and must exist as a directory; both checks run before any\n\t\t * session file is written, so a rejected create leaves the disk\n\t\t * untouched.\n\t\t */\n\t\tasync create(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// The server boundary rejects cwd-less creates; a direct host call\n\t\t\t// falls back to the host-level cwd like legacy opens.\n\t\t\tconst cwd = descriptor.cwd === undefined || descriptor.cwd === \"\" ? options.cwd : descriptor.cwd;\n\t\t\tassertWithinWorkspaceRoots(cwd, options.workspaceRoots);\n\t\t\tawait assertCwdIsDirectory(cwd);\n\t\t\tconst sm = SessionManager.create(\n\t\t\t\tcwd,\n\t\t\t\tsessionsDir,\n\t\t\t\t{\n\t\t\t\t\tid: descriptor.id,\n\t\t\t\t\t// Creation-time profile lock, persisted into the session header so\n\t\t\t\t\t// it survives restarts (read back via `list`/`open` descriptors).\n\t\t\t\t\t...(descriptor.profileId === undefined ? {} : { profileId: descriptor.profileId }),\n\t\t\t\t\t...(descriptor.profileVersion === undefined ? {} : { profileVersion: descriptor.profileVersion }),\n\t\t\t\t},\n\t\t\t\toptions.storage,\n\t\t\t);\n\t\t\treturn buildSession(sm, options, cwd, {\n\t\t\t\t...(descriptor.model === undefined ? {} : { model: descriptor.model }),\n\t\t\t\t...(descriptor.thinkingLevel === undefined ? {} : { thinkingLevel: descriptor.thinkingLevel }),\n\t\t\t});\n\t\t},\n\n\t\tasync open(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// Re-scan to locate the session file path for the given id.\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\tconst match = infos.find((info) => info.id === descriptor.id);\n\t\t\tif (!match) {\n\t\t\t\tthrow new Error(`Session not found: ${descriptor.id}`);\n\t\t\t}\n\t\t\t// The session file records the cwd it ran in; legacy files may have\n\t\t\t// none (empty string), which falls back to the host-level cwd. The\n\t\t\t// override keeps the SessionManager cwd consistent with the build\n\t\t\t// cwd for consumers of `getCwd()` (extension surface, snapshot).\n\t\t\tconst cwd = match.cwd === \"\" ? options.cwd : match.cwd;\n\t\t\tconst sm = SessionManager.open(match.path, sessionsDir, cwd, options.storage);\n\t\t\treturn buildSession(sm, options, cwd);\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-source.d.ts","sourceRoot":"","sources":["../../src/remote/session-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,8BAA8B,EAAgC,MAAM,sBAAsB,CAAC;AAEzG,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACxC,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,2CAA2C;IAC3C,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C,iUAAiU;IACjU,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,eAAe,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE;QAC3B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF;;;;OAIG;IACH,QAAQ,CAAC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IAClD;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,gBAAgB,CAAC;CAC/F;AAiHD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,8BAA8B,CAwDzG","sourcesContent":["/**\n * Production `CodingAgentServerSessionSource` backed by the `SessionManager`\n * file-based persistence and `createAgentSession` from the SDK.\n *\n * Owns the mapping between server descriptors and on-disk `.jsonl` session\n * files. Each `open()` call reconstructs a full `AgentSession` whose messages\n * are rebuilt from the JSONL entries, producing a transcript and durable\n * revision identical to an in-process session.\n *\n * Honest boundary: model runtime, auth, tool suite, and extensions are resolved\n * at `open`/`create` time from the host-provided `agentDir` and the session's\n * own working directory (`descriptor.cwd` at create; the recorded cwd at open,\n * with the host-level fallback for legacy cwd-less files).\n * The source does not cache or pool sessions.\n */\n\nimport { stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { StreamFn } from \"@agent-forge/agent-core\";\nimport type { CredentialStore } from \"@agent-forge/ai\";\nimport type { Api, Model } from \"@agent-forge/ai/compat\";\nimport type { ThinkingLevel } from \"@agent-forge/protocol\";\nimport type { AgentSession } from \"../core/agent-session.ts\";\nimport type { AgentTaskAdapter } from \"../core/extensions/public-api.ts\";\nimport { t } from \"../core/i18n/index.ts\";\nimport type { HostLogger } from \"../core/logger.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\nimport { createAgentSession } from \"../core/sdk.ts\";\nimport { type SessionInfo, SessionManager } from \"../core/session-manager.ts\";\nimport type { SessionStorageProvider } from \"../core/session-storage.ts\";\nimport type { SettingsManager } from \"../core/settings-manager.ts\";\nimport type { DurableServiceV1 } from \"../durable/durable-service.ts\";\nimport type { CodingAgentServerSessionSource, CodingAgentSessionDescriptor } from \"./server-assembly.ts\";\n\n/** Configuration for a file-backed session source. */\nexport interface FileSessionSourceOptions {\n\t/** Absolute path to the sessions directory containing `.jsonl` files. */\n\treadonly sessionsDir: string;\n\t/**\n\t * Fallback working directory. Opens of legacy session files that recorded\n\t * no cwd (`SessionInfo.cwd` is `\"\"`) run here, and so do creates whose\n\t * descriptor carries no cwd. Sessions always prefer their own cwd:\n\t * `descriptor.cwd` at create, the recorded cwd at open.\n\t */\n\treadonly cwd: string;\n\t/** Absolute path to the agent config directory (defaults to `~/.agent-forge/agent`). */\n\treadonly agentDir?: string;\n\t/** Optional pre-built model runtime; created from `agentDir` when omitted. */\n\treadonly modelRuntime?: ModelRuntime;\n\t/** Optional explicit stream function (faux providers in tests). */\n\treadonly streamFn?: StreamFn;\n\t/** Optional explicit model to attach on creation. */\n\treadonly model?: Model<Api>;\n\t/** Optional thinking level for new sessions. */\n\treadonly thinkingLevel?: ThinkingLevel;\n\t/** Optional pre-built settings manager. */\n\treadonly settingsManager?: SettingsManager;\n\t/** Opt-in workspace boundary: when provided, `create` rejects descriptors whose resolved cwd is not inside one of these roots. The check is purely lexical (`path.resolve` normalization); symlinks are not resolved. Omit for unrestricted local-trust operation; `open` is not gated (it reopens sessions already on disk). */\n\treadonly workspaceRoots?: readonly string[];\n\t/**\n\t * Storage seam for the session records (D-067 phase 1). Defaults to the\n\t * local JSONL file protocol; hosts may inject an alternative provider and\n\t * every session this source builds uses it.\n\t */\n\treadonly storage?: SessionStorageProvider;\n\t/**\n\t * Credential storage for the model runtime each session builds (D-067\n\t * phase 1): forwarded to the default `ModelRuntime` construction. Ignored\n\t * when `modelRuntime` is supplied explicitly. Defaults to the file at\n\t * `<agentDir>/auth.json`.\n\t */\n\treadonly credentials?: CredentialStore;\n\t/**\n\t * Host-process logger forwarded into every session this source builds\n\t * (D-067 phase 1 seam: serve sessions previously had no logger at all —\n\t * the SDK treats an absent logger as an explicit no-op).\n\t */\n\treadonly hostLogger?: HostLogger;\n\t/**\n\t * Durable replay channel for agent task terminal outcomes, forwarded into\n\t * every session this source builds (agent-result-replay-v1). The host owns\n\t * the store and the writer claim; the writerId must be the same one the\n\t * server assembly claims so a single writer serves the whole process.\n\t */\n\treadonly agentTaskResults?: {\n\t\treadonly store: DurableServiceV1;\n\t\treadonly writerId: string;\n\t};\n\t/**\n\t * 本进程自身入口可信(承载退役切片 2):转发给每个会话的装配域,delegate 在未\n\t * 显式配置池且 self-invocation 可解析时自动池化——serve 装配用它给会话一个\n\t * 委派载体。SDK 嵌入方不传则委派面不注册。\n\t */\n\treadonly subagentPoolFromSelfInvocation?: boolean;\n\t/**\n\t * Per-session agent task carrier factory(承载退役切片 2):source 装配的每个\n\t * 会话没有默认子任务 creator;SDK 嵌入方可用它按会话绑定父身份注入 in-process\n\t * 或池化 adapter(生产 serve 走 `subagentPoolFromSelfInvocation`)。\n\t */\n\treadonly createAgentTaskAdapter?: (parent: { readonly sessionId: string }) => AgentTaskAdapter;\n}\n\n/**\n * Maps a `SessionInfo` from `SessionManager.listAll` to a\n * `CodingAgentSessionDescriptor` visible to the server boundary.\n */\nfunction infoToDescriptor(info: SessionInfo): CodingAgentSessionDescriptor {\n\treturn {\n\t\tid: info.id,\n\t\t...(info.name === undefined ? {} : { name: info.name }),\n\t\t// Legacy session files recorded no cwd (empty string); omit the field\n\t\t// like `name` instead of leaking a protocol-invalid empty cwd.\n\t\t...(info.cwd === \"\" ? {} : { cwd: info.cwd }),\n\t\t// Profile lock recorded in the header at creation; omit the keys when\n\t\t// absent so descriptors keep the protocol's optional-field semantics\n\t\t// and reopened-session snapshots echo exactly what was persisted.\n\t\t...(info.profileId === undefined ? {} : { profileId: info.profileId }),\n\t\t...(info.profileVersion === undefined ? {} : { profileVersion: info.profileVersion }),\n\t\tcreatedAt: info.created.getTime(),\n\t\tupdatedAt: info.modified.getTime(),\n\t};\n}\n\n/**\n * Shared logic to reconstruct an `AgentSession` from an existing\n * `SessionManager` instance (used by both `create` and `open`). `cwd` is the\n * session's own working directory — the one the descriptor recorded at create\n * (or the recorded cwd at open) — and drives tool ctx, resource discovery, and\n * the agents.md chain for this session regardless of the host-level fallback.\n * Optional `overrides` carry per-session descriptor values; they win over the\n * host-level `options` defaults.\n */\nasync function buildSession(\n\tsessionManager: SessionManager,\n\toptions: FileSessionSourceOptions,\n\tcwd: string,\n\toverrides?: { readonly model?: Model<Api>; readonly thinkingLevel?: ThinkingLevel },\n): Promise<AgentSession> {\n\tconst model = overrides?.model ?? options.model;\n\tconst thinkingLevel = overrides?.thinkingLevel ?? options.thinkingLevel;\n\tconst { session } = await createAgentSession({\n\t\tcwd,\n\t\t...(options.agentDir === undefined ? {} : { agentDir: options.agentDir }),\n\t\tsessionManager,\n\t\t...(options.modelRuntime === undefined ? {} : { modelRuntime: options.modelRuntime }),\n\t\t...(options.streamFn === undefined ? {} : { streamFn: options.streamFn }),\n\t\t...(model === undefined ? {} : { model }),\n\t\t...(thinkingLevel === undefined ? {} : { thinkingLevel }),\n\t\t...(options.settingsManager === undefined ? {} : { settingsManager: options.settingsManager }),\n\t\t...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n\t\t...(options.hostLogger === undefined ? {} : { hostLogger: options.hostLogger }),\n\t\t...(options.agentTaskResults === undefined ? {} : { agentTaskResults: options.agentTaskResults }),\n\t\t...(options.subagentPoolFromSelfInvocation === undefined\n\t\t\t? {}\n\t\t\t: { subagentPoolFromSelfInvocation: options.subagentPoolFromSelfInvocation }),\n\t\t...(options.createAgentTaskAdapter === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tagentTaskAdapter: options.createAgentTaskAdapter({ sessionId: sessionManager.getSessionId() }),\n\t\t\t\t}),\n\t});\n\treturn session;\n}\n\n/**\n * Enforces the opt-in workspace boundary for `create`. Both the root and the\n * final cwd are resolved first; the cwd is inside when it is the root itself\n * or a descendant. On win32 `path.relative` compares case-insensitively by\n * platform default and yields an absolute path across drive letters, which\n * fails the containment check naturally. Throws a plain `Error` (matching the\n * existing session-source convention) so the server boundary maps it to a\n * request-class protocol error with the original message.\n */\nfunction assertWithinWorkspaceRoots(cwd: string, roots: readonly string[] | undefined): void {\n\tif (roots === undefined) return;\n\tconst resolvedCwd = resolve(cwd);\n\tfor (const root of roots) {\n\t\tconst resolvedRoot = resolve(root);\n\t\tconst rel = relative(resolvedRoot, resolvedCwd);\n\t\t// `rel === \"\"` means the cwd is the root itself, which is allowed. The\n\t\t// escape check is segment-precise so in-root entries that merely start\n\t\t// with \"..\" (e.g. `..foo`) are not mistaken for parent escapes.\n\t\tif (rel === \"\" || (!isAbsolute(rel) && rel !== \"..\" && !rel.startsWith(`..${sep}`))) return;\n\t}\n\tthrow new Error(\n\t\tt('cwd \"{cwd}\" is outside the configured workspace roots: [{roots}]', {\n\t\t\tcwd: resolvedCwd,\n\t\t\troots: roots.map((root) => resolve(root)).join(\", \"),\n\t\t}),\n\t);\n}\n\n/**\n * `create` targets a fresh session workspace, so a missing or non-directory\n * cwd must fail the create with a clear, path-bearing error instead of\n * producing a session whose tools fail on their first relative access.\n * `open` re-opens sessions already recorded on disk and is not gated. The\n * plain `Error` matches the session-source convention; the server boundary\n * maps it to an `invalid_request` protocol error with the original message.\n */\nasync function assertCwdIsDirectory(cwd: string): Promise<void> {\n\tconst stats = await stat(cwd).catch((error: unknown) => {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t});\n\tif (stats === undefined) {\n\t\tthrow new Error(t(\"Cannot create session: cwd does not exist: {cwd}\", { cwd }));\n\t}\n\tif (!stats.isDirectory()) {\n\t\tthrow new Error(t(\"Cannot create session: cwd is not a directory: {cwd}\", { cwd }));\n\t}\n}\n\n/**\n * Creates a production `CodingAgentServerSessionSource` backed by on-disk\n * `.jsonl` session files in `sessionsDir`.\n */\nexport function createFileSessionSource(options: FileSessionSourceOptions): CodingAgentServerSessionSource {\n\tconst sessionsDir = resolve(options.sessionsDir);\n\n\treturn {\n\t\tasync list(): Promise<readonly CodingAgentSessionDescriptor[]> {\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\treturn infos.map(infoToDescriptor);\n\t\t},\n\n\t\t/**\n\t\t * Creates a session in the descriptor cwd (or the host-level fallback).\n\t\t * The final cwd must be inside the configured workspace roots (when\n\t\t * provided) and must exist as a directory; both checks run before any\n\t\t * session file is written, so a rejected create leaves the disk\n\t\t * untouched.\n\t\t */\n\t\tasync create(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// The server boundary rejects cwd-less creates; a direct host call\n\t\t\t// falls back to the host-level cwd like legacy opens.\n\t\t\tconst cwd = descriptor.cwd === undefined || descriptor.cwd === \"\" ? options.cwd : descriptor.cwd;\n\t\t\tassertWithinWorkspaceRoots(cwd, options.workspaceRoots);\n\t\t\tawait assertCwdIsDirectory(cwd);\n\t\t\tconst sm = SessionManager.create(\n\t\t\t\tcwd,\n\t\t\t\tsessionsDir,\n\t\t\t\t{\n\t\t\t\t\tid: descriptor.id,\n\t\t\t\t\t// Creation-time profile lock, persisted into the session header so\n\t\t\t\t\t// it survives restarts (read back via `list`/`open` descriptors).\n\t\t\t\t\t...(descriptor.profileId === undefined ? {} : { profileId: descriptor.profileId }),\n\t\t\t\t\t...(descriptor.profileVersion === undefined ? {} : { profileVersion: descriptor.profileVersion }),\n\t\t\t\t},\n\t\t\t\toptions.storage,\n\t\t\t);\n\t\t\treturn buildSession(sm, options, cwd, {\n\t\t\t\t...(descriptor.model === undefined ? {} : { model: descriptor.model }),\n\t\t\t\t...(descriptor.thinkingLevel === undefined ? {} : { thinkingLevel: descriptor.thinkingLevel }),\n\t\t\t});\n\t\t},\n\n\t\tasync open(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// Re-scan to locate the session file path for the given id.\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\tconst match = infos.find((info) => info.id === descriptor.id);\n\t\t\tif (!match) {\n\t\t\t\tthrow new Error(t(\"Session not found: {id}\", { id: descriptor.id }));\n\t\t\t}\n\t\t\t// The session file records the cwd it ran in; legacy files may have\n\t\t\t// none (empty string), which falls back to the host-level cwd. The\n\t\t\t// override keeps the SessionManager cwd consistent with the build\n\t\t\t// cwd for consumers of `getCwd()` (extension surface, snapshot).\n\t\t\tconst cwd = match.cwd === \"\" ? options.cwd : match.cwd;\n\t\t\tconst sm = SessionManager.open(match.path, sessionsDir, cwd, options.storage);\n\t\t\treturn buildSession(sm, options, cwd);\n\t\t},\n\t};\n}\n"]}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { stat } from "node:fs/promises";
|
|
17
17
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
18
|
+
import { t } from "../core/i18n/index.js";
|
|
18
19
|
import { createAgentSession } from "../core/sdk.js";
|
|
19
20
|
import { SessionManager } from "../core/session-manager.js";
|
|
20
21
|
/**
|
|
@@ -94,7 +95,10 @@ function assertWithinWorkspaceRoots(cwd, roots) {
|
|
|
94
95
|
if (rel === "" || (!isAbsolute(rel) && rel !== ".." && !rel.startsWith(`..${sep}`)))
|
|
95
96
|
return;
|
|
96
97
|
}
|
|
97
|
-
throw new Error(
|
|
98
|
+
throw new Error(t('cwd "{cwd}" is outside the configured workspace roots: [{roots}]', {
|
|
99
|
+
cwd: resolvedCwd,
|
|
100
|
+
roots: roots.map((root) => resolve(root)).join(", "),
|
|
101
|
+
}));
|
|
98
102
|
}
|
|
99
103
|
/**
|
|
100
104
|
* `create` targets a fresh session workspace, so a missing or non-directory
|
|
@@ -111,10 +115,10 @@ async function assertCwdIsDirectory(cwd) {
|
|
|
111
115
|
throw error;
|
|
112
116
|
});
|
|
113
117
|
if (stats === undefined) {
|
|
114
|
-
throw new Error(
|
|
118
|
+
throw new Error(t("Cannot create session: cwd does not exist: {cwd}", { cwd }));
|
|
115
119
|
}
|
|
116
120
|
if (!stats.isDirectory()) {
|
|
117
|
-
throw new Error(
|
|
121
|
+
throw new Error(t("Cannot create session: cwd is not a directory: {cwd}", { cwd }));
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
/**
|
|
@@ -158,7 +162,7 @@ export function createFileSessionSource(options) {
|
|
|
158
162
|
const infos = await SessionManager.listAll(sessionsDir);
|
|
159
163
|
const match = infos.find((info) => info.id === descriptor.id);
|
|
160
164
|
if (!match) {
|
|
161
|
-
throw new Error(
|
|
165
|
+
throw new Error(t("Session not found: {id}", { id: descriptor.id }));
|
|
162
166
|
}
|
|
163
167
|
// The session file records the cwd it ran in; legacy files may have
|
|
164
168
|
// none (empty string), which falls back to the host-level cwd. The
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-source.js","sourceRoot":"","sources":["../../src/remote/session-source.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Production `CodingAgentServerSessionSource` backed by the `SessionManager`\n * file-based persistence and `createAgentSession` from the SDK.\n *\n * Owns the mapping between server descriptors and on-disk `.jsonl` session\n * files. Each `open()` call reconstructs a full `AgentSession` whose messages\n * are rebuilt from the JSONL entries, producing a transcript and durable\n * revision identical to an in-process session.\n *\n * Honest boundary: model runtime, auth, tool suite, and extensions are resolved\n * at `open`/`create` time from the host-provided `agentDir` and the session's\n * own working directory (`descriptor.cwd` at create; the recorded cwd at open,\n * with the host-level fallback for legacy cwd-less files).\n * The source does not cache or pool sessions.\n */\n\nimport { stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { StreamFn } from \"@agent-forge/agent-core\";\nimport type { CredentialStore } from \"@agent-forge/ai\";\nimport type { Api, Model } from \"@agent-forge/ai/compat\";\nimport type { ThinkingLevel } from \"@agent-forge/protocol\";\nimport type { AgentSession } from \"../core/agent-session.ts\";\nimport type { AgentTaskAdapter } from \"../core/extensions/public-api.ts\";\nimport type { HostLogger } from \"../core/logger.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\nimport { createAgentSession } from \"../core/sdk.ts\";\nimport { type SessionInfo, SessionManager } from \"../core/session-manager.ts\";\nimport type { SessionStorageProvider } from \"../core/session-storage.ts\";\nimport type { SettingsManager } from \"../core/settings-manager.ts\";\nimport type { DurableServiceV1 } from \"../durable/durable-service.ts\";\nimport type { CodingAgentServerSessionSource, CodingAgentSessionDescriptor } from \"./server-assembly.ts\";\n\n/** Configuration for a file-backed session source. */\nexport interface FileSessionSourceOptions {\n\t/** Absolute path to the sessions directory containing `.jsonl` files. */\n\treadonly sessionsDir: string;\n\t/**\n\t * Fallback working directory. Opens of legacy session files that recorded\n\t * no cwd (`SessionInfo.cwd` is `\"\"`) run here, and so do creates whose\n\t * descriptor carries no cwd. Sessions always prefer their own cwd:\n\t * `descriptor.cwd` at create, the recorded cwd at open.\n\t */\n\treadonly cwd: string;\n\t/** Absolute path to the agent config directory (defaults to `~/.agent-forge/agent`). */\n\treadonly agentDir?: string;\n\t/** Optional pre-built model runtime; created from `agentDir` when omitted. */\n\treadonly modelRuntime?: ModelRuntime;\n\t/** Optional explicit stream function (faux providers in tests). */\n\treadonly streamFn?: StreamFn;\n\t/** Optional explicit model to attach on creation. */\n\treadonly model?: Model<Api>;\n\t/** Optional thinking level for new sessions. */\n\treadonly thinkingLevel?: ThinkingLevel;\n\t/** Optional pre-built settings manager. */\n\treadonly settingsManager?: SettingsManager;\n\t/** Opt-in workspace boundary: when provided, `create` rejects descriptors whose resolved cwd is not inside one of these roots. The check is purely lexical (`path.resolve` normalization); symlinks are not resolved. Omit for unrestricted local-trust operation; `open` is not gated (it reopens sessions already on disk). */\n\treadonly workspaceRoots?: readonly string[];\n\t/**\n\t * Storage seam for the session records (D-067 phase 1). Defaults to the\n\t * local JSONL file protocol; hosts may inject an alternative provider and\n\t * every session this source builds uses it.\n\t */\n\treadonly storage?: SessionStorageProvider;\n\t/**\n\t * Credential storage for the model runtime each session builds (D-067\n\t * phase 1): forwarded to the default `ModelRuntime` construction. Ignored\n\t * when `modelRuntime` is supplied explicitly. Defaults to the file at\n\t * `<agentDir>/auth.json`.\n\t */\n\treadonly credentials?: CredentialStore;\n\t/**\n\t * Host-process logger forwarded into every session this source builds\n\t * (D-067 phase 1 seam: serve sessions previously had no logger at all —\n\t * the SDK treats an absent logger as an explicit no-op).\n\t */\n\treadonly hostLogger?: HostLogger;\n\t/**\n\t * Durable replay channel for agent task terminal outcomes, forwarded into\n\t * every session this source builds (agent-result-replay-v1). The host owns\n\t * the store and the writer claim; the writerId must be the same one the\n\t * server assembly claims so a single writer serves the whole process.\n\t */\n\treadonly agentTaskResults?: {\n\t\treadonly store: DurableServiceV1;\n\t\treadonly writerId: string;\n\t};\n\t/**\n\t * 本进程自身入口可信(承载退役切片 2):转发给每个会话的装配域,delegate 在未\n\t * 显式配置池且 self-invocation 可解析时自动池化——serve 装配用它给会话一个\n\t * 委派载体。SDK 嵌入方不传则委派面不注册。\n\t */\n\treadonly subagentPoolFromSelfInvocation?: boolean;\n\t/**\n\t * Per-session agent task carrier factory(承载退役切片 2):source 装配的每个\n\t * 会话没有默认子任务 creator;SDK 嵌入方可用它按会话绑定父身份注入 in-process\n\t * 或池化 adapter(生产 serve 走 `subagentPoolFromSelfInvocation`)。\n\t */\n\treadonly createAgentTaskAdapter?: (parent: { readonly sessionId: string }) => AgentTaskAdapter;\n}\n\n/**\n * Maps a `SessionInfo` from `SessionManager.listAll` to a\n * `CodingAgentSessionDescriptor` visible to the server boundary.\n */\nfunction infoToDescriptor(info: SessionInfo): CodingAgentSessionDescriptor {\n\treturn {\n\t\tid: info.id,\n\t\t...(info.name === undefined ? {} : { name: info.name }),\n\t\t// Legacy session files recorded no cwd (empty string); omit the field\n\t\t// like `name` instead of leaking a protocol-invalid empty cwd.\n\t\t...(info.cwd === \"\" ? {} : { cwd: info.cwd }),\n\t\t// Profile lock recorded in the header at creation; omit the keys when\n\t\t// absent so descriptors keep the protocol's optional-field semantics\n\t\t// and reopened-session snapshots echo exactly what was persisted.\n\t\t...(info.profileId === undefined ? {} : { profileId: info.profileId }),\n\t\t...(info.profileVersion === undefined ? {} : { profileVersion: info.profileVersion }),\n\t\tcreatedAt: info.created.getTime(),\n\t\tupdatedAt: info.modified.getTime(),\n\t};\n}\n\n/**\n * Shared logic to reconstruct an `AgentSession` from an existing\n * `SessionManager` instance (used by both `create` and `open`). `cwd` is the\n * session's own working directory — the one the descriptor recorded at create\n * (or the recorded cwd at open) — and drives tool ctx, resource discovery, and\n * the agents.md chain for this session regardless of the host-level fallback.\n * Optional `overrides` carry per-session descriptor values; they win over the\n * host-level `options` defaults.\n */\nasync function buildSession(\n\tsessionManager: SessionManager,\n\toptions: FileSessionSourceOptions,\n\tcwd: string,\n\toverrides?: { readonly model?: Model<Api>; readonly thinkingLevel?: ThinkingLevel },\n): Promise<AgentSession> {\n\tconst model = overrides?.model ?? options.model;\n\tconst thinkingLevel = overrides?.thinkingLevel ?? options.thinkingLevel;\n\tconst { session } = await createAgentSession({\n\t\tcwd,\n\t\t...(options.agentDir === undefined ? {} : { agentDir: options.agentDir }),\n\t\tsessionManager,\n\t\t...(options.modelRuntime === undefined ? {} : { modelRuntime: options.modelRuntime }),\n\t\t...(options.streamFn === undefined ? {} : { streamFn: options.streamFn }),\n\t\t...(model === undefined ? {} : { model }),\n\t\t...(thinkingLevel === undefined ? {} : { thinkingLevel }),\n\t\t...(options.settingsManager === undefined ? {} : { settingsManager: options.settingsManager }),\n\t\t...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n\t\t...(options.hostLogger === undefined ? {} : { hostLogger: options.hostLogger }),\n\t\t...(options.agentTaskResults === undefined ? {} : { agentTaskResults: options.agentTaskResults }),\n\t\t...(options.subagentPoolFromSelfInvocation === undefined\n\t\t\t? {}\n\t\t\t: { subagentPoolFromSelfInvocation: options.subagentPoolFromSelfInvocation }),\n\t\t...(options.createAgentTaskAdapter === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tagentTaskAdapter: options.createAgentTaskAdapter({ sessionId: sessionManager.getSessionId() }),\n\t\t\t\t}),\n\t});\n\treturn session;\n}\n\n/**\n * Enforces the opt-in workspace boundary for `create`. Both the root and the\n * final cwd are resolved first; the cwd is inside when it is the root itself\n * or a descendant. On win32 `path.relative` compares case-insensitively by\n * platform default and yields an absolute path across drive letters, which\n * fails the containment check naturally. Throws a plain `Error` (matching the\n * existing session-source convention) so the server boundary maps it to a\n * request-class protocol error with the original message.\n */\nfunction assertWithinWorkspaceRoots(cwd: string, roots: readonly string[] | undefined): void {\n\tif (roots === undefined) return;\n\tconst resolvedCwd = resolve(cwd);\n\tfor (const root of roots) {\n\t\tconst resolvedRoot = resolve(root);\n\t\tconst rel = relative(resolvedRoot, resolvedCwd);\n\t\t// `rel === \"\"` means the cwd is the root itself, which is allowed. The\n\t\t// escape check is segment-precise so in-root entries that merely start\n\t\t// with \"..\" (e.g. `..foo`) are not mistaken for parent escapes.\n\t\tif (rel === \"\" || (!isAbsolute(rel) && rel !== \"..\" && !rel.startsWith(`..${sep}`))) return;\n\t}\n\tthrow new Error(\n\t\t`cwd \"${resolvedCwd}\" is outside the configured workspace roots: [${roots.map((root) => resolve(root)).join(\", \")}]`,\n\t);\n}\n\n/**\n * `create` targets a fresh session workspace, so a missing or non-directory\n * cwd must fail the create with a clear, path-bearing error instead of\n * producing a session whose tools fail on their first relative access.\n * `open` re-opens sessions already recorded on disk and is not gated. The\n * plain `Error` matches the session-source convention; the server boundary\n * maps it to an `invalid_request` protocol error with the original message.\n */\nasync function assertCwdIsDirectory(cwd: string): Promise<void> {\n\tconst stats = await stat(cwd).catch((error: unknown) => {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t});\n\tif (stats === undefined) {\n\t\tthrow new Error(`Cannot create session: cwd does not exist: ${cwd}`);\n\t}\n\tif (!stats.isDirectory()) {\n\t\tthrow new Error(`Cannot create session: cwd is not a directory: ${cwd}`);\n\t}\n}\n\n/**\n * Creates a production `CodingAgentServerSessionSource` backed by on-disk\n * `.jsonl` session files in `sessionsDir`.\n */\nexport function createFileSessionSource(options: FileSessionSourceOptions): CodingAgentServerSessionSource {\n\tconst sessionsDir = resolve(options.sessionsDir);\n\n\treturn {\n\t\tasync list(): Promise<readonly CodingAgentSessionDescriptor[]> {\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\treturn infos.map(infoToDescriptor);\n\t\t},\n\n\t\t/**\n\t\t * Creates a session in the descriptor cwd (or the host-level fallback).\n\t\t * The final cwd must be inside the configured workspace roots (when\n\t\t * provided) and must exist as a directory; both checks run before any\n\t\t * session file is written, so a rejected create leaves the disk\n\t\t * untouched.\n\t\t */\n\t\tasync create(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// The server boundary rejects cwd-less creates; a direct host call\n\t\t\t// falls back to the host-level cwd like legacy opens.\n\t\t\tconst cwd = descriptor.cwd === undefined || descriptor.cwd === \"\" ? options.cwd : descriptor.cwd;\n\t\t\tassertWithinWorkspaceRoots(cwd, options.workspaceRoots);\n\t\t\tawait assertCwdIsDirectory(cwd);\n\t\t\tconst sm = SessionManager.create(\n\t\t\t\tcwd,\n\t\t\t\tsessionsDir,\n\t\t\t\t{\n\t\t\t\t\tid: descriptor.id,\n\t\t\t\t\t// Creation-time profile lock, persisted into the session header so\n\t\t\t\t\t// it survives restarts (read back via `list`/`open` descriptors).\n\t\t\t\t\t...(descriptor.profileId === undefined ? {} : { profileId: descriptor.profileId }),\n\t\t\t\t\t...(descriptor.profileVersion === undefined ? {} : { profileVersion: descriptor.profileVersion }),\n\t\t\t\t},\n\t\t\t\toptions.storage,\n\t\t\t);\n\t\t\treturn buildSession(sm, options, cwd, {\n\t\t\t\t...(descriptor.model === undefined ? {} : { model: descriptor.model }),\n\t\t\t\t...(descriptor.thinkingLevel === undefined ? {} : { thinkingLevel: descriptor.thinkingLevel }),\n\t\t\t});\n\t\t},\n\n\t\tasync open(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// Re-scan to locate the session file path for the given id.\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\tconst match = infos.find((info) => info.id === descriptor.id);\n\t\t\tif (!match) {\n\t\t\t\tthrow new Error(`Session not found: ${descriptor.id}`);\n\t\t\t}\n\t\t\t// The session file records the cwd it ran in; legacy files may have\n\t\t\t// none (empty string), which falls back to the host-level cwd. The\n\t\t\t// override keeps the SessionManager cwd consistent with the build\n\t\t\t// cwd for consumers of `getCwd()` (extension surface, snapshot).\n\t\t\tconst cwd = match.cwd === \"\" ? options.cwd : match.cwd;\n\t\t\tconst sm = SessionManager.open(match.path, sessionsDir, cwd, options.storage);\n\t\t\treturn buildSession(sm, options, cwd);\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-source.js","sourceRoot":"","sources":["../../src/remote/session-source.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Production `CodingAgentServerSessionSource` backed by the `SessionManager`\n * file-based persistence and `createAgentSession` from the SDK.\n *\n * Owns the mapping between server descriptors and on-disk `.jsonl` session\n * files. Each `open()` call reconstructs a full `AgentSession` whose messages\n * are rebuilt from the JSONL entries, producing a transcript and durable\n * revision identical to an in-process session.\n *\n * Honest boundary: model runtime, auth, tool suite, and extensions are resolved\n * at `open`/`create` time from the host-provided `agentDir` and the session's\n * own working directory (`descriptor.cwd` at create; the recorded cwd at open,\n * with the host-level fallback for legacy cwd-less files).\n * The source does not cache or pool sessions.\n */\n\nimport { stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { StreamFn } from \"@agent-forge/agent-core\";\nimport type { CredentialStore } from \"@agent-forge/ai\";\nimport type { Api, Model } from \"@agent-forge/ai/compat\";\nimport type { ThinkingLevel } from \"@agent-forge/protocol\";\nimport type { AgentSession } from \"../core/agent-session.ts\";\nimport type { AgentTaskAdapter } from \"../core/extensions/public-api.ts\";\nimport { t } from \"../core/i18n/index.ts\";\nimport type { HostLogger } from \"../core/logger.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\nimport { createAgentSession } from \"../core/sdk.ts\";\nimport { type SessionInfo, SessionManager } from \"../core/session-manager.ts\";\nimport type { SessionStorageProvider } from \"../core/session-storage.ts\";\nimport type { SettingsManager } from \"../core/settings-manager.ts\";\nimport type { DurableServiceV1 } from \"../durable/durable-service.ts\";\nimport type { CodingAgentServerSessionSource, CodingAgentSessionDescriptor } from \"./server-assembly.ts\";\n\n/** Configuration for a file-backed session source. */\nexport interface FileSessionSourceOptions {\n\t/** Absolute path to the sessions directory containing `.jsonl` files. */\n\treadonly sessionsDir: string;\n\t/**\n\t * Fallback working directory. Opens of legacy session files that recorded\n\t * no cwd (`SessionInfo.cwd` is `\"\"`) run here, and so do creates whose\n\t * descriptor carries no cwd. Sessions always prefer their own cwd:\n\t * `descriptor.cwd` at create, the recorded cwd at open.\n\t */\n\treadonly cwd: string;\n\t/** Absolute path to the agent config directory (defaults to `~/.agent-forge/agent`). */\n\treadonly agentDir?: string;\n\t/** Optional pre-built model runtime; created from `agentDir` when omitted. */\n\treadonly modelRuntime?: ModelRuntime;\n\t/** Optional explicit stream function (faux providers in tests). */\n\treadonly streamFn?: StreamFn;\n\t/** Optional explicit model to attach on creation. */\n\treadonly model?: Model<Api>;\n\t/** Optional thinking level for new sessions. */\n\treadonly thinkingLevel?: ThinkingLevel;\n\t/** Optional pre-built settings manager. */\n\treadonly settingsManager?: SettingsManager;\n\t/** Opt-in workspace boundary: when provided, `create` rejects descriptors whose resolved cwd is not inside one of these roots. The check is purely lexical (`path.resolve` normalization); symlinks are not resolved. Omit for unrestricted local-trust operation; `open` is not gated (it reopens sessions already on disk). */\n\treadonly workspaceRoots?: readonly string[];\n\t/**\n\t * Storage seam for the session records (D-067 phase 1). Defaults to the\n\t * local JSONL file protocol; hosts may inject an alternative provider and\n\t * every session this source builds uses it.\n\t */\n\treadonly storage?: SessionStorageProvider;\n\t/**\n\t * Credential storage for the model runtime each session builds (D-067\n\t * phase 1): forwarded to the default `ModelRuntime` construction. Ignored\n\t * when `modelRuntime` is supplied explicitly. Defaults to the file at\n\t * `<agentDir>/auth.json`.\n\t */\n\treadonly credentials?: CredentialStore;\n\t/**\n\t * Host-process logger forwarded into every session this source builds\n\t * (D-067 phase 1 seam: serve sessions previously had no logger at all —\n\t * the SDK treats an absent logger as an explicit no-op).\n\t */\n\treadonly hostLogger?: HostLogger;\n\t/**\n\t * Durable replay channel for agent task terminal outcomes, forwarded into\n\t * every session this source builds (agent-result-replay-v1). The host owns\n\t * the store and the writer claim; the writerId must be the same one the\n\t * server assembly claims so a single writer serves the whole process.\n\t */\n\treadonly agentTaskResults?: {\n\t\treadonly store: DurableServiceV1;\n\t\treadonly writerId: string;\n\t};\n\t/**\n\t * 本进程自身入口可信(承载退役切片 2):转发给每个会话的装配域,delegate 在未\n\t * 显式配置池且 self-invocation 可解析时自动池化——serve 装配用它给会话一个\n\t * 委派载体。SDK 嵌入方不传则委派面不注册。\n\t */\n\treadonly subagentPoolFromSelfInvocation?: boolean;\n\t/**\n\t * Per-session agent task carrier factory(承载退役切片 2):source 装配的每个\n\t * 会话没有默认子任务 creator;SDK 嵌入方可用它按会话绑定父身份注入 in-process\n\t * 或池化 adapter(生产 serve 走 `subagentPoolFromSelfInvocation`)。\n\t */\n\treadonly createAgentTaskAdapter?: (parent: { readonly sessionId: string }) => AgentTaskAdapter;\n}\n\n/**\n * Maps a `SessionInfo` from `SessionManager.listAll` to a\n * `CodingAgentSessionDescriptor` visible to the server boundary.\n */\nfunction infoToDescriptor(info: SessionInfo): CodingAgentSessionDescriptor {\n\treturn {\n\t\tid: info.id,\n\t\t...(info.name === undefined ? {} : { name: info.name }),\n\t\t// Legacy session files recorded no cwd (empty string); omit the field\n\t\t// like `name` instead of leaking a protocol-invalid empty cwd.\n\t\t...(info.cwd === \"\" ? {} : { cwd: info.cwd }),\n\t\t// Profile lock recorded in the header at creation; omit the keys when\n\t\t// absent so descriptors keep the protocol's optional-field semantics\n\t\t// and reopened-session snapshots echo exactly what was persisted.\n\t\t...(info.profileId === undefined ? {} : { profileId: info.profileId }),\n\t\t...(info.profileVersion === undefined ? {} : { profileVersion: info.profileVersion }),\n\t\tcreatedAt: info.created.getTime(),\n\t\tupdatedAt: info.modified.getTime(),\n\t};\n}\n\n/**\n * Shared logic to reconstruct an `AgentSession` from an existing\n * `SessionManager` instance (used by both `create` and `open`). `cwd` is the\n * session's own working directory — the one the descriptor recorded at create\n * (or the recorded cwd at open) — and drives tool ctx, resource discovery, and\n * the agents.md chain for this session regardless of the host-level fallback.\n * Optional `overrides` carry per-session descriptor values; they win over the\n * host-level `options` defaults.\n */\nasync function buildSession(\n\tsessionManager: SessionManager,\n\toptions: FileSessionSourceOptions,\n\tcwd: string,\n\toverrides?: { readonly model?: Model<Api>; readonly thinkingLevel?: ThinkingLevel },\n): Promise<AgentSession> {\n\tconst model = overrides?.model ?? options.model;\n\tconst thinkingLevel = overrides?.thinkingLevel ?? options.thinkingLevel;\n\tconst { session } = await createAgentSession({\n\t\tcwd,\n\t\t...(options.agentDir === undefined ? {} : { agentDir: options.agentDir }),\n\t\tsessionManager,\n\t\t...(options.modelRuntime === undefined ? {} : { modelRuntime: options.modelRuntime }),\n\t\t...(options.streamFn === undefined ? {} : { streamFn: options.streamFn }),\n\t\t...(model === undefined ? {} : { model }),\n\t\t...(thinkingLevel === undefined ? {} : { thinkingLevel }),\n\t\t...(options.settingsManager === undefined ? {} : { settingsManager: options.settingsManager }),\n\t\t...(options.credentials === undefined ? {} : { credentials: options.credentials }),\n\t\t...(options.hostLogger === undefined ? {} : { hostLogger: options.hostLogger }),\n\t\t...(options.agentTaskResults === undefined ? {} : { agentTaskResults: options.agentTaskResults }),\n\t\t...(options.subagentPoolFromSelfInvocation === undefined\n\t\t\t? {}\n\t\t\t: { subagentPoolFromSelfInvocation: options.subagentPoolFromSelfInvocation }),\n\t\t...(options.createAgentTaskAdapter === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tagentTaskAdapter: options.createAgentTaskAdapter({ sessionId: sessionManager.getSessionId() }),\n\t\t\t\t}),\n\t});\n\treturn session;\n}\n\n/**\n * Enforces the opt-in workspace boundary for `create`. Both the root and the\n * final cwd are resolved first; the cwd is inside when it is the root itself\n * or a descendant. On win32 `path.relative` compares case-insensitively by\n * platform default and yields an absolute path across drive letters, which\n * fails the containment check naturally. Throws a plain `Error` (matching the\n * existing session-source convention) so the server boundary maps it to a\n * request-class protocol error with the original message.\n */\nfunction assertWithinWorkspaceRoots(cwd: string, roots: readonly string[] | undefined): void {\n\tif (roots === undefined) return;\n\tconst resolvedCwd = resolve(cwd);\n\tfor (const root of roots) {\n\t\tconst resolvedRoot = resolve(root);\n\t\tconst rel = relative(resolvedRoot, resolvedCwd);\n\t\t// `rel === \"\"` means the cwd is the root itself, which is allowed. The\n\t\t// escape check is segment-precise so in-root entries that merely start\n\t\t// with \"..\" (e.g. `..foo`) are not mistaken for parent escapes.\n\t\tif (rel === \"\" || (!isAbsolute(rel) && rel !== \"..\" && !rel.startsWith(`..${sep}`))) return;\n\t}\n\tthrow new Error(\n\t\tt('cwd \"{cwd}\" is outside the configured workspace roots: [{roots}]', {\n\t\t\tcwd: resolvedCwd,\n\t\t\troots: roots.map((root) => resolve(root)).join(\", \"),\n\t\t}),\n\t);\n}\n\n/**\n * `create` targets a fresh session workspace, so a missing or non-directory\n * cwd must fail the create with a clear, path-bearing error instead of\n * producing a session whose tools fail on their first relative access.\n * `open` re-opens sessions already recorded on disk and is not gated. The\n * plain `Error` matches the session-source convention; the server boundary\n * maps it to an `invalid_request` protocol error with the original message.\n */\nasync function assertCwdIsDirectory(cwd: string): Promise<void> {\n\tconst stats = await stat(cwd).catch((error: unknown) => {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t});\n\tif (stats === undefined) {\n\t\tthrow new Error(t(\"Cannot create session: cwd does not exist: {cwd}\", { cwd }));\n\t}\n\tif (!stats.isDirectory()) {\n\t\tthrow new Error(t(\"Cannot create session: cwd is not a directory: {cwd}\", { cwd }));\n\t}\n}\n\n/**\n * Creates a production `CodingAgentServerSessionSource` backed by on-disk\n * `.jsonl` session files in `sessionsDir`.\n */\nexport function createFileSessionSource(options: FileSessionSourceOptions): CodingAgentServerSessionSource {\n\tconst sessionsDir = resolve(options.sessionsDir);\n\n\treturn {\n\t\tasync list(): Promise<readonly CodingAgentSessionDescriptor[]> {\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\treturn infos.map(infoToDescriptor);\n\t\t},\n\n\t\t/**\n\t\t * Creates a session in the descriptor cwd (or the host-level fallback).\n\t\t * The final cwd must be inside the configured workspace roots (when\n\t\t * provided) and must exist as a directory; both checks run before any\n\t\t * session file is written, so a rejected create leaves the disk\n\t\t * untouched.\n\t\t */\n\t\tasync create(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// The server boundary rejects cwd-less creates; a direct host call\n\t\t\t// falls back to the host-level cwd like legacy opens.\n\t\t\tconst cwd = descriptor.cwd === undefined || descriptor.cwd === \"\" ? options.cwd : descriptor.cwd;\n\t\t\tassertWithinWorkspaceRoots(cwd, options.workspaceRoots);\n\t\t\tawait assertCwdIsDirectory(cwd);\n\t\t\tconst sm = SessionManager.create(\n\t\t\t\tcwd,\n\t\t\t\tsessionsDir,\n\t\t\t\t{\n\t\t\t\t\tid: descriptor.id,\n\t\t\t\t\t// Creation-time profile lock, persisted into the session header so\n\t\t\t\t\t// it survives restarts (read back via `list`/`open` descriptors).\n\t\t\t\t\t...(descriptor.profileId === undefined ? {} : { profileId: descriptor.profileId }),\n\t\t\t\t\t...(descriptor.profileVersion === undefined ? {} : { profileVersion: descriptor.profileVersion }),\n\t\t\t\t},\n\t\t\t\toptions.storage,\n\t\t\t);\n\t\t\treturn buildSession(sm, options, cwd, {\n\t\t\t\t...(descriptor.model === undefined ? {} : { model: descriptor.model }),\n\t\t\t\t...(descriptor.thinkingLevel === undefined ? {} : { thinkingLevel: descriptor.thinkingLevel }),\n\t\t\t});\n\t\t},\n\n\t\tasync open(descriptor: CodingAgentSessionDescriptor): Promise<AgentSession> {\n\t\t\t// Re-scan to locate the session file path for the given id.\n\t\t\tconst infos = await SessionManager.listAll(sessionsDir);\n\t\t\tconst match = infos.find((info) => info.id === descriptor.id);\n\t\t\tif (!match) {\n\t\t\t\tthrow new Error(t(\"Session not found: {id}\", { id: descriptor.id }));\n\t\t\t}\n\t\t\t// The session file records the cwd it ran in; legacy files may have\n\t\t\t// none (empty string), which falls back to the host-level cwd. The\n\t\t\t// override keeps the SessionManager cwd consistent with the build\n\t\t\t// cwd for consumers of `getCwd()` (extension surface, snapshot).\n\t\t\tconst cwd = match.cwd === \"\" ? options.cwd : match.cwd;\n\t\t\tconst sm = SessionManager.open(match.path, sessionsDir, cwd, options.storage);\n\t\t\treturn buildSession(sm, options, cwd);\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-share.d.ts","sourceRoot":"","sources":["../../src/share/session-share.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"session-share.d.ts","sourceRoot":"","sources":["../../src/share/session-share.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * session-share contract (2.6c) — an explicit, revocable share contract with\n * a permission context, scope whitelist, and artifact references.\n *\n * A share contract is created for one session with a read-only permission\n * context and an explicit scope (messages on/off, artifact whitelist).\n * Resolution fails structurally for revoked, expired, out-of-scope, or\n * unknown requests — nothing is implicitly included. Revocation is the\n * cancellation path and is terminal. Transports are injected explicitly by\n * the caller (the kernel ships none); HTML/viewer integration is 2.6d.\n */\n\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface ShareScopeV1 {\n\treadonly messages: boolean;\n\t/** Exact artifact references shareable under this contract. */\n\treadonly artifacts: readonly string[];\n\treadonly diagnostics: boolean;\n}\n\nexport interface ShareContractV1 {\n\treadonly shareId: string;\n\treadonly sessionId: string;\n\treadonly permission: \"read_only\";\n\treadonly scope: ShareScopeV1;\n\treadonly createdAt: number;\n\treadonly expiresAt?: number;\n}\n\nexport interface ShareArtifactInputV1 {\n\treadonly artifactId: string;\n\treadonly mediaType: string;\n\treadonly bytesBase64: string;\n}\n\nexport type ShareResolveRequestV1 =\n\t| { readonly kind: \"messages\" }\n\t| { readonly kind: \"diagnostics\" }\n\t| { readonly kind: \"artifact\"; readonly artifactId: string };\n\nexport type ShareResolveResultV1 =\n\t| { readonly status: \"resolved\"; readonly kind: \"messages\"; readonly content: JsonValue }\n\t| { readonly status: \"resolved\"; readonly kind: \"diagnostics\"; readonly content: JsonValue }\n\t| { readonly status: \"resolved\"; readonly kind: \"artifact\"; readonly artifact: ShareArtifactInputV1 }\n\t| { readonly status: \"denied\"; readonly reason: string }\n\t| { readonly status: \"not_found\"; readonly shareId: string };\n\nexport type ShareTransportPayloadV1 = JsonValue | ShareResolveResultV1;\n\nexport interface ShareTransportV1 {\n\treadonly id: string;\n\tsend(input: { readonly contract: ShareContractV1; readonly payload: ShareTransportPayloadV1 }): {\n\t\treadonly accepted: boolean;\n\t};\n}\n\nexport interface SessionShareManagerV1 {\n\tcreateShare(input: {\n\t\treadonly sessionId: string;\n\t\treadonly scope: ShareScopeV1;\n\t\treadonly expiresAt?: number;\n\t}): ShareContractV1;\n\tresolve(input: {\n\t\treadonly shareId: string;\n\t\treadonly request: ShareResolveRequestV1;\n\t\treadonly now?: number;\n\t}): ShareResolveResultV1;\n\trevoke(shareId: string, input: { readonly reason: string }): ShareContractV1;\n\treadonly transport: ShareTransportV1;\n}\n\nexport function createSessionShare(options: {\n\t/** Provider for the session's message transcript (JSON-safe). */\n\treadonly readMessages: (sessionId: string) => JsonValue;\n\t/** Provider for the session's diagnostics (JSON-safe). */\n\treadonly readDiagnostics: (sessionId: string) => JsonValue;\n\t/** Provider for artifact bytes (base64); wired to the 2.6a store by the caller. */\n\treadonly readArtifact: (input: { readonly sessionId: string; readonly artifactId: string }) => ShareArtifactInputV1;\n\treadonly transport: ShareTransportV1;\n\treadonly now?: () => number;\n}): SessionShareManagerV1 {\n\tconst now = options.now ?? (() => Date.now());\n\tconst contracts = new Map<string, { contract: ShareContractV1; revokedReason?: string }>();\n\tlet shareSequence = 0;\n\n\tconst shareIdOf = (sessionId: string): string => {\n\t\tshareSequence += 1;\n\t\tlet hash = 0x811c9dc5;\n\t\tconst value = `${sessionId}#${shareSequence}`;\n\t\tfor (let index = 0; index < value.length; index += 1) {\n\t\t\thash ^= value.charCodeAt(index);\n\t\t\thash = Math.imul(hash, 0x01000193);\n\t\t}\n\t\treturn `share-${(hash >>> 0).toString(36)}`;\n\t};\n\n\treturn {\n\t\ttransport: options.transport,\n\t\tcreateShare(input) {\n\t\t\tconst contract: ShareContractV1 = {\n\t\t\t\tshareId: shareIdOf(input.sessionId),\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tpermission: \"read_only\",\n\t\t\t\tscope: input.scope,\n\t\t\t\tcreatedAt: now(),\n\t\t\t\t...(input.expiresAt === undefined ? {} : { expiresAt: input.expiresAt }),\n\t\t\t};\n\t\t\tcontracts.set(contract.shareId, { contract });\n\t\t\treturn contract;\n\t\t},\n\t\tresolve({ shareId, request, now: at }) {\n\t\t\tconst record = contracts.get(shareId);\n\t\t\tif (!record) return { status: \"not_found\", shareId };\n\t\t\tconst currentTime = at ?? now();\n\t\t\tif (record.revokedReason !== undefined) {\n\t\t\t\treturn { status: \"denied\", reason: `Share ${shareId} is revoked: ${record.revokedReason}` };\n\t\t\t}\n\t\t\tif (record.contract.expiresAt !== undefined && currentTime > record.contract.expiresAt) {\n\t\t\t\treturn { status: \"denied\", reason: `Share ${shareId} expired at ${record.contract.expiresAt}` };\n\t\t\t}\n\t\t\tconst { scope } = record.contract;\n\t\t\tswitch (request.kind) {\n\t\t\t\tcase \"messages\":\n\t\t\t\t\tif (!scope.messages) {\n\t\t\t\t\t\treturn { status: \"denied\", reason: \"Messages are outside the share scope\" };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"messages\",\n\t\t\t\t\t\tcontent: options.readMessages(record.contract.sessionId),\n\t\t\t\t\t};\n\t\t\t\tcase \"diagnostics\":\n\t\t\t\t\tif (!scope.diagnostics) {\n\t\t\t\t\t\treturn { status: \"denied\", reason: \"Diagnostics are outside the share scope\" };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"diagnostics\",\n\t\t\t\t\t\tcontent: options.readDiagnostics(record.contract.sessionId),\n\t\t\t\t\t};\n\t\t\t\tcase \"artifact\":\n\t\t\t\t\tif (!scope.artifacts.includes(request.artifactId)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstatus: \"denied\",\n\t\t\t\t\t\t\treason: `Artifact ${request.artifactId} is not in the share whitelist`,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"artifact\",\n\t\t\t\t\t\tartifact: options.readArtifact({\n\t\t\t\t\t\t\tsessionId: record.contract.sessionId,\n\t\t\t\t\t\t\tartifactId: request.artifactId,\n\t\t\t\t\t\t}),\n\t\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\trevoke(shareId, input) {\n\t\t\tconst record = contracts.get(shareId);\n\t\t\tif (!record) throw new Error(t(\"Share not found: {shareId}\", { shareId }));\n\t\t\tif (record.revokedReason !== undefined) {\n\t\t\t\tthrow new Error(t(\"Share {shareId} has already been revoked\", { shareId }));\n\t\t\t}\n\t\t\trecord.revokedReason = input.reason;\n\t\t\treturn record.contract;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* session-share contract (2.6c) — an explicit, revocable share contract with
|
|
3
|
+
* a permission context, scope whitelist, and artifact references.
|
|
4
|
+
*
|
|
5
|
+
* A share contract is created for one session with a read-only permission
|
|
6
|
+
* context and an explicit scope (messages on/off, artifact whitelist).
|
|
7
|
+
* Resolution fails structurally for revoked, expired, out-of-scope, or
|
|
8
|
+
* unknown requests — nothing is implicitly included. Revocation is the
|
|
9
|
+
* cancellation path and is terminal. Transports are injected explicitly by
|
|
10
|
+
* the caller (the kernel ships none); HTML/viewer integration is 2.6d.
|
|
11
|
+
*/
|
|
12
|
+
import { t } from "../core/i18n/index.js";
|
|
1
13
|
export function createSessionShare(options) {
|
|
2
14
|
const now = options.now ?? (() => Date.now());
|
|
3
15
|
const contracts = new Map();
|
|
@@ -77,9 +89,9 @@ export function createSessionShare(options) {
|
|
|
77
89
|
revoke(shareId, input) {
|
|
78
90
|
const record = contracts.get(shareId);
|
|
79
91
|
if (!record)
|
|
80
|
-
throw new Error(
|
|
92
|
+
throw new Error(t("Share not found: {shareId}", { shareId }));
|
|
81
93
|
if (record.revokedReason !== undefined) {
|
|
82
|
-
throw new Error(
|
|
94
|
+
throw new Error(t("Share {shareId} has already been revoked", { shareId }));
|
|
83
95
|
}
|
|
84
96
|
record.revokedReason = input.reason;
|
|
85
97
|
return record.contract;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-share.js","sourceRoot":"","sources":["../../src/share/session-share.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * session-share contract (2.6c) — an explicit, revocable share contract with\n * a permission context, scope whitelist, and artifact references.\n *\n * A share contract is created for one session with a read-only permission\n * context and an explicit scope (messages on/off, artifact whitelist).\n * Resolution fails structurally for revoked, expired, out-of-scope, or\n * unknown requests — nothing is implicitly included. Revocation is the\n * cancellation path and is terminal. Transports are injected explicitly by\n * the caller (the kernel ships none); HTML/viewer integration is 2.6d.\n */\nimport type { JsonValue } from \"@agent-forge/ai\";\n\nexport interface ShareScopeV1 {\n\treadonly messages: boolean;\n\t/** Exact artifact references shareable under this contract. */\n\treadonly artifacts: readonly string[];\n\treadonly diagnostics: boolean;\n}\n\nexport interface ShareContractV1 {\n\treadonly shareId: string;\n\treadonly sessionId: string;\n\treadonly permission: \"read_only\";\n\treadonly scope: ShareScopeV1;\n\treadonly createdAt: number;\n\treadonly expiresAt?: number;\n}\n\nexport interface ShareArtifactInputV1 {\n\treadonly artifactId: string;\n\treadonly mediaType: string;\n\treadonly bytesBase64: string;\n}\n\nexport type ShareResolveRequestV1 =\n\t| { readonly kind: \"messages\" }\n\t| { readonly kind: \"diagnostics\" }\n\t| { readonly kind: \"artifact\"; readonly artifactId: string };\n\nexport type ShareResolveResultV1 =\n\t| { readonly status: \"resolved\"; readonly kind: \"messages\"; readonly content: JsonValue }\n\t| { readonly status: \"resolved\"; readonly kind: \"diagnostics\"; readonly content: JsonValue }\n\t| { readonly status: \"resolved\"; readonly kind: \"artifact\"; readonly artifact: ShareArtifactInputV1 }\n\t| { readonly status: \"denied\"; readonly reason: string }\n\t| { readonly status: \"not_found\"; readonly shareId: string };\n\nexport type ShareTransportPayloadV1 = JsonValue | ShareResolveResultV1;\n\nexport interface ShareTransportV1 {\n\treadonly id: string;\n\tsend(input: { readonly contract: ShareContractV1; readonly payload: ShareTransportPayloadV1 }): {\n\t\treadonly accepted: boolean;\n\t};\n}\n\nexport interface SessionShareManagerV1 {\n\tcreateShare(input: {\n\t\treadonly sessionId: string;\n\t\treadonly scope: ShareScopeV1;\n\t\treadonly expiresAt?: number;\n\t}): ShareContractV1;\n\tresolve(input: {\n\t\treadonly shareId: string;\n\t\treadonly request: ShareResolveRequestV1;\n\t\treadonly now?: number;\n\t}): ShareResolveResultV1;\n\trevoke(shareId: string, input: { readonly reason: string }): ShareContractV1;\n\treadonly transport: ShareTransportV1;\n}\n\nexport function createSessionShare(options: {\n\t/** Provider for the session's message transcript (JSON-safe). */\n\treadonly readMessages: (sessionId: string) => JsonValue;\n\t/** Provider for the session's diagnostics (JSON-safe). */\n\treadonly readDiagnostics: (sessionId: string) => JsonValue;\n\t/** Provider for artifact bytes (base64); wired to the 2.6a store by the caller. */\n\treadonly readArtifact: (input: { readonly sessionId: string; readonly artifactId: string }) => ShareArtifactInputV1;\n\treadonly transport: ShareTransportV1;\n\treadonly now?: () => number;\n}): SessionShareManagerV1 {\n\tconst now = options.now ?? (() => Date.now());\n\tconst contracts = new Map<string, { contract: ShareContractV1; revokedReason?: string }>();\n\tlet shareSequence = 0;\n\n\tconst shareIdOf = (sessionId: string): string => {\n\t\tshareSequence += 1;\n\t\tlet hash = 0x811c9dc5;\n\t\tconst value = `${sessionId}#${shareSequence}`;\n\t\tfor (let index = 0; index < value.length; index += 1) {\n\t\t\thash ^= value.charCodeAt(index);\n\t\t\thash = Math.imul(hash, 0x01000193);\n\t\t}\n\t\treturn `share-${(hash >>> 0).toString(36)}`;\n\t};\n\n\treturn {\n\t\ttransport: options.transport,\n\t\tcreateShare(input) {\n\t\t\tconst contract: ShareContractV1 = {\n\t\t\t\tshareId: shareIdOf(input.sessionId),\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tpermission: \"read_only\",\n\t\t\t\tscope: input.scope,\n\t\t\t\tcreatedAt: now(),\n\t\t\t\t...(input.expiresAt === undefined ? {} : { expiresAt: input.expiresAt }),\n\t\t\t};\n\t\t\tcontracts.set(contract.shareId, { contract });\n\t\t\treturn contract;\n\t\t},\n\t\tresolve({ shareId, request, now: at }) {\n\t\t\tconst record = contracts.get(shareId);\n\t\t\tif (!record) return { status: \"not_found\", shareId };\n\t\t\tconst currentTime = at ?? now();\n\t\t\tif (record.revokedReason !== undefined) {\n\t\t\t\treturn { status: \"denied\", reason: `Share ${shareId} is revoked: ${record.revokedReason}` };\n\t\t\t}\n\t\t\tif (record.contract.expiresAt !== undefined && currentTime > record.contract.expiresAt) {\n\t\t\t\treturn { status: \"denied\", reason: `Share ${shareId} expired at ${record.contract.expiresAt}` };\n\t\t\t}\n\t\t\tconst { scope } = record.contract;\n\t\t\tswitch (request.kind) {\n\t\t\t\tcase \"messages\":\n\t\t\t\t\tif (!scope.messages) {\n\t\t\t\t\t\treturn { status: \"denied\", reason: \"Messages are outside the share scope\" };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"messages\",\n\t\t\t\t\t\tcontent: options.readMessages(record.contract.sessionId),\n\t\t\t\t\t};\n\t\t\t\tcase \"diagnostics\":\n\t\t\t\t\tif (!scope.diagnostics) {\n\t\t\t\t\t\treturn { status: \"denied\", reason: \"Diagnostics are outside the share scope\" };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"diagnostics\",\n\t\t\t\t\t\tcontent: options.readDiagnostics(record.contract.sessionId),\n\t\t\t\t\t};\n\t\t\t\tcase \"artifact\":\n\t\t\t\t\tif (!scope.artifacts.includes(request.artifactId)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstatus: \"denied\",\n\t\t\t\t\t\t\treason: `Artifact ${request.artifactId} is not in the share whitelist`,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"artifact\",\n\t\t\t\t\t\tartifact: options.readArtifact({\n\t\t\t\t\t\t\tsessionId: record.contract.sessionId,\n\t\t\t\t\t\t\tartifactId: request.artifactId,\n\t\t\t\t\t\t}),\n\t\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\trevoke(shareId, input) {\n\t\t\tconst record = contracts.get(shareId);\n\t\t\tif (!record) throw new Error(`Share not found: ${shareId}`);\n\t\t\tif (record.revokedReason !== undefined) {\n\t\t\t\tthrow new Error(`Share ${shareId} has already been revoked`);\n\t\t\t}\n\t\t\trecord.revokedReason = input.reason;\n\t\t\treturn record.contract;\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-share.js","sourceRoot":"","sources":["../../src/share/session-share.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * session-share contract (2.6c) — an explicit, revocable share contract with\n * a permission context, scope whitelist, and artifact references.\n *\n * A share contract is created for one session with a read-only permission\n * context and an explicit scope (messages on/off, artifact whitelist).\n * Resolution fails structurally for revoked, expired, out-of-scope, or\n * unknown requests — nothing is implicitly included. Revocation is the\n * cancellation path and is terminal. Transports are injected explicitly by\n * the caller (the kernel ships none); HTML/viewer integration is 2.6d.\n */\n\nimport type { JsonValue } from \"@agent-forge/ai\";\nimport { t } from \"../core/i18n/index.ts\";\n\nexport interface ShareScopeV1 {\n\treadonly messages: boolean;\n\t/** Exact artifact references shareable under this contract. */\n\treadonly artifacts: readonly string[];\n\treadonly diagnostics: boolean;\n}\n\nexport interface ShareContractV1 {\n\treadonly shareId: string;\n\treadonly sessionId: string;\n\treadonly permission: \"read_only\";\n\treadonly scope: ShareScopeV1;\n\treadonly createdAt: number;\n\treadonly expiresAt?: number;\n}\n\nexport interface ShareArtifactInputV1 {\n\treadonly artifactId: string;\n\treadonly mediaType: string;\n\treadonly bytesBase64: string;\n}\n\nexport type ShareResolveRequestV1 =\n\t| { readonly kind: \"messages\" }\n\t| { readonly kind: \"diagnostics\" }\n\t| { readonly kind: \"artifact\"; readonly artifactId: string };\n\nexport type ShareResolveResultV1 =\n\t| { readonly status: \"resolved\"; readonly kind: \"messages\"; readonly content: JsonValue }\n\t| { readonly status: \"resolved\"; readonly kind: \"diagnostics\"; readonly content: JsonValue }\n\t| { readonly status: \"resolved\"; readonly kind: \"artifact\"; readonly artifact: ShareArtifactInputV1 }\n\t| { readonly status: \"denied\"; readonly reason: string }\n\t| { readonly status: \"not_found\"; readonly shareId: string };\n\nexport type ShareTransportPayloadV1 = JsonValue | ShareResolveResultV1;\n\nexport interface ShareTransportV1 {\n\treadonly id: string;\n\tsend(input: { readonly contract: ShareContractV1; readonly payload: ShareTransportPayloadV1 }): {\n\t\treadonly accepted: boolean;\n\t};\n}\n\nexport interface SessionShareManagerV1 {\n\tcreateShare(input: {\n\t\treadonly sessionId: string;\n\t\treadonly scope: ShareScopeV1;\n\t\treadonly expiresAt?: number;\n\t}): ShareContractV1;\n\tresolve(input: {\n\t\treadonly shareId: string;\n\t\treadonly request: ShareResolveRequestV1;\n\t\treadonly now?: number;\n\t}): ShareResolveResultV1;\n\trevoke(shareId: string, input: { readonly reason: string }): ShareContractV1;\n\treadonly transport: ShareTransportV1;\n}\n\nexport function createSessionShare(options: {\n\t/** Provider for the session's message transcript (JSON-safe). */\n\treadonly readMessages: (sessionId: string) => JsonValue;\n\t/** Provider for the session's diagnostics (JSON-safe). */\n\treadonly readDiagnostics: (sessionId: string) => JsonValue;\n\t/** Provider for artifact bytes (base64); wired to the 2.6a store by the caller. */\n\treadonly readArtifact: (input: { readonly sessionId: string; readonly artifactId: string }) => ShareArtifactInputV1;\n\treadonly transport: ShareTransportV1;\n\treadonly now?: () => number;\n}): SessionShareManagerV1 {\n\tconst now = options.now ?? (() => Date.now());\n\tconst contracts = new Map<string, { contract: ShareContractV1; revokedReason?: string }>();\n\tlet shareSequence = 0;\n\n\tconst shareIdOf = (sessionId: string): string => {\n\t\tshareSequence += 1;\n\t\tlet hash = 0x811c9dc5;\n\t\tconst value = `${sessionId}#${shareSequence}`;\n\t\tfor (let index = 0; index < value.length; index += 1) {\n\t\t\thash ^= value.charCodeAt(index);\n\t\t\thash = Math.imul(hash, 0x01000193);\n\t\t}\n\t\treturn `share-${(hash >>> 0).toString(36)}`;\n\t};\n\n\treturn {\n\t\ttransport: options.transport,\n\t\tcreateShare(input) {\n\t\t\tconst contract: ShareContractV1 = {\n\t\t\t\tshareId: shareIdOf(input.sessionId),\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tpermission: \"read_only\",\n\t\t\t\tscope: input.scope,\n\t\t\t\tcreatedAt: now(),\n\t\t\t\t...(input.expiresAt === undefined ? {} : { expiresAt: input.expiresAt }),\n\t\t\t};\n\t\t\tcontracts.set(contract.shareId, { contract });\n\t\t\treturn contract;\n\t\t},\n\t\tresolve({ shareId, request, now: at }) {\n\t\t\tconst record = contracts.get(shareId);\n\t\t\tif (!record) return { status: \"not_found\", shareId };\n\t\t\tconst currentTime = at ?? now();\n\t\t\tif (record.revokedReason !== undefined) {\n\t\t\t\treturn { status: \"denied\", reason: `Share ${shareId} is revoked: ${record.revokedReason}` };\n\t\t\t}\n\t\t\tif (record.contract.expiresAt !== undefined && currentTime > record.contract.expiresAt) {\n\t\t\t\treturn { status: \"denied\", reason: `Share ${shareId} expired at ${record.contract.expiresAt}` };\n\t\t\t}\n\t\t\tconst { scope } = record.contract;\n\t\t\tswitch (request.kind) {\n\t\t\t\tcase \"messages\":\n\t\t\t\t\tif (!scope.messages) {\n\t\t\t\t\t\treturn { status: \"denied\", reason: \"Messages are outside the share scope\" };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"messages\",\n\t\t\t\t\t\tcontent: options.readMessages(record.contract.sessionId),\n\t\t\t\t\t};\n\t\t\t\tcase \"diagnostics\":\n\t\t\t\t\tif (!scope.diagnostics) {\n\t\t\t\t\t\treturn { status: \"denied\", reason: \"Diagnostics are outside the share scope\" };\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"diagnostics\",\n\t\t\t\t\t\tcontent: options.readDiagnostics(record.contract.sessionId),\n\t\t\t\t\t};\n\t\t\t\tcase \"artifact\":\n\t\t\t\t\tif (!scope.artifacts.includes(request.artifactId)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tstatus: \"denied\",\n\t\t\t\t\t\t\treason: `Artifact ${request.artifactId} is not in the share whitelist`,\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"resolved\",\n\t\t\t\t\t\tkind: \"artifact\",\n\t\t\t\t\t\tartifact: options.readArtifact({\n\t\t\t\t\t\t\tsessionId: record.contract.sessionId,\n\t\t\t\t\t\t\tartifactId: request.artifactId,\n\t\t\t\t\t\t}),\n\t\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\trevoke(shareId, input) {\n\t\t\tconst record = contracts.get(shareId);\n\t\t\tif (!record) throw new Error(t(\"Share not found: {shareId}\", { shareId }));\n\t\t\tif (record.revokedReason !== undefined) {\n\t\t\t\tthrow new Error(t(\"Share {shareId} has already been revoked\", { shareId }));\n\t\t\t}\n\t\t\trecord.revokedReason = input.reason;\n\t\t\treturn record.contract;\n\t\t},\n\t};\n}\n"]}
|