@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":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Host-process logger: minimal kernel carrying-layer mechanism for runtime\n * diagnostics (design `会话轨迹与日志设计.md` §5). One JSONL entry per line,\n * written through with `appendFileSync` into `<dir>/<yyyy-mm-dd>-<pid>.log`\n * (local date). The file is created lazily on the first written entry.\n *\n * Failure contract: logging must never throw. Level filtering drops entries\n * below the configured level; write failures (disk full, permissions, bad dir)\n * are swallowed and counted, and `close()` reports `{ written, failed }`.\n * Expired log files are swept once at logger creation; sweep failures are\n * recorded as a warn entry through the logger itself.\n *\n * Crash contract: registering `uncaughtException`/`unhandledRejection`\n * listeners replaces Node's default fatal behavior, so the hooks restore it —\n * one log line per fatal value, Node-default crash text on stderr, exit(1).\n */\n\nexport type HostLogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_RANK: Record<HostLogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\n/** All valid host log levels; the construction-time level check runs against this list. */\nconst HOST_LOG_LEVELS: readonly HostLogLevel[] = [\"debug\", \"info\", \"warn\", \"error\"];\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/** Upper bound on retained stack lines for a logged cause. */\nconst MAX_STACK_LINES = 10;\n\n/** Default retention window for startup sweep, in days. `0` disables sweeping. */\nconst DEFAULT_MAX_AGE_DAYS = 14;\n\n/** Per-entry call-site detail. All members optional; `undefined` members are omitted from the line. */\nexport interface HostLogContext {\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\treadonly cause?: unknown;\n}\n\n/** One JSONL line in the host log file. */\nexport interface HostLogEntry {\n\treadonly v: 1;\n\t/** Host timestamp (epoch ms). */\n\treadonly t: number;\n\treadonly level: HostLogLevel;\n\t/** Call-site marker, e.g. \"sdk\", \"compaction\", \"process\". */\n\treadonly src: string;\n\treadonly msg: string;\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\t/** Bounded error facts (name/message + at most 10 stack lines, or safe JSON for non-Error values). */\n\treadonly cause?: unknown;\n}\n\nexport interface HostLoggerOptions {\n\t/** Log directory. Created recursively on first write. */\n\treadonly dir: string;\n\t/**\n\t * Minimum level to write; lower levels are dropped. Default \"info\". An\n\t * invalid level fails construction (programmer error), never a silent\n\t * fallback to a default.\n\t */\n\treadonly level?: HostLogLevel;\n\t/** Startup sweep retention in days; `0` disables sweeping. Default 14. */\n\treadonly maxAgeDays?: number;\n\t/** Injected clock for deterministic tests. Default `Date.now`. */\n\treadonly now?: () => number;\n\t/**\n\t * Injected process hooks to avoid attaching to the real process in tests.\n\t * Members left unset default to the real process.\n\t */\n\treadonly processHost?: HostProcessHost;\n}\n\n/**\n * Process-hook injection surface for the host logger. When the whole\n * processHost is omitted it falls back to the real process: both fatal hooks\n * are registered via `process.on`. With a processHost present, the two\n * registrar members are opt-in: a member left unset means that fatal hook is\n * NOT registered and there is no fallback to `process.on` — the process keeps\n * Node's default fatal behavior for that hook. The crash-restore members\n * (`exit`/`writeStderr`/`deferThrow`) fall back to the real process when\n * omitted, so tests can inject captured fakes that never exit or throw.\n */\nexport interface HostProcessHost {\n\t/**\n\t * Registrar for fatal uncaught exceptions. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"uncaughtException\", cb)`).\n\t */\n\treadonly onUncaughtException?: (cb: (error: unknown) => void) => void;\n\t/**\n\t * Registrar for fatal unhandled rejections. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"unhandledRejection\", cb)`).\n\t */\n\treadonly onUnhandledRejection?: (cb: (reason: unknown) => void) => void;\n\t/** Terminal exit. Omitted = falls back to the real `process.exit`. */\n\treadonly exit?: (code: number) => void;\n\t/** Crash-text sink. Omitted = falls back to the real `process.stderr.write`. */\n\treadonly writeStderr?: (chunk: string) => void;\n\t/**\n\t * Defers the rejection rethrow so it surfaces as an uncaughtException.\n\t * Omitted = falls back to the real `setImmediate(thrower)`.\n\t */\n\treadonly deferThrow?: (thrower: () => void) => void;\n}\n\nexport interface HostLoggerCloseSummary {\n\treadonly written: number;\n\treadonly failed: number;\n}\n\nexport interface HostLogger {\n\tdebug(src: string, msg: string, context?: HostLogContext): void;\n\tinfo(src: string, msg: string, context?: HostLogContext): void;\n\twarn(src: string, msg: string, context?: HostLogContext): void;\n\terror(src: string, msg: string, context?: HostLogContext): void;\n\t/**\n\t * Stop logging. Idempotent; later log calls are no-ops. Registered process\n\t * hooks stay attached: they stop writing log lines but still restore the\n\t * crash semantics (stderr + exit). Returns the write tally.\n\t */\n\tclose(): HostLoggerCloseSummary;\n}\n\n/** Real-process defaults for the crash-restore members; `Required` keeps resolved hooks callable. */\nconst NODE_PROCESS_CRASH_HOST: Required<Pick<HostProcessHost, \"exit\" | \"writeStderr\" | \"deferThrow\">> = {\n\texit(code) {\n\t\tprocess.exit(code);\n\t},\n\twriteStderr(chunk) {\n\t\tprocess.stderr.write(chunk);\n\t},\n\tdeferThrow(thrower) {\n\t\tsetImmediate(thrower);\n\t},\n};\n\nconst NODE_PROCESS_HOST: HostProcessHost = {\n\tonUncaughtException(cb) {\n\t\tprocess.on(\"uncaughtException\", cb);\n\t},\n\tonUnhandledRejection(cb) {\n\t\tprocess.on(\"unhandledRejection\", cb);\n\t},\n\t...NODE_PROCESS_CRASH_HOST,\n};\n\n/** Local-date file name for the given timestamp: `<yyyy-mm-dd>-<pid>.log`. */\nfunction logFileName(timestamp: number): string {\n\tconst date = new Date(timestamp);\n\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(date.getDate()).padStart(2, \"0\");\n\treturn `${date.getFullYear()}-${month}-${day}-${process.pid}.log`;\n}\n\n/**\n * Convert an arbitrary value to JSON-safe data: cycles become \"[circular]\",\n * unserializable members become \"[unserializable]\", bigint/symbol/function are\n * stringified. Diamond references (same object in two places, no cycle) survive.\n */\nfunction toSafeJson(value: unknown): unknown {\n\tconst ancestors = new WeakSet<object>();\n\tconst walk = (input: unknown): unknown => {\n\t\tif (input === null || input === undefined) return null;\n\t\tconst kind = typeof input;\n\t\tif (kind === \"string\" || kind === \"boolean\" || kind === \"number\") return input;\n\t\tif (kind === \"bigint\") return `${String(input)}n`;\n\t\tif (kind === \"function\" || kind === \"symbol\") return \"[unserializable]\";\n\t\tconst obj = input as object;\n\t\tif (ancestors.has(obj)) return \"[circular]\";\n\t\tancestors.add(obj);\n\t\ttry {\n\t\t\tif (input instanceof Date) return input.toISOString();\n\t\t\tif (Array.isArray(input)) return input.map((item) => walk(item));\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const [key, item] of Object.entries(input as Record<string, unknown>)) {\n\t\t\t\tout[key] = walk(item);\n\t\t\t}\n\t\t\treturn out;\n\t\t} catch {\n\t\t\treturn \"[unserializable]\";\n\t\t} finally {\n\t\t\tancestors.delete(obj);\n\t\t}\n\t};\n\treturn walk(value);\n}\n\nfunction boundedStack(stack: string | undefined): string | undefined {\n\tif (stack === undefined) return undefined;\n\tconst lines = stack.split(\"\\n\");\n\treturn lines.length <= MAX_STACK_LINES ? stack : lines.slice(0, MAX_STACK_LINES).join(\"\\n\");\n}\n\n/** Normalize a cause to bounded facts: Errors keep name/message + truncated stack, the rest become safe JSON. */\nfunction boundCause(cause: unknown): unknown {\n\tif (cause instanceof Error) {\n\t\treturn { name: cause.name, message: cause.message, stack: boundedStack(cause.stack) };\n\t}\n\treturn toSafeJson(cause);\n}\n\n/**\n * Node-default crash text for a fatal value: `name: message` plus the stack\n * for Errors (`err.stack` already opens with that header, so it is never\n * echoed twice), safe JSON for anything else.\n */\nfunction fatalStderrText(value: unknown): string {\n\tif (value instanceof Error) {\n\t\tconst header = `${value.name}: ${value.message}`;\n\t\tif (value.stack === undefined) return `${header}\\n`;\n\t\tconst body = value.stack.startsWith(`${header}\\n`) ? value.stack : `${header}\\n${value.stack}`;\n\t\treturn `${body}\\n`;\n\t}\n\treturn `${JSON.stringify(toSafeJson(value))}\\n`;\n}\n\nexport function createHostLogger(options: HostLoggerOptions): HostLogger {\n\t// 构造期校验(程序错误,非运行时降级):非法 level 立即抛错,绝不静默回落\n\t// 默认级别——那会把配置错误伪装成\"日志变少了\"。\n\tif (options.level !== undefined && !HOST_LOG_LEVELS.includes(options.level)) {\n\t\tthrow new Error(\n\t\t\t`Host logger level must be one of ${HOST_LOG_LEVELS.map((level) => `\"${level}\"`).join(\" | \")}; got ${JSON.stringify(options.level)}`,\n\t\t);\n\t}\n\tconst minRank = LEVEL_RANK[options.level ?? \"info\"];\n\tconst now = options.now ?? Date.now;\n\tconst maxAgeDays = options.maxAgeDays ?? DEFAULT_MAX_AGE_DAYS;\n\tconst processHost = options.processHost ?? NODE_PROCESS_HOST;\n\n\tlet closed = false;\n\tlet dirReady = false;\n\tlet written = 0;\n\tlet failed = 0;\n\n\tconst write = (level: HostLogLevel, src: string, msg: string, context?: HostLogContext): void => {\n\t\tif (closed) return;\n\t\tif (LEVEL_RANK[level] < minRank) return;\n\t\tconst entry: HostLogEntry = {\n\t\t\tv: 1,\n\t\t\tt: now(),\n\t\t\tlevel,\n\t\t\tsrc,\n\t\t\tmsg,\n\t\t\tsessionId: context?.sessionId,\n\t\t\ttraceId: context?.traceId,\n\t\t\tfields: context?.fields === undefined ? undefined : (toSafeJson(context.fields) as Record<string, unknown>),\n\t\t\tcause: context?.cause === undefined ? undefined : boundCause(context.cause),\n\t\t};\n\t\ttry {\n\t\t\tif (!dirReady) {\n\t\t\t\tmkdirSync(options.dir, { recursive: true });\n\t\t\t\tdirReady = true;\n\t\t\t}\n\t\t\tappendFileSync(join(options.dir, logFileName(entry.t)), `${JSON.stringify(entry)}\\n`);\n\t\t\twritten += 1;\n\t\t} catch {\n\t\t\t// Never propagate write failures (disk full, permissions, dir is a file).\n\t\t\tfailed += 1;\n\t\t\tdirReady = false;\n\t\t}\n\t};\n\n\tconst sweep = (): void => {\n\t\tif (maxAgeDays <= 0) return;\n\t\tconst cutoff = now() - maxAgeDays * DAY_MS;\n\t\tconst currentName = logFileName(now());\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(options.dir);\n\t\t} catch (error) {\n\t\t\t// A missing directory means there is nothing to sweep; any other\n\t\t\t// read failure is a real fact and goes into the log itself.\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\twrite(\"warn\", \"logger\", \"log sweep failed: cannot read log directory\", { cause: error });\n\t\t\treturn;\n\t\t}\n\t\tlet removed = 0;\n\t\tlet errors = 0;\n\t\tfor (const name of names) {\n\t\t\tif (!name.endsWith(\".log\") || name === currentName) continue;\n\t\t\tconst fullPath = join(options.dir, name);\n\t\t\ttry {\n\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\tif (!stats.isFile() || stats.mtimeMs >= cutoff) continue;\n\t\t\t\tunlinkSync(fullPath);\n\t\t\t\tremoved += 1;\n\t\t\t} catch {\n\t\t\t\terrors += 1;\n\t\t\t}\n\t\t}\n\t\tif (errors > 0) {\n\t\t\twrite(\"warn\", \"logger\", \"log sweep finished with failures\", { fields: { removed, errors } });\n\t\t}\n\t};\n\n\tsweep();\n\n\t// Registering uncaughtException/unhandledRejection listeners replaces Node's\n\t// default crash behavior, so these hooks restore it: crash text on stderr\n\t// and exit(1). Without this, a non-interactive crash (print/RPC/serve)\n\t// would leave the process running and disguise the failure as success.\n\t//\n\t// Fatal-value dedup: a rejection reason rethrown below arrives a second time\n\t// as an uncaughtException; the WeakSet keeps the log line to one write while\n\t// stderr + exit still run on every pass.\n\t//\n\t// Interactive boundary: the TUI registers its own uncaughtException handler\n\t// via `prependListener` and exits(1) first, so the uncaughtException branch\n\t// never fires under interactive mode (TUI crashes stay out of the host\n\t// log); a rejection rethrow surfaces to that prepended handler instead.\n\t//\n\t// After close(): the log line is skipped but stderr + exit still run, so a\n\t// closed logger can never swallow a crash.\n\tconst exit = processHost.exit ?? NODE_PROCESS_CRASH_HOST.exit;\n\tconst writeStderr = processHost.writeStderr ?? NODE_PROCESS_CRASH_HOST.writeStderr;\n\tconst deferThrow = processHost.deferThrow ?? NODE_PROCESS_CRASH_HOST.deferThrow;\n\tconst loggedFatalValues = new WeakSet<object>();\n\tconst isFatalValueLogged = (value: unknown): boolean =>\n\t\tvalue !== null && (typeof value === \"object\" || typeof value === \"function\") && loggedFatalValues.has(value);\n\tconst markFatalValueLogged = (value: unknown): void => {\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) loggedFatalValues.add(value);\n\t};\n\tif (processHost.onUncaughtException) {\n\t\tprocessHost.onUncaughtException((error) => {\n\t\t\tif (!isFatalValueLogged(error)) {\n\t\t\t\tmarkFatalValueLogged(error);\n\t\t\t\twrite(\"error\", \"process\", \"uncaughtException\", { cause: error });\n\t\t\t}\n\t\t\twriteStderr(fatalStderrText(error));\n\t\t\texit(1);\n\t\t});\n\t}\n\tif (processHost.onUnhandledRejection) {\n\t\tprocessHost.onUnhandledRejection((reason) => {\n\t\t\tmarkFatalValueLogged(reason);\n\t\t\twrite(\"error\", \"process\", \"unhandledRejection\", { cause: reason });\n\t\t\tdeferThrow(() => {\n\t\t\t\tthrow reason;\n\t\t\t});\n\t\t});\n\t}\n\n\treturn {\n\t\tdebug: (src, msg, context) => write(\"debug\", src, msg, context),\n\t\tinfo: (src, msg, context) => write(\"info\", src, msg, context),\n\t\twarn: (src, msg, context) => write(\"warn\", src, msg, context),\n\t\terror: (src, msg, context) => write(\"error\", src, msg, context),\n\t\tclose: () => {\n\t\t\tclosed = true;\n\t\t\treturn { written, failed };\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { t } from \"./i18n/index.ts\";\n\n/**\n * Host-process logger: minimal kernel carrying-layer mechanism for runtime\n * diagnostics (design `会话轨迹与日志设计.md` §5). One JSONL entry per line,\n * written through with `appendFileSync` into `<dir>/<yyyy-mm-dd>-<pid>.log`\n * (local date). The file is created lazily on the first written entry.\n *\n * Failure contract: logging must never throw. Level filtering drops entries\n * below the configured level; write failures (disk full, permissions, bad dir)\n * are swallowed and counted, and `close()` reports `{ written, failed }`.\n * Expired log files are swept once at logger creation; sweep failures are\n * recorded as a warn entry through the logger itself.\n *\n * Crash contract: registering `uncaughtException`/`unhandledRejection`\n * listeners replaces Node's default fatal behavior, so the hooks restore it —\n * one log line per fatal value, Node-default crash text on stderr, exit(1).\n */\n\nexport type HostLogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_RANK: Record<HostLogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\n/** All valid host log levels; the construction-time level check runs against this list. */\nconst HOST_LOG_LEVELS: readonly HostLogLevel[] = [\"debug\", \"info\", \"warn\", \"error\"];\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/** Upper bound on retained stack lines for a logged cause. */\nconst MAX_STACK_LINES = 10;\n\n/** Default retention window for startup sweep, in days. `0` disables sweeping. */\nconst DEFAULT_MAX_AGE_DAYS = 14;\n\n/** Per-entry call-site detail. All members optional; `undefined` members are omitted from the line. */\nexport interface HostLogContext {\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\treadonly cause?: unknown;\n}\n\n/** One JSONL line in the host log file. */\nexport interface HostLogEntry {\n\treadonly v: 1;\n\t/** Host timestamp (epoch ms). */\n\treadonly t: number;\n\treadonly level: HostLogLevel;\n\t/** Call-site marker, e.g. \"sdk\", \"compaction\", \"process\". */\n\treadonly src: string;\n\treadonly msg: string;\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\t/** Bounded error facts (name/message + at most 10 stack lines, or safe JSON for non-Error values). */\n\treadonly cause?: unknown;\n}\n\nexport interface HostLoggerOptions {\n\t/** Log directory. Created recursively on first write. */\n\treadonly dir: string;\n\t/**\n\t * Minimum level to write; lower levels are dropped. Default \"info\". An\n\t * invalid level fails construction (programmer error), never a silent\n\t * fallback to a default.\n\t */\n\treadonly level?: HostLogLevel;\n\t/** Startup sweep retention in days; `0` disables sweeping. Default 14. */\n\treadonly maxAgeDays?: number;\n\t/** Injected clock for deterministic tests. Default `Date.now`. */\n\treadonly now?: () => number;\n\t/**\n\t * Injected process hooks to avoid attaching to the real process in tests.\n\t * Members left unset default to the real process.\n\t */\n\treadonly processHost?: HostProcessHost;\n}\n\n/**\n * Process-hook injection surface for the host logger. When the whole\n * processHost is omitted it falls back to the real process: both fatal hooks\n * are registered via `process.on`. With a processHost present, the two\n * registrar members are opt-in: a member left unset means that fatal hook is\n * NOT registered and there is no fallback to `process.on` — the process keeps\n * Node's default fatal behavior for that hook. The crash-restore members\n * (`exit`/`writeStderr`/`deferThrow`) fall back to the real process when\n * omitted, so tests can inject captured fakes that never exit or throw.\n */\nexport interface HostProcessHost {\n\t/**\n\t * Registrar for fatal uncaught exceptions. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"uncaughtException\", cb)`).\n\t */\n\treadonly onUncaughtException?: (cb: (error: unknown) => void) => void;\n\t/**\n\t * Registrar for fatal unhandled rejections. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"unhandledRejection\", cb)`).\n\t */\n\treadonly onUnhandledRejection?: (cb: (reason: unknown) => void) => void;\n\t/** Terminal exit. Omitted = falls back to the real `process.exit`. */\n\treadonly exit?: (code: number) => void;\n\t/** Crash-text sink. Omitted = falls back to the real `process.stderr.write`. */\n\treadonly writeStderr?: (chunk: string) => void;\n\t/**\n\t * Defers the rejection rethrow so it surfaces as an uncaughtException.\n\t * Omitted = falls back to the real `setImmediate(thrower)`.\n\t */\n\treadonly deferThrow?: (thrower: () => void) => void;\n}\n\nexport interface HostLoggerCloseSummary {\n\treadonly written: number;\n\treadonly failed: number;\n}\n\nexport interface HostLogger {\n\tdebug(src: string, msg: string, context?: HostLogContext): void;\n\tinfo(src: string, msg: string, context?: HostLogContext): void;\n\twarn(src: string, msg: string, context?: HostLogContext): void;\n\terror(src: string, msg: string, context?: HostLogContext): void;\n\t/**\n\t * Stop logging. Idempotent; later log calls are no-ops. Registered process\n\t * hooks stay attached: they stop writing log lines but still restore the\n\t * crash semantics (stderr + exit). Returns the write tally.\n\t */\n\tclose(): HostLoggerCloseSummary;\n}\n\n/** Real-process defaults for the crash-restore members; `Required` keeps resolved hooks callable. */\nconst NODE_PROCESS_CRASH_HOST: Required<Pick<HostProcessHost, \"exit\" | \"writeStderr\" | \"deferThrow\">> = {\n\texit(code) {\n\t\tprocess.exit(code);\n\t},\n\twriteStderr(chunk) {\n\t\tprocess.stderr.write(chunk);\n\t},\n\tdeferThrow(thrower) {\n\t\tsetImmediate(thrower);\n\t},\n};\n\nconst NODE_PROCESS_HOST: HostProcessHost = {\n\tonUncaughtException(cb) {\n\t\tprocess.on(\"uncaughtException\", cb);\n\t},\n\tonUnhandledRejection(cb) {\n\t\tprocess.on(\"unhandledRejection\", cb);\n\t},\n\t...NODE_PROCESS_CRASH_HOST,\n};\n\n/** Local-date file name for the given timestamp: `<yyyy-mm-dd>-<pid>.log`. */\nfunction logFileName(timestamp: number): string {\n\tconst date = new Date(timestamp);\n\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(date.getDate()).padStart(2, \"0\");\n\treturn `${date.getFullYear()}-${month}-${day}-${process.pid}.log`;\n}\n\n/**\n * Convert an arbitrary value to JSON-safe data: cycles become \"[circular]\",\n * unserializable members become \"[unserializable]\", bigint/symbol/function are\n * stringified. Diamond references (same object in two places, no cycle) survive.\n */\nfunction toSafeJson(value: unknown): unknown {\n\tconst ancestors = new WeakSet<object>();\n\tconst walk = (input: unknown): unknown => {\n\t\tif (input === null || input === undefined) return null;\n\t\tconst kind = typeof input;\n\t\tif (kind === \"string\" || kind === \"boolean\" || kind === \"number\") return input;\n\t\tif (kind === \"bigint\") return `${String(input)}n`;\n\t\tif (kind === \"function\" || kind === \"symbol\") return \"[unserializable]\";\n\t\tconst obj = input as object;\n\t\tif (ancestors.has(obj)) return \"[circular]\";\n\t\tancestors.add(obj);\n\t\ttry {\n\t\t\tif (input instanceof Date) return input.toISOString();\n\t\t\tif (Array.isArray(input)) return input.map((item) => walk(item));\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const [key, item] of Object.entries(input as Record<string, unknown>)) {\n\t\t\t\tout[key] = walk(item);\n\t\t\t}\n\t\t\treturn out;\n\t\t} catch {\n\t\t\treturn \"[unserializable]\";\n\t\t} finally {\n\t\t\tancestors.delete(obj);\n\t\t}\n\t};\n\treturn walk(value);\n}\n\nfunction boundedStack(stack: string | undefined): string | undefined {\n\tif (stack === undefined) return undefined;\n\tconst lines = stack.split(\"\\n\");\n\treturn lines.length <= MAX_STACK_LINES ? stack : lines.slice(0, MAX_STACK_LINES).join(\"\\n\");\n}\n\n/** Normalize a cause to bounded facts: Errors keep name/message + truncated stack, the rest become safe JSON. */\nfunction boundCause(cause: unknown): unknown {\n\tif (cause instanceof Error) {\n\t\treturn { name: cause.name, message: cause.message, stack: boundedStack(cause.stack) };\n\t}\n\treturn toSafeJson(cause);\n}\n\n/**\n * Node-default crash text for a fatal value: `name: message` plus the stack\n * for Errors (`err.stack` already opens with that header, so it is never\n * echoed twice), safe JSON for anything else.\n */\nfunction fatalStderrText(value: unknown): string {\n\tif (value instanceof Error) {\n\t\tconst header = `${value.name}: ${value.message}`;\n\t\tif (value.stack === undefined) return `${header}\\n`;\n\t\tconst body = value.stack.startsWith(`${header}\\n`) ? value.stack : `${header}\\n${value.stack}`;\n\t\treturn `${body}\\n`;\n\t}\n\treturn `${JSON.stringify(toSafeJson(value))}\\n`;\n}\n\nexport function createHostLogger(options: HostLoggerOptions): HostLogger {\n\t// 构造期校验(程序错误,非运行时降级):非法 level 立即抛错,绝不静默回落\n\t// 默认级别——那会把配置错误伪装成\"日志变少了\"。\n\tif (options.level !== undefined && !HOST_LOG_LEVELS.includes(options.level)) {\n\t\tthrow new Error(\n\t\t\tt(\"Host logger level must be one of {levels}; got {value}\", {\n\t\t\t\tlevels: HOST_LOG_LEVELS.map((level) => `\"${level}\"`).join(\" | \"),\n\t\t\t\tvalue: JSON.stringify(options.level),\n\t\t\t}),\n\t\t);\n\t}\n\tconst minRank = LEVEL_RANK[options.level ?? \"info\"];\n\tconst now = options.now ?? Date.now;\n\tconst maxAgeDays = options.maxAgeDays ?? DEFAULT_MAX_AGE_DAYS;\n\tconst processHost = options.processHost ?? NODE_PROCESS_HOST;\n\n\tlet closed = false;\n\tlet dirReady = false;\n\tlet written = 0;\n\tlet failed = 0;\n\n\tconst write = (level: HostLogLevel, src: string, msg: string, context?: HostLogContext): void => {\n\t\tif (closed) return;\n\t\tif (LEVEL_RANK[level] < minRank) return;\n\t\tconst entry: HostLogEntry = {\n\t\t\tv: 1,\n\t\t\tt: now(),\n\t\t\tlevel,\n\t\t\tsrc,\n\t\t\tmsg,\n\t\t\tsessionId: context?.sessionId,\n\t\t\ttraceId: context?.traceId,\n\t\t\tfields: context?.fields === undefined ? undefined : (toSafeJson(context.fields) as Record<string, unknown>),\n\t\t\tcause: context?.cause === undefined ? undefined : boundCause(context.cause),\n\t\t};\n\t\ttry {\n\t\t\tif (!dirReady) {\n\t\t\t\tmkdirSync(options.dir, { recursive: true });\n\t\t\t\tdirReady = true;\n\t\t\t}\n\t\t\tappendFileSync(join(options.dir, logFileName(entry.t)), `${JSON.stringify(entry)}\\n`);\n\t\t\twritten += 1;\n\t\t} catch {\n\t\t\t// Never propagate write failures (disk full, permissions, dir is a file).\n\t\t\tfailed += 1;\n\t\t\tdirReady = false;\n\t\t}\n\t};\n\n\tconst sweep = (): void => {\n\t\tif (maxAgeDays <= 0) return;\n\t\tconst cutoff = now() - maxAgeDays * DAY_MS;\n\t\tconst currentName = logFileName(now());\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(options.dir);\n\t\t} catch (error) {\n\t\t\t// A missing directory means there is nothing to sweep; any other\n\t\t\t// read failure is a real fact and goes into the log itself.\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\twrite(\"warn\", \"logger\", \"log sweep failed: cannot read log directory\", { cause: error });\n\t\t\treturn;\n\t\t}\n\t\tlet removed = 0;\n\t\tlet errors = 0;\n\t\tfor (const name of names) {\n\t\t\tif (!name.endsWith(\".log\") || name === currentName) continue;\n\t\t\tconst fullPath = join(options.dir, name);\n\t\t\ttry {\n\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\tif (!stats.isFile() || stats.mtimeMs >= cutoff) continue;\n\t\t\t\tunlinkSync(fullPath);\n\t\t\t\tremoved += 1;\n\t\t\t} catch {\n\t\t\t\terrors += 1;\n\t\t\t}\n\t\t}\n\t\tif (errors > 0) {\n\t\t\twrite(\"warn\", \"logger\", \"log sweep finished with failures\", { fields: { removed, errors } });\n\t\t}\n\t};\n\n\tsweep();\n\n\t// Registering uncaughtException/unhandledRejection listeners replaces Node's\n\t// default crash behavior, so these hooks restore it: crash text on stderr\n\t// and exit(1). Without this, a non-interactive crash (print/RPC/serve)\n\t// would leave the process running and disguise the failure as success.\n\t//\n\t// Fatal-value dedup: a rejection reason rethrown below arrives a second time\n\t// as an uncaughtException; the WeakSet keeps the log line to one write while\n\t// stderr + exit still run on every pass.\n\t//\n\t// Interactive boundary: the TUI registers its own uncaughtException handler\n\t// via `prependListener` and exits(1) first, so the uncaughtException branch\n\t// never fires under interactive mode (TUI crashes stay out of the host\n\t// log); a rejection rethrow surfaces to that prepended handler instead.\n\t//\n\t// After close(): the log line is skipped but stderr + exit still run, so a\n\t// closed logger can never swallow a crash.\n\tconst exit = processHost.exit ?? NODE_PROCESS_CRASH_HOST.exit;\n\tconst writeStderr = processHost.writeStderr ?? NODE_PROCESS_CRASH_HOST.writeStderr;\n\tconst deferThrow = processHost.deferThrow ?? NODE_PROCESS_CRASH_HOST.deferThrow;\n\tconst loggedFatalValues = new WeakSet<object>();\n\tconst isFatalValueLogged = (value: unknown): boolean =>\n\t\tvalue !== null && (typeof value === \"object\" || typeof value === \"function\") && loggedFatalValues.has(value);\n\tconst markFatalValueLogged = (value: unknown): void => {\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) loggedFatalValues.add(value);\n\t};\n\tif (processHost.onUncaughtException) {\n\t\tprocessHost.onUncaughtException((error) => {\n\t\t\tif (!isFatalValueLogged(error)) {\n\t\t\t\tmarkFatalValueLogged(error);\n\t\t\t\twrite(\"error\", \"process\", \"uncaughtException\", { cause: error });\n\t\t\t}\n\t\t\twriteStderr(fatalStderrText(error));\n\t\t\texit(1);\n\t\t});\n\t}\n\tif (processHost.onUnhandledRejection) {\n\t\tprocessHost.onUnhandledRejection((reason) => {\n\t\t\tmarkFatalValueLogged(reason);\n\t\t\twrite(\"error\", \"process\", \"unhandledRejection\", { cause: reason });\n\t\t\tdeferThrow(() => {\n\t\t\t\tthrow reason;\n\t\t\t});\n\t\t});\n\t}\n\n\treturn {\n\t\tdebug: (src, msg, context) => write(\"debug\", src, msg, context),\n\t\tinfo: (src, msg, context) => write(\"info\", src, msg, context),\n\t\twarn: (src, msg, context) => write(\"warn\", src, msg, context),\n\t\terror: (src, msg, context) => write(\"error\", src, msg, context),\n\t\tclose: () => {\n\t\t\tclosed = true;\n\t\t\treturn { written, failed };\n\t\t},\n\t};\n}\n"]}
|
package/dist/core/logger.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { appendFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { t } from "./i18n/index.js";
|
|
3
4
|
const LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
4
5
|
/** All valid host log levels; the construction-time level check runs against this list. */
|
|
5
6
|
const HOST_LOG_LEVELS = ["debug", "info", "warn", "error"];
|
|
@@ -109,7 +110,10 @@ export function createHostLogger(options) {
|
|
|
109
110
|
// 构造期校验(程序错误,非运行时降级):非法 level 立即抛错,绝不静默回落
|
|
110
111
|
// 默认级别——那会把配置错误伪装成"日志变少了"。
|
|
111
112
|
if (options.level !== undefined && !HOST_LOG_LEVELS.includes(options.level)) {
|
|
112
|
-
throw new Error(
|
|
113
|
+
throw new Error(t("Host logger level must be one of {levels}; got {value}", {
|
|
114
|
+
levels: HOST_LOG_LEVELS.map((level) => `"${level}"`).join(" | "),
|
|
115
|
+
value: JSON.stringify(options.level),
|
|
116
|
+
}));
|
|
113
117
|
}
|
|
114
118
|
const minRank = LEVEL_RANK[options.level ?? "info"];
|
|
115
119
|
const now = options.now ?? Date.now;
|
package/dist/core/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Host-process logger: minimal kernel carrying-layer mechanism for runtime\n * diagnostics (design `会话轨迹与日志设计.md` §5). One JSONL entry per line,\n * written through with `appendFileSync` into `<dir>/<yyyy-mm-dd>-<pid>.log`\n * (local date). The file is created lazily on the first written entry.\n *\n * Failure contract: logging must never throw. Level filtering drops entries\n * below the configured level; write failures (disk full, permissions, bad dir)\n * are swallowed and counted, and `close()` reports `{ written, failed }`.\n * Expired log files are swept once at logger creation; sweep failures are\n * recorded as a warn entry through the logger itself.\n *\n * Crash contract: registering `uncaughtException`/`unhandledRejection`\n * listeners replaces Node's default fatal behavior, so the hooks restore it —\n * one log line per fatal value, Node-default crash text on stderr, exit(1).\n */\n\nexport type HostLogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_RANK: Record<HostLogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\n/** All valid host log levels; the construction-time level check runs against this list. */\nconst HOST_LOG_LEVELS: readonly HostLogLevel[] = [\"debug\", \"info\", \"warn\", \"error\"];\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/** Upper bound on retained stack lines for a logged cause. */\nconst MAX_STACK_LINES = 10;\n\n/** Default retention window for startup sweep, in days. `0` disables sweeping. */\nconst DEFAULT_MAX_AGE_DAYS = 14;\n\n/** Per-entry call-site detail. All members optional; `undefined` members are omitted from the line. */\nexport interface HostLogContext {\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\treadonly cause?: unknown;\n}\n\n/** One JSONL line in the host log file. */\nexport interface HostLogEntry {\n\treadonly v: 1;\n\t/** Host timestamp (epoch ms). */\n\treadonly t: number;\n\treadonly level: HostLogLevel;\n\t/** Call-site marker, e.g. \"sdk\", \"compaction\", \"process\". */\n\treadonly src: string;\n\treadonly msg: string;\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\t/** Bounded error facts (name/message + at most 10 stack lines, or safe JSON for non-Error values). */\n\treadonly cause?: unknown;\n}\n\nexport interface HostLoggerOptions {\n\t/** Log directory. Created recursively on first write. */\n\treadonly dir: string;\n\t/**\n\t * Minimum level to write; lower levels are dropped. Default \"info\". An\n\t * invalid level fails construction (programmer error), never a silent\n\t * fallback to a default.\n\t */\n\treadonly level?: HostLogLevel;\n\t/** Startup sweep retention in days; `0` disables sweeping. Default 14. */\n\treadonly maxAgeDays?: number;\n\t/** Injected clock for deterministic tests. Default `Date.now`. */\n\treadonly now?: () => number;\n\t/**\n\t * Injected process hooks to avoid attaching to the real process in tests.\n\t * Members left unset default to the real process.\n\t */\n\treadonly processHost?: HostProcessHost;\n}\n\n/**\n * Process-hook injection surface for the host logger. When the whole\n * processHost is omitted it falls back to the real process: both fatal hooks\n * are registered via `process.on`. With a processHost present, the two\n * registrar members are opt-in: a member left unset means that fatal hook is\n * NOT registered and there is no fallback to `process.on` — the process keeps\n * Node's default fatal behavior for that hook. The crash-restore members\n * (`exit`/`writeStderr`/`deferThrow`) fall back to the real process when\n * omitted, so tests can inject captured fakes that never exit or throw.\n */\nexport interface HostProcessHost {\n\t/**\n\t * Registrar for fatal uncaught exceptions. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"uncaughtException\", cb)`).\n\t */\n\treadonly onUncaughtException?: (cb: (error: unknown) => void) => void;\n\t/**\n\t * Registrar for fatal unhandled rejections. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"unhandledRejection\", cb)`).\n\t */\n\treadonly onUnhandledRejection?: (cb: (reason: unknown) => void) => void;\n\t/** Terminal exit. Omitted = falls back to the real `process.exit`. */\n\treadonly exit?: (code: number) => void;\n\t/** Crash-text sink. Omitted = falls back to the real `process.stderr.write`. */\n\treadonly writeStderr?: (chunk: string) => void;\n\t/**\n\t * Defers the rejection rethrow so it surfaces as an uncaughtException.\n\t * Omitted = falls back to the real `setImmediate(thrower)`.\n\t */\n\treadonly deferThrow?: (thrower: () => void) => void;\n}\n\nexport interface HostLoggerCloseSummary {\n\treadonly written: number;\n\treadonly failed: number;\n}\n\nexport interface HostLogger {\n\tdebug(src: string, msg: string, context?: HostLogContext): void;\n\tinfo(src: string, msg: string, context?: HostLogContext): void;\n\twarn(src: string, msg: string, context?: HostLogContext): void;\n\terror(src: string, msg: string, context?: HostLogContext): void;\n\t/**\n\t * Stop logging. Idempotent; later log calls are no-ops. Registered process\n\t * hooks stay attached: they stop writing log lines but still restore the\n\t * crash semantics (stderr + exit). Returns the write tally.\n\t */\n\tclose(): HostLoggerCloseSummary;\n}\n\n/** Real-process defaults for the crash-restore members; `Required` keeps resolved hooks callable. */\nconst NODE_PROCESS_CRASH_HOST: Required<Pick<HostProcessHost, \"exit\" | \"writeStderr\" | \"deferThrow\">> = {\n\texit(code) {\n\t\tprocess.exit(code);\n\t},\n\twriteStderr(chunk) {\n\t\tprocess.stderr.write(chunk);\n\t},\n\tdeferThrow(thrower) {\n\t\tsetImmediate(thrower);\n\t},\n};\n\nconst NODE_PROCESS_HOST: HostProcessHost = {\n\tonUncaughtException(cb) {\n\t\tprocess.on(\"uncaughtException\", cb);\n\t},\n\tonUnhandledRejection(cb) {\n\t\tprocess.on(\"unhandledRejection\", cb);\n\t},\n\t...NODE_PROCESS_CRASH_HOST,\n};\n\n/** Local-date file name for the given timestamp: `<yyyy-mm-dd>-<pid>.log`. */\nfunction logFileName(timestamp: number): string {\n\tconst date = new Date(timestamp);\n\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(date.getDate()).padStart(2, \"0\");\n\treturn `${date.getFullYear()}-${month}-${day}-${process.pid}.log`;\n}\n\n/**\n * Convert an arbitrary value to JSON-safe data: cycles become \"[circular]\",\n * unserializable members become \"[unserializable]\", bigint/symbol/function are\n * stringified. Diamond references (same object in two places, no cycle) survive.\n */\nfunction toSafeJson(value: unknown): unknown {\n\tconst ancestors = new WeakSet<object>();\n\tconst walk = (input: unknown): unknown => {\n\t\tif (input === null || input === undefined) return null;\n\t\tconst kind = typeof input;\n\t\tif (kind === \"string\" || kind === \"boolean\" || kind === \"number\") return input;\n\t\tif (kind === \"bigint\") return `${String(input)}n`;\n\t\tif (kind === \"function\" || kind === \"symbol\") return \"[unserializable]\";\n\t\tconst obj = input as object;\n\t\tif (ancestors.has(obj)) return \"[circular]\";\n\t\tancestors.add(obj);\n\t\ttry {\n\t\t\tif (input instanceof Date) return input.toISOString();\n\t\t\tif (Array.isArray(input)) return input.map((item) => walk(item));\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const [key, item] of Object.entries(input as Record<string, unknown>)) {\n\t\t\t\tout[key] = walk(item);\n\t\t\t}\n\t\t\treturn out;\n\t\t} catch {\n\t\t\treturn \"[unserializable]\";\n\t\t} finally {\n\t\t\tancestors.delete(obj);\n\t\t}\n\t};\n\treturn walk(value);\n}\n\nfunction boundedStack(stack: string | undefined): string | undefined {\n\tif (stack === undefined) return undefined;\n\tconst lines = stack.split(\"\\n\");\n\treturn lines.length <= MAX_STACK_LINES ? stack : lines.slice(0, MAX_STACK_LINES).join(\"\\n\");\n}\n\n/** Normalize a cause to bounded facts: Errors keep name/message + truncated stack, the rest become safe JSON. */\nfunction boundCause(cause: unknown): unknown {\n\tif (cause instanceof Error) {\n\t\treturn { name: cause.name, message: cause.message, stack: boundedStack(cause.stack) };\n\t}\n\treturn toSafeJson(cause);\n}\n\n/**\n * Node-default crash text for a fatal value: `name: message` plus the stack\n * for Errors (`err.stack` already opens with that header, so it is never\n * echoed twice), safe JSON for anything else.\n */\nfunction fatalStderrText(value: unknown): string {\n\tif (value instanceof Error) {\n\t\tconst header = `${value.name}: ${value.message}`;\n\t\tif (value.stack === undefined) return `${header}\\n`;\n\t\tconst body = value.stack.startsWith(`${header}\\n`) ? value.stack : `${header}\\n${value.stack}`;\n\t\treturn `${body}\\n`;\n\t}\n\treturn `${JSON.stringify(toSafeJson(value))}\\n`;\n}\n\nexport function createHostLogger(options: HostLoggerOptions): HostLogger {\n\t// 构造期校验(程序错误,非运行时降级):非法 level 立即抛错,绝不静默回落\n\t// 默认级别——那会把配置错误伪装成\"日志变少了\"。\n\tif (options.level !== undefined && !HOST_LOG_LEVELS.includes(options.level)) {\n\t\tthrow new Error(\n\t\t\t`Host logger level must be one of ${HOST_LOG_LEVELS.map((level) => `\"${level}\"`).join(\" | \")}; got ${JSON.stringify(options.level)}`,\n\t\t);\n\t}\n\tconst minRank = LEVEL_RANK[options.level ?? \"info\"];\n\tconst now = options.now ?? Date.now;\n\tconst maxAgeDays = options.maxAgeDays ?? DEFAULT_MAX_AGE_DAYS;\n\tconst processHost = options.processHost ?? NODE_PROCESS_HOST;\n\n\tlet closed = false;\n\tlet dirReady = false;\n\tlet written = 0;\n\tlet failed = 0;\n\n\tconst write = (level: HostLogLevel, src: string, msg: string, context?: HostLogContext): void => {\n\t\tif (closed) return;\n\t\tif (LEVEL_RANK[level] < minRank) return;\n\t\tconst entry: HostLogEntry = {\n\t\t\tv: 1,\n\t\t\tt: now(),\n\t\t\tlevel,\n\t\t\tsrc,\n\t\t\tmsg,\n\t\t\tsessionId: context?.sessionId,\n\t\t\ttraceId: context?.traceId,\n\t\t\tfields: context?.fields === undefined ? undefined : (toSafeJson(context.fields) as Record<string, unknown>),\n\t\t\tcause: context?.cause === undefined ? undefined : boundCause(context.cause),\n\t\t};\n\t\ttry {\n\t\t\tif (!dirReady) {\n\t\t\t\tmkdirSync(options.dir, { recursive: true });\n\t\t\t\tdirReady = true;\n\t\t\t}\n\t\t\tappendFileSync(join(options.dir, logFileName(entry.t)), `${JSON.stringify(entry)}\\n`);\n\t\t\twritten += 1;\n\t\t} catch {\n\t\t\t// Never propagate write failures (disk full, permissions, dir is a file).\n\t\t\tfailed += 1;\n\t\t\tdirReady = false;\n\t\t}\n\t};\n\n\tconst sweep = (): void => {\n\t\tif (maxAgeDays <= 0) return;\n\t\tconst cutoff = now() - maxAgeDays * DAY_MS;\n\t\tconst currentName = logFileName(now());\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(options.dir);\n\t\t} catch (error) {\n\t\t\t// A missing directory means there is nothing to sweep; any other\n\t\t\t// read failure is a real fact and goes into the log itself.\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\twrite(\"warn\", \"logger\", \"log sweep failed: cannot read log directory\", { cause: error });\n\t\t\treturn;\n\t\t}\n\t\tlet removed = 0;\n\t\tlet errors = 0;\n\t\tfor (const name of names) {\n\t\t\tif (!name.endsWith(\".log\") || name === currentName) continue;\n\t\t\tconst fullPath = join(options.dir, name);\n\t\t\ttry {\n\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\tif (!stats.isFile() || stats.mtimeMs >= cutoff) continue;\n\t\t\t\tunlinkSync(fullPath);\n\t\t\t\tremoved += 1;\n\t\t\t} catch {\n\t\t\t\terrors += 1;\n\t\t\t}\n\t\t}\n\t\tif (errors > 0) {\n\t\t\twrite(\"warn\", \"logger\", \"log sweep finished with failures\", { fields: { removed, errors } });\n\t\t}\n\t};\n\n\tsweep();\n\n\t// Registering uncaughtException/unhandledRejection listeners replaces Node's\n\t// default crash behavior, so these hooks restore it: crash text on stderr\n\t// and exit(1). Without this, a non-interactive crash (print/RPC/serve)\n\t// would leave the process running and disguise the failure as success.\n\t//\n\t// Fatal-value dedup: a rejection reason rethrown below arrives a second time\n\t// as an uncaughtException; the WeakSet keeps the log line to one write while\n\t// stderr + exit still run on every pass.\n\t//\n\t// Interactive boundary: the TUI registers its own uncaughtException handler\n\t// via `prependListener` and exits(1) first, so the uncaughtException branch\n\t// never fires under interactive mode (TUI crashes stay out of the host\n\t// log); a rejection rethrow surfaces to that prepended handler instead.\n\t//\n\t// After close(): the log line is skipped but stderr + exit still run, so a\n\t// closed logger can never swallow a crash.\n\tconst exit = processHost.exit ?? NODE_PROCESS_CRASH_HOST.exit;\n\tconst writeStderr = processHost.writeStderr ?? NODE_PROCESS_CRASH_HOST.writeStderr;\n\tconst deferThrow = processHost.deferThrow ?? NODE_PROCESS_CRASH_HOST.deferThrow;\n\tconst loggedFatalValues = new WeakSet<object>();\n\tconst isFatalValueLogged = (value: unknown): boolean =>\n\t\tvalue !== null && (typeof value === \"object\" || typeof value === \"function\") && loggedFatalValues.has(value);\n\tconst markFatalValueLogged = (value: unknown): void => {\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) loggedFatalValues.add(value);\n\t};\n\tif (processHost.onUncaughtException) {\n\t\tprocessHost.onUncaughtException((error) => {\n\t\t\tif (!isFatalValueLogged(error)) {\n\t\t\t\tmarkFatalValueLogged(error);\n\t\t\t\twrite(\"error\", \"process\", \"uncaughtException\", { cause: error });\n\t\t\t}\n\t\t\twriteStderr(fatalStderrText(error));\n\t\t\texit(1);\n\t\t});\n\t}\n\tif (processHost.onUnhandledRejection) {\n\t\tprocessHost.onUnhandledRejection((reason) => {\n\t\t\tmarkFatalValueLogged(reason);\n\t\t\twrite(\"error\", \"process\", \"unhandledRejection\", { cause: reason });\n\t\t\tdeferThrow(() => {\n\t\t\t\tthrow reason;\n\t\t\t});\n\t\t});\n\t}\n\n\treturn {\n\t\tdebug: (src, msg, context) => write(\"debug\", src, msg, context),\n\t\tinfo: (src, msg, context) => write(\"info\", src, msg, context),\n\t\twarn: (src, msg, context) => write(\"warn\", src, msg, context),\n\t\terror: (src, msg, context) => write(\"error\", src, msg, context),\n\t\tclose: () => {\n\t\t\tclosed = true;\n\t\t\treturn { written, failed };\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync, mkdirSync, readdirSync, statSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { t } from \"./i18n/index.ts\";\n\n/**\n * Host-process logger: minimal kernel carrying-layer mechanism for runtime\n * diagnostics (design `会话轨迹与日志设计.md` §5). One JSONL entry per line,\n * written through with `appendFileSync` into `<dir>/<yyyy-mm-dd>-<pid>.log`\n * (local date). The file is created lazily on the first written entry.\n *\n * Failure contract: logging must never throw. Level filtering drops entries\n * below the configured level; write failures (disk full, permissions, bad dir)\n * are swallowed and counted, and `close()` reports `{ written, failed }`.\n * Expired log files are swept once at logger creation; sweep failures are\n * recorded as a warn entry through the logger itself.\n *\n * Crash contract: registering `uncaughtException`/`unhandledRejection`\n * listeners replaces Node's default fatal behavior, so the hooks restore it —\n * one log line per fatal value, Node-default crash text on stderr, exit(1).\n */\n\nexport type HostLogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_RANK: Record<HostLogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\n\n/** All valid host log levels; the construction-time level check runs against this list. */\nconst HOST_LOG_LEVELS: readonly HostLogLevel[] = [\"debug\", \"info\", \"warn\", \"error\"];\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\n/** Upper bound on retained stack lines for a logged cause. */\nconst MAX_STACK_LINES = 10;\n\n/** Default retention window for startup sweep, in days. `0` disables sweeping. */\nconst DEFAULT_MAX_AGE_DAYS = 14;\n\n/** Per-entry call-site detail. All members optional; `undefined` members are omitted from the line. */\nexport interface HostLogContext {\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\treadonly cause?: unknown;\n}\n\n/** One JSONL line in the host log file. */\nexport interface HostLogEntry {\n\treadonly v: 1;\n\t/** Host timestamp (epoch ms). */\n\treadonly t: number;\n\treadonly level: HostLogLevel;\n\t/** Call-site marker, e.g. \"sdk\", \"compaction\", \"process\". */\n\treadonly src: string;\n\treadonly msg: string;\n\treadonly sessionId?: string;\n\treadonly traceId?: string;\n\treadonly fields?: Record<string, unknown>;\n\t/** Bounded error facts (name/message + at most 10 stack lines, or safe JSON for non-Error values). */\n\treadonly cause?: unknown;\n}\n\nexport interface HostLoggerOptions {\n\t/** Log directory. Created recursively on first write. */\n\treadonly dir: string;\n\t/**\n\t * Minimum level to write; lower levels are dropped. Default \"info\". An\n\t * invalid level fails construction (programmer error), never a silent\n\t * fallback to a default.\n\t */\n\treadonly level?: HostLogLevel;\n\t/** Startup sweep retention in days; `0` disables sweeping. Default 14. */\n\treadonly maxAgeDays?: number;\n\t/** Injected clock for deterministic tests. Default `Date.now`. */\n\treadonly now?: () => number;\n\t/**\n\t * Injected process hooks to avoid attaching to the real process in tests.\n\t * Members left unset default to the real process.\n\t */\n\treadonly processHost?: HostProcessHost;\n}\n\n/**\n * Process-hook injection surface for the host logger. When the whole\n * processHost is omitted it falls back to the real process: both fatal hooks\n * are registered via `process.on`. With a processHost present, the two\n * registrar members are opt-in: a member left unset means that fatal hook is\n * NOT registered and there is no fallback to `process.on` — the process keeps\n * Node's default fatal behavior for that hook. The crash-restore members\n * (`exit`/`writeStderr`/`deferThrow`) fall back to the real process when\n * omitted, so tests can inject captured fakes that never exit or throw.\n */\nexport interface HostProcessHost {\n\t/**\n\t * Registrar for fatal uncaught exceptions. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"uncaughtException\", cb)`).\n\t */\n\treadonly onUncaughtException?: (cb: (error: unknown) => void) => void;\n\t/**\n\t * Registrar for fatal unhandled rejections. Omitted = no hook is registered\n\t * (no fallback to `process.on(\"unhandledRejection\", cb)`).\n\t */\n\treadonly onUnhandledRejection?: (cb: (reason: unknown) => void) => void;\n\t/** Terminal exit. Omitted = falls back to the real `process.exit`. */\n\treadonly exit?: (code: number) => void;\n\t/** Crash-text sink. Omitted = falls back to the real `process.stderr.write`. */\n\treadonly writeStderr?: (chunk: string) => void;\n\t/**\n\t * Defers the rejection rethrow so it surfaces as an uncaughtException.\n\t * Omitted = falls back to the real `setImmediate(thrower)`.\n\t */\n\treadonly deferThrow?: (thrower: () => void) => void;\n}\n\nexport interface HostLoggerCloseSummary {\n\treadonly written: number;\n\treadonly failed: number;\n}\n\nexport interface HostLogger {\n\tdebug(src: string, msg: string, context?: HostLogContext): void;\n\tinfo(src: string, msg: string, context?: HostLogContext): void;\n\twarn(src: string, msg: string, context?: HostLogContext): void;\n\terror(src: string, msg: string, context?: HostLogContext): void;\n\t/**\n\t * Stop logging. Idempotent; later log calls are no-ops. Registered process\n\t * hooks stay attached: they stop writing log lines but still restore the\n\t * crash semantics (stderr + exit). Returns the write tally.\n\t */\n\tclose(): HostLoggerCloseSummary;\n}\n\n/** Real-process defaults for the crash-restore members; `Required` keeps resolved hooks callable. */\nconst NODE_PROCESS_CRASH_HOST: Required<Pick<HostProcessHost, \"exit\" | \"writeStderr\" | \"deferThrow\">> = {\n\texit(code) {\n\t\tprocess.exit(code);\n\t},\n\twriteStderr(chunk) {\n\t\tprocess.stderr.write(chunk);\n\t},\n\tdeferThrow(thrower) {\n\t\tsetImmediate(thrower);\n\t},\n};\n\nconst NODE_PROCESS_HOST: HostProcessHost = {\n\tonUncaughtException(cb) {\n\t\tprocess.on(\"uncaughtException\", cb);\n\t},\n\tonUnhandledRejection(cb) {\n\t\tprocess.on(\"unhandledRejection\", cb);\n\t},\n\t...NODE_PROCESS_CRASH_HOST,\n};\n\n/** Local-date file name for the given timestamp: `<yyyy-mm-dd>-<pid>.log`. */\nfunction logFileName(timestamp: number): string {\n\tconst date = new Date(timestamp);\n\tconst month = String(date.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(date.getDate()).padStart(2, \"0\");\n\treturn `${date.getFullYear()}-${month}-${day}-${process.pid}.log`;\n}\n\n/**\n * Convert an arbitrary value to JSON-safe data: cycles become \"[circular]\",\n * unserializable members become \"[unserializable]\", bigint/symbol/function are\n * stringified. Diamond references (same object in two places, no cycle) survive.\n */\nfunction toSafeJson(value: unknown): unknown {\n\tconst ancestors = new WeakSet<object>();\n\tconst walk = (input: unknown): unknown => {\n\t\tif (input === null || input === undefined) return null;\n\t\tconst kind = typeof input;\n\t\tif (kind === \"string\" || kind === \"boolean\" || kind === \"number\") return input;\n\t\tif (kind === \"bigint\") return `${String(input)}n`;\n\t\tif (kind === \"function\" || kind === \"symbol\") return \"[unserializable]\";\n\t\tconst obj = input as object;\n\t\tif (ancestors.has(obj)) return \"[circular]\";\n\t\tancestors.add(obj);\n\t\ttry {\n\t\t\tif (input instanceof Date) return input.toISOString();\n\t\t\tif (Array.isArray(input)) return input.map((item) => walk(item));\n\t\t\tconst out: Record<string, unknown> = {};\n\t\t\tfor (const [key, item] of Object.entries(input as Record<string, unknown>)) {\n\t\t\t\tout[key] = walk(item);\n\t\t\t}\n\t\t\treturn out;\n\t\t} catch {\n\t\t\treturn \"[unserializable]\";\n\t\t} finally {\n\t\t\tancestors.delete(obj);\n\t\t}\n\t};\n\treturn walk(value);\n}\n\nfunction boundedStack(stack: string | undefined): string | undefined {\n\tif (stack === undefined) return undefined;\n\tconst lines = stack.split(\"\\n\");\n\treturn lines.length <= MAX_STACK_LINES ? stack : lines.slice(0, MAX_STACK_LINES).join(\"\\n\");\n}\n\n/** Normalize a cause to bounded facts: Errors keep name/message + truncated stack, the rest become safe JSON. */\nfunction boundCause(cause: unknown): unknown {\n\tif (cause instanceof Error) {\n\t\treturn { name: cause.name, message: cause.message, stack: boundedStack(cause.stack) };\n\t}\n\treturn toSafeJson(cause);\n}\n\n/**\n * Node-default crash text for a fatal value: `name: message` plus the stack\n * for Errors (`err.stack` already opens with that header, so it is never\n * echoed twice), safe JSON for anything else.\n */\nfunction fatalStderrText(value: unknown): string {\n\tif (value instanceof Error) {\n\t\tconst header = `${value.name}: ${value.message}`;\n\t\tif (value.stack === undefined) return `${header}\\n`;\n\t\tconst body = value.stack.startsWith(`${header}\\n`) ? value.stack : `${header}\\n${value.stack}`;\n\t\treturn `${body}\\n`;\n\t}\n\treturn `${JSON.stringify(toSafeJson(value))}\\n`;\n}\n\nexport function createHostLogger(options: HostLoggerOptions): HostLogger {\n\t// 构造期校验(程序错误,非运行时降级):非法 level 立即抛错,绝不静默回落\n\t// 默认级别——那会把配置错误伪装成\"日志变少了\"。\n\tif (options.level !== undefined && !HOST_LOG_LEVELS.includes(options.level)) {\n\t\tthrow new Error(\n\t\t\tt(\"Host logger level must be one of {levels}; got {value}\", {\n\t\t\t\tlevels: HOST_LOG_LEVELS.map((level) => `\"${level}\"`).join(\" | \"),\n\t\t\t\tvalue: JSON.stringify(options.level),\n\t\t\t}),\n\t\t);\n\t}\n\tconst minRank = LEVEL_RANK[options.level ?? \"info\"];\n\tconst now = options.now ?? Date.now;\n\tconst maxAgeDays = options.maxAgeDays ?? DEFAULT_MAX_AGE_DAYS;\n\tconst processHost = options.processHost ?? NODE_PROCESS_HOST;\n\n\tlet closed = false;\n\tlet dirReady = false;\n\tlet written = 0;\n\tlet failed = 0;\n\n\tconst write = (level: HostLogLevel, src: string, msg: string, context?: HostLogContext): void => {\n\t\tif (closed) return;\n\t\tif (LEVEL_RANK[level] < minRank) return;\n\t\tconst entry: HostLogEntry = {\n\t\t\tv: 1,\n\t\t\tt: now(),\n\t\t\tlevel,\n\t\t\tsrc,\n\t\t\tmsg,\n\t\t\tsessionId: context?.sessionId,\n\t\t\ttraceId: context?.traceId,\n\t\t\tfields: context?.fields === undefined ? undefined : (toSafeJson(context.fields) as Record<string, unknown>),\n\t\t\tcause: context?.cause === undefined ? undefined : boundCause(context.cause),\n\t\t};\n\t\ttry {\n\t\t\tif (!dirReady) {\n\t\t\t\tmkdirSync(options.dir, { recursive: true });\n\t\t\t\tdirReady = true;\n\t\t\t}\n\t\t\tappendFileSync(join(options.dir, logFileName(entry.t)), `${JSON.stringify(entry)}\\n`);\n\t\t\twritten += 1;\n\t\t} catch {\n\t\t\t// Never propagate write failures (disk full, permissions, dir is a file).\n\t\t\tfailed += 1;\n\t\t\tdirReady = false;\n\t\t}\n\t};\n\n\tconst sweep = (): void => {\n\t\tif (maxAgeDays <= 0) return;\n\t\tconst cutoff = now() - maxAgeDays * DAY_MS;\n\t\tconst currentName = logFileName(now());\n\t\tlet names: string[];\n\t\ttry {\n\t\t\tnames = readdirSync(options.dir);\n\t\t} catch (error) {\n\t\t\t// A missing directory means there is nothing to sweep; any other\n\t\t\t// read failure is a real fact and goes into the log itself.\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\twrite(\"warn\", \"logger\", \"log sweep failed: cannot read log directory\", { cause: error });\n\t\t\treturn;\n\t\t}\n\t\tlet removed = 0;\n\t\tlet errors = 0;\n\t\tfor (const name of names) {\n\t\t\tif (!name.endsWith(\".log\") || name === currentName) continue;\n\t\t\tconst fullPath = join(options.dir, name);\n\t\t\ttry {\n\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\tif (!stats.isFile() || stats.mtimeMs >= cutoff) continue;\n\t\t\t\tunlinkSync(fullPath);\n\t\t\t\tremoved += 1;\n\t\t\t} catch {\n\t\t\t\terrors += 1;\n\t\t\t}\n\t\t}\n\t\tif (errors > 0) {\n\t\t\twrite(\"warn\", \"logger\", \"log sweep finished with failures\", { fields: { removed, errors } });\n\t\t}\n\t};\n\n\tsweep();\n\n\t// Registering uncaughtException/unhandledRejection listeners replaces Node's\n\t// default crash behavior, so these hooks restore it: crash text on stderr\n\t// and exit(1). Without this, a non-interactive crash (print/RPC/serve)\n\t// would leave the process running and disguise the failure as success.\n\t//\n\t// Fatal-value dedup: a rejection reason rethrown below arrives a second time\n\t// as an uncaughtException; the WeakSet keeps the log line to one write while\n\t// stderr + exit still run on every pass.\n\t//\n\t// Interactive boundary: the TUI registers its own uncaughtException handler\n\t// via `prependListener` and exits(1) first, so the uncaughtException branch\n\t// never fires under interactive mode (TUI crashes stay out of the host\n\t// log); a rejection rethrow surfaces to that prepended handler instead.\n\t//\n\t// After close(): the log line is skipped but stderr + exit still run, so a\n\t// closed logger can never swallow a crash.\n\tconst exit = processHost.exit ?? NODE_PROCESS_CRASH_HOST.exit;\n\tconst writeStderr = processHost.writeStderr ?? NODE_PROCESS_CRASH_HOST.writeStderr;\n\tconst deferThrow = processHost.deferThrow ?? NODE_PROCESS_CRASH_HOST.deferThrow;\n\tconst loggedFatalValues = new WeakSet<object>();\n\tconst isFatalValueLogged = (value: unknown): boolean =>\n\t\tvalue !== null && (typeof value === \"object\" || typeof value === \"function\") && loggedFatalValues.has(value);\n\tconst markFatalValueLogged = (value: unknown): void => {\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) loggedFatalValues.add(value);\n\t};\n\tif (processHost.onUncaughtException) {\n\t\tprocessHost.onUncaughtException((error) => {\n\t\t\tif (!isFatalValueLogged(error)) {\n\t\t\t\tmarkFatalValueLogged(error);\n\t\t\t\twrite(\"error\", \"process\", \"uncaughtException\", { cause: error });\n\t\t\t}\n\t\t\twriteStderr(fatalStderrText(error));\n\t\t\texit(1);\n\t\t});\n\t}\n\tif (processHost.onUnhandledRejection) {\n\t\tprocessHost.onUnhandledRejection((reason) => {\n\t\t\tmarkFatalValueLogged(reason);\n\t\t\twrite(\"error\", \"process\", \"unhandledRejection\", { cause: reason });\n\t\t\tdeferThrow(() => {\n\t\t\t\tthrow reason;\n\t\t\t});\n\t\t});\n\t}\n\n\treturn {\n\t\tdebug: (src, msg, context) => write(\"debug\", src, msg, context),\n\t\tinfo: (src, msg, context) => write(\"info\", src, msg, context),\n\t\twarn: (src, msg, context) => write(\"warn\", src, msg, context),\n\t\terror: (src, msg, context) => write(\"error\", src, msg, context),\n\t\tclose: () => {\n\t\t\tclosed = true;\n\t\t\treturn { written, failed };\n\t\t},\n\t};\n}\n"]}
|
|
@@ -276,7 +276,6 @@ declare const ModelOverrideSchema: Type.TObject<{
|
|
|
276
276
|
declare const ProviderConfigSchema: Type.TObject<{
|
|
277
277
|
name: Type.TOptional<Type.TString>;
|
|
278
278
|
baseUrl: Type.TOptional<Type.TString>;
|
|
279
|
-
apiKey: Type.TOptional<Type.TString>;
|
|
280
279
|
api: Type.TOptional<Type.TString>;
|
|
281
280
|
oauth: Type.TOptional<Type.TLiteral<"radius">>;
|
|
282
281
|
headers: Type.TOptional<Type.TRecord<"^.*$", Type.TString>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAGxD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAuK5C,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBzB,CAAC;AAEH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoBvB,CAAC;AAEH,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWxB,CAAC;AAOH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACnE,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACzE,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAsBrE,yCAAyC;AACzC,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,OAAO,eAGN;IAED,OAAa,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAuC1E;IAED,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE9D;IAED,cAAc,IAAI,SAAS,MAAM,EAAE,CAElC;IAED,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7B;IAED;;;;;;;;OAQG;IACH,oBAAoB,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC,CAa7F;CACD","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tsupportsFinishReason: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsAdditionalTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n\tsupportsMaxOutputTokens: Type.Optional(Type.Boolean()),\n});\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsMidConvoEffort: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n\tallowedFallbackModels: Type.Optional(\n\t\tType.Array(\n\t\t\tType.Object({\n\t\t\t\tprovider: Type.String({ minLength: 1 }),\n\t\t\t\tmodel: Type.String({ minLength: 1 }),\n\t\t\t\tcost: ModelCostSchema,\n\t\t\t}),\n\t\t\t{ maxItems: 3 },\n\t\t),\n\t),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\t// 供应商能力槽位(设计 §3.1):语义与既有 ImagesModel.output 对齐,缺省 =\n\t// 纯文本(undefined 视为 [\"text\"])。生图供应商在 models.json 登记\n\t// \"output\": [\"image\"] 的模型即进入宿主注入的生图模型目录快照。\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapiKey: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(providers: ReadonlyMap<string, ModelsJsonProvider>, error?: string) {\n\t\tthis.providers = providers;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(stripBom(content)));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\treturn new ModelConfig(providers);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n\n\t/**\n\t * 生图模型目录快照(供应商能力槽位设计 §3.2 推断供料):models.json 中\n\t * `output` 含 `image` 的模型按 provider 分组,供宿主在装配期经\n\t * `configOverride` 注入 image-generation 插件(注入键 `imageModelCatalog`)。\n\t * 快照为装配期静态数据;插件运行期按会话当前 provider 动态查询。内建\n\t * 聊天目录不参与——内建 images 目录走 chat modalities 协议,与插件消费的\n\t * `/images/generations` 端点协议不互通(设计 §3.2 第 4 层)。保持\n\t * models.json 登记顺序(确定性来源);无生图模型的 provider 不出现在键集中。\n\t */\n\tgetImageModelCatalog(): Readonly<Record<string, ReadonlyArray<{ id: string; name?: string }>>> {\n\t\tconst catalog: Record<string, Array<{ id: string; name?: string }>> = {};\n\t\tfor (const [providerId, provider] of this.providers) {\n\t\t\tconst imageModels = (provider.models ?? []).filter(\n\t\t\t\t(model) => Array.isArray(model.output) && model.output.includes(\"image\"),\n\t\t\t);\n\t\t\tif (imageModels.length === 0) continue;\n\t\t\tcatalog[providerId] = imageModels.map((model) => ({\n\t\t\t\tid: model.id,\n\t\t\t\t...(model.name === undefined ? {} : { name: model.name }),\n\t\t\t}));\n\t\t}\n\t\treturn deepFreeze(catalog);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAGxD,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAuK5C,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBzB,CAAC;AAEH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoBvB,CAAC;AAEH,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUxB,CAAC;AAOH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACnE,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACzE,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAsBrE,yCAAyC;AACzC,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;IACpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAE3C,OAAO,eAGN;IAED,OAAa,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAmD1E;IAED,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAE9D;IAED,cAAc,IAAI,SAAS,MAAM,EAAE,CAElC;IAED,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7B;IAED;;;;;;;;OAQG;IACH,oBAAoB,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC,CAa7F;CACD","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tsupportsFinishReason: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsAdditionalTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n\tsupportsMaxOutputTokens: Type.Optional(Type.Boolean()),\n});\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsMidConvoEffort: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n\tallowedFallbackModels: Type.Optional(\n\t\tType.Array(\n\t\t\tType.Object({\n\t\t\t\tprovider: Type.String({ minLength: 1 }),\n\t\t\t\tmodel: Type.String({ minLength: 1 }),\n\t\t\t\tcost: ModelCostSchema,\n\t\t\t}),\n\t\t\t{ maxItems: 3 },\n\t\t),\n\t),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\t// 供应商能力槽位(设计 §3.1):语义与既有 ImagesModel.output 对齐,缺省 =\n\t// 纯文本(undefined 视为 [\"text\"])。生图供应商在 models.json 登记\n\t// \"output\": [\"image\"] 的模型即进入宿主注入的生图模型目录快照。\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(providers: ReadonlyMap<string, ModelsJsonProvider>, error?: string) {\n\t\tthis.providers = providers;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(stripBom(content)));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\t// apiKey was removed from models.json: keys live in auth.json (via /login) or\n\t\t// --api-key. TypeBox objects allow additional properties, so reject explicitly.\n\t\tconst offenders = Object.entries(config.providers).filter(([, provider]) => Object.hasOwn(provider, \"apiKey\"));\n\t\tif (offenders.length > 0) {\n\t\t\tconst details = offenders\n\t\t\t\t.map(\n\t\t\t\t\t([providerId]) =>\n\t\t\t\t\t\t` - providers.${providerId}: \"apiKey\" is not allowed in models.json. Store provider keys in auth.json (via /login) or pass --api-key.`,\n\t\t\t\t)\n\t\t\t\t.join(\"\\n\");\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${details}\\n\\nFile: ${path}`);\n\t\t}\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\treturn new ModelConfig(providers);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n\n\t/**\n\t * 生图模型目录快照(供应商能力槽位设计 §3.2 推断供料):models.json 中\n\t * `output` 含 `image` 的模型按 provider 分组,供宿主在装配期经\n\t * `configOverride` 注入 image-generation 插件(注入键 `imageModelCatalog`)。\n\t * 快照为装配期静态数据;插件运行期按会话当前 provider 动态查询。内建\n\t * 聊天目录不参与——内建 images 目录走 chat modalities 协议,与插件消费的\n\t * `/images/generations` 端点协议不互通(设计 §3.2 第 4 层)。保持\n\t * models.json 登记顺序(确定性来源);无生图模型的 provider 不出现在键集中。\n\t */\n\tgetImageModelCatalog(): Readonly<Record<string, ReadonlyArray<{ id: string; name?: string }>>> {\n\t\tconst catalog: Record<string, Array<{ id: string; name?: string }>> = {};\n\t\tfor (const [providerId, provider] of this.providers) {\n\t\t\tconst imageModels = (provider.models ?? []).filter(\n\t\t\t\t(model) => Array.isArray(model.output) && model.output.includes(\"image\"),\n\t\t\t);\n\t\t\tif (imageModels.length === 0) continue;\n\t\t\tcatalog[providerId] = imageModels.map((model) => ({\n\t\t\t\tid: model.id,\n\t\t\t\t...(model.name === undefined ? {} : { name: model.name }),\n\t\t\t}));\n\t\t}\n\t\treturn deepFreeze(catalog);\n\t}\n}\n"]}
|
|
@@ -181,7 +181,6 @@ const ModelOverrideSchema = Type.Object({
|
|
|
181
181
|
const ProviderConfigSchema = Type.Object({
|
|
182
182
|
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
183
183
|
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
184
|
-
apiKey: Type.Optional(Type.String({ minLength: 1 })),
|
|
185
184
|
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
186
185
|
oauth: Type.Optional(Type.Literal("radius")),
|
|
187
186
|
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
@@ -249,6 +248,15 @@ export class ModelConfig {
|
|
|
249
248
|
return new ModelConfig(new Map(), `Invalid models.json schema:\n${errors}\n\nFile: ${path}`);
|
|
250
249
|
}
|
|
251
250
|
const config = parsed;
|
|
251
|
+
// apiKey was removed from models.json: keys live in auth.json (via /login) or
|
|
252
|
+
// --api-key. TypeBox objects allow additional properties, so reject explicitly.
|
|
253
|
+
const offenders = Object.entries(config.providers).filter(([, provider]) => Object.hasOwn(provider, "apiKey"));
|
|
254
|
+
if (offenders.length > 0) {
|
|
255
|
+
const details = offenders
|
|
256
|
+
.map(([providerId]) => ` - providers.${providerId}: "apiKey" is not allowed in models.json. Store provider keys in auth.json (via /login) or pass --api-key.`)
|
|
257
|
+
.join("\n");
|
|
258
|
+
return new ModelConfig(new Map(), `Invalid models.json schema:\n${details}\n\nFile: ${path}`);
|
|
259
|
+
}
|
|
252
260
|
const providers = new Map();
|
|
253
261
|
for (const [providerId, provider] of Object.entries(config.providers)) {
|
|
254
262
|
providers.set(providerId, deepFreeze(structuredClone(provider)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-config.js","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"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","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tsupportsFinishReason: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsAdditionalTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n\tsupportsMaxOutputTokens: Type.Optional(Type.Boolean()),\n});\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsMidConvoEffort: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n\tallowedFallbackModels: Type.Optional(\n\t\tType.Array(\n\t\t\tType.Object({\n\t\t\t\tprovider: Type.String({ minLength: 1 }),\n\t\t\t\tmodel: Type.String({ minLength: 1 }),\n\t\t\t\tcost: ModelCostSchema,\n\t\t\t}),\n\t\t\t{ maxItems: 3 },\n\t\t),\n\t),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\t// 供应商能力槽位(设计 §3.1):语义与既有 ImagesModel.output 对齐,缺省 =\n\t// 纯文本(undefined 视为 [\"text\"])。生图供应商在 models.json 登记\n\t// \"output\": [\"image\"] 的模型即进入宿主注入的生图模型目录快照。\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapiKey: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(providers: ReadonlyMap<string, ModelsJsonProvider>, error?: string) {\n\t\tthis.providers = providers;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(stripBom(content)));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\treturn new ModelConfig(providers);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n\n\t/**\n\t * 生图模型目录快照(供应商能力槽位设计 §3.2 推断供料):models.json 中\n\t * `output` 含 `image` 的模型按 provider 分组,供宿主在装配期经\n\t * `configOverride` 注入 image-generation 插件(注入键 `imageModelCatalog`)。\n\t * 快照为装配期静态数据;插件运行期按会话当前 provider 动态查询。内建\n\t * 聊天目录不参与——内建 images 目录走 chat modalities 协议,与插件消费的\n\t * `/images/generations` 端点协议不互通(设计 §3.2 第 4 层)。保持\n\t * models.json 登记顺序(确定性来源);无生图模型的 provider 不出现在键集中。\n\t */\n\tgetImageModelCatalog(): Readonly<Record<string, ReadonlyArray<{ id: string; name?: string }>>> {\n\t\tconst catalog: Record<string, Array<{ id: string; name?: string }>> = {};\n\t\tfor (const [providerId, provider] of this.providers) {\n\t\t\tconst imageModels = (provider.models ?? []).filter(\n\t\t\t\t(model) => Array.isArray(model.output) && model.output.includes(\"image\"),\n\t\t\t);\n\t\t\tif (imageModels.length === 0) continue;\n\t\t\tcatalog[providerId] = imageModels.map((model) => ({\n\t\t\t\tid: model.id,\n\t\t\t\t...(model.name === undefined ? {} : { name: model.name }),\n\t\t\t}));\n\t\t}\n\t\treturn deepFreeze(catalog);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-config.js","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"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","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tsupportsFinishReason: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsAdditionalTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n\tsupportsMaxOutputTokens: Type.Optional(Type.Boolean()),\n});\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsMidConvoEffort: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n\tallowedFallbackModels: Type.Optional(\n\t\tType.Array(\n\t\t\tType.Object({\n\t\t\t\tprovider: Type.String({ minLength: 1 }),\n\t\t\t\tmodel: Type.String({ minLength: 1 }),\n\t\t\t\tcost: ModelCostSchema,\n\t\t\t}),\n\t\t\t{ maxItems: 3 },\n\t\t),\n\t),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\t// 供应商能力槽位(设计 §3.1):语义与既有 ImagesModel.output 对齐,缺省 =\n\t// 纯文本(undefined 视为 [\"text\"])。生图供应商在 models.json 登记\n\t// \"output\": [\"image\"] 的模型即进入宿主注入的生图模型目录快照。\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(providers: ReadonlyMap<string, ModelsJsonProvider>, error?: string) {\n\t\tthis.providers = providers;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(stripBom(content)));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\t// apiKey was removed from models.json: keys live in auth.json (via /login) or\n\t\t// --api-key. TypeBox objects allow additional properties, so reject explicitly.\n\t\tconst offenders = Object.entries(config.providers).filter(([, provider]) => Object.hasOwn(provider, \"apiKey\"));\n\t\tif (offenders.length > 0) {\n\t\t\tconst details = offenders\n\t\t\t\t.map(\n\t\t\t\t\t([providerId]) =>\n\t\t\t\t\t\t` - providers.${providerId}: \"apiKey\" is not allowed in models.json. Store provider keys in auth.json (via /login) or pass --api-key.`,\n\t\t\t\t)\n\t\t\t\t.join(\"\\n\");\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${details}\\n\\nFile: ${path}`);\n\t\t}\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\treturn new ModelConfig(providers);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n\n\t/**\n\t * 生图模型目录快照(供应商能力槽位设计 §3.2 推断供料):models.json 中\n\t * `output` 含 `image` 的模型按 provider 分组,供宿主在装配期经\n\t * `configOverride` 注入 image-generation 插件(注入键 `imageModelCatalog`)。\n\t * 快照为装配期静态数据;插件运行期按会话当前 provider 动态查询。内建\n\t * 聊天目录不参与——内建 images 目录走 chat modalities 协议,与插件消费的\n\t * `/images/generations` 端点协议不互通(设计 §3.2 第 4 层)。保持\n\t * models.json 登记顺序(确定性来源);无生图模型的 provider 不出现在键集中。\n\t */\n\tgetImageModelCatalog(): Readonly<Record<string, ReadonlyArray<{ id: string; name?: string }>>> {\n\t\tconst catalog: Record<string, Array<{ id: string; name?: string }>> = {};\n\t\tfor (const [providerId, provider] of this.providers) {\n\t\t\tconst imageModels = (provider.models ?? []).filter(\n\t\t\t\t(model) => Array.isArray(model.output) && model.output.includes(\"image\"),\n\t\t\t);\n\t\t\tif (imageModels.length === 0) continue;\n\t\t\tcatalog[providerId] = imageModels.map((model) => ({\n\t\t\t\tid: model.id,\n\t\t\t\t...(model.name === undefined ? {} : { name: model.name }),\n\t\t\t}));\n\t\t}\n\t\treturn deepFreeze(catalog);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,gBAAgB,EAChB,2BAA2B,EAC3B,UAAU,EACV,OAAO,EACP,KAAK,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,EACzB,QAAQ,EACR,eAAe,EACf,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEventStream,\n\tAuthResult,\n\tContext,\n\tModel,\n\tModelsApiStreamOptions,\n\tModelsRefreshOptions,\n\tModelsRefreshResult,\n\tModelsSimpleStreamOptions,\n\tProvider,\n\tProviderHeaders,\n} from \"@agent-forge/ai\";\nimport { t } from \"./i18n/index.ts\";\nimport type { ModelRuntime } from \"./model-runtime.ts\";\nimport type { AuthStatus, ProviderConfigInput } from \"./provider-composer.ts\";\n\nexport type { ProviderConfigInput } from \"./provider-composer.ts\";\nexport type ResolvedRequestAuth =\n\t| {\n\t\t\tok: true;\n\t\t\tapiKey?: string;\n\t\t\theaders?: ProviderHeaders;\n\t\t\tbaseUrl?: string;\n\t\t\tenv?: Record<string, string>;\n\t }\n\t| { ok: false; error: string };\nexport { clearApiKeyCache } from \"./provider-composer.ts\";\n\n/**\n * Synchronous model registry facade over models.json-declared models.\n * Coding-agent internals use ModelRuntime directly.\n */\nexport class ModelRegistry {\n\tprivate readonly runtime: ModelRuntime;\n\n\tconstructor(runtime: ModelRuntime) {\n\t\tthis.runtime = runtime;\n\t}\n\n\t/** Reload models.json asynchronously. Await before making synchronous registry reads. */\n\trefresh(options?: ModelsRefreshOptions): Promise<ModelsRefreshResult> {\n\t\treturn this.runtime.refresh(options);\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.runtime.getError();\n\t}\n\n\tgetAll(): Model<Api>[] {\n\t\treturn [...this.runtime.getModels()];\n\t}\n\n\tgetAvailable(): Model<Api>[] {\n\t\treturn [...this.runtime.getAvailableSnapshot()];\n\t}\n\n\tfind(provider: string, modelId: string): Model<Api> | undefined {\n\t\treturn this.runtime.getModel(provider, modelId);\n\t}\n\n\thasConfiguredAuth(model: Model<Api>): boolean {\n\t\treturn this.runtime.hasConfiguredAuth(model.provider);\n\t}\n\n\tasync getApiKeyAndHeaders(model: Model<Api>): Promise<ResolvedRequestAuth> {\n\t\ttry {\n\t\t\tconst resolution = await this.runtime.getAuth(model);\n\t\t\tif (!resolution) {\n\t\t\t\tconst compatibility = this.runtime.getCompatibilityRequestConfig(model);\n\t\t\t\tif (compatibility.authHeader) {\n\t\t\t\t\treturn { ok: false, error: `No API key found for \"${model.provider}\"` };\n\t\t\t\t}\n\t\t\t\treturn { ok: true, headers: compatibility.headers };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tapiKey: resolution.auth.apiKey,\n\t\t\t\theaders: resolution.auth.headers,\n\t\t\t\t...(resolution.auth.baseUrl ? { baseUrl: resolution.auth.baseUrl } : {}),\n\t\t\t\tenv: resolution.env,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst cause = error instanceof Error ? error.cause : undefined;\n\t\t\tconst message =\n\t\t\t\tcause instanceof Error ? cause.message : error instanceof Error ? error.message : String(error);\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror:\n\t\t\t\t\tmessage === \"authHeader requires a resolved API key\"\n\t\t\t\t\t\t? `No API key found for \"${model.provider}\"`\n\t\t\t\t\t\t: message,\n\t\t\t};\n\t\t}\n\t}\n\n\tgetProviderAuthStatus(provider: string): AuthStatus {\n\t\treturn this.runtime.getProviderAuthStatus(provider);\n\t}\n\n\tgetProvider(provider: string): Provider | undefined {\n\t\treturn this.runtime.getProvider(provider);\n\t}\n\n\t/** Stream through the configured provider with request-time authentication. */\n\tstream<TApi extends Api>(\n\t\tmodel: Model<TApi>,\n\t\tcontext: Context,\n\t\toptions?: ModelsApiStreamOptions<TApi>,\n\t): AssistantMessageEventStream {\n\t\treturn this.runtime.stream(model, context, options);\n\t}\n\n\tcomplete<TApi extends Api>(\n\t\tmodel: Model<TApi>,\n\t\tcontext: Context,\n\t\toptions?: ModelsApiStreamOptions<TApi>,\n\t): Promise<AssistantMessage> {\n\t\treturn this.runtime.complete(model, context, options);\n\t}\n\n\t/** Stream with provider-neutral options and request-time authentication. */\n\tstreamSimple(model: Model<Api>, context: Context, options?: ModelsSimpleStreamOptions): AssistantMessageEventStream {\n\t\treturn this.runtime.streamSimple(model, context, options);\n\t}\n\n\tgetProviderDisplayName(provider: string): string {\n\t\treturn this.runtime.getProvider(provider)?.name ?? provider;\n\t}\n\n\tgetProviderAuth(provider: string): Promise<AuthResult | undefined> {\n\t\treturn this.runtime.getAuth(provider);\n\t}\n\n\tasync getApiKeyForProvider(provider: string): Promise<string | undefined> {\n\t\ttry {\n\t\t\treturn (await this.runtime.getAuth(provider))?.auth.apiKey;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tisUsingOAuth(model: Model<Api>): boolean {\n\t\treturn this.runtime.isUsingOAuth(model.provider);\n\t}\n\n\tregisterProvider(provider: Provider): void;\n\tregisterProvider(providerName: string, config: ProviderConfigInput): void;\n\tregisterProvider(providerOrName: Provider | string, config?: ProviderConfigInput): void {\n\t\tif (typeof providerOrName === \"string\") {\n\t\t\tif (!config) throw new Error(t(\"Provider config is required when registering by name\"));\n\t\t\tthis.runtime.registerProvider(providerOrName, config);\n\t\t\treturn;\n\t\t}\n\t\tthis.runtime.registerNativeProvider(providerOrName);\n\t}\n\n\tunregisterProvider(providerName: string): void {\n\t\tthis.runtime.unregisterProvider(providerName);\n\t}\n\n\tgetRegisteredProviderConfig(providerName: string): ProviderConfigInput | undefined {\n\t\treturn this.runtime.getRegisteredProviderConfig(providerName);\n\t}\n\n\tgetRegisteredNativeProvider(providerName: string): Provider | undefined {\n\t\treturn this.runtime.getRegisteredNativeProvider(providerName);\n\t}\n\n\tgetRegisteredProviderIds(): readonly string[] {\n\t\treturn this.runtime.getRegisteredProviderIds();\n\t}\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t } from "./i18n/index.js";
|
|
1
2
|
export { clearApiKeyCache } from "./provider-composer.js";
|
|
2
3
|
/**
|
|
3
4
|
* Synchronous model registry facade over models.json-declared models.
|
|
@@ -93,7 +94,7 @@ export class ModelRegistry {
|
|
|
93
94
|
registerProvider(providerOrName, config) {
|
|
94
95
|
if (typeof providerOrName === "string") {
|
|
95
96
|
if (!config)
|
|
96
|
-
throw new Error("Provider config is required when registering by name");
|
|
97
|
+
throw new Error(t("Provider config is required when registering by name"));
|
|
97
98
|
this.runtime.registerProvider(providerOrName, config);
|
|
98
99
|
return;
|
|
99
100
|
}
|