@ai-agent-forge/agent-forge 0.86.6 → 0.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -1
- package/README.md +8 -9
- package/dist/artifacts/artifact-store.d.ts.map +1 -1
- package/dist/artifacts/artifact-store.js +9 -5
- package/dist/artifacts/artifact-store.js.map +1 -1
- package/dist/bundle/.build-manifest.json +410 -371
- package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
- package/dist/bundle/chunks/chunk-BFC2BDVJ.js +13 -0
- package/dist/bundle/chunks/chunk-MOHOLL3F.js +1456 -0
- package/dist/bundle/chunks/image-resize-worker.js +12 -1
- package/dist/bundle/chunks/{virtual-modules-3IZ4MYSQ.js → virtual-modules-KZ5DRH7Q.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/client.js +1 -1
- package/dist/bundle/index.js +2 -2
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +231 -185
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts.map +1 -1
- package/dist/cli/auth-check.js +3 -2
- package/dist/cli/auth-check.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js +15 -9
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +14 -7
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/command.d.ts.map +1 -1
- package/dist/cli/experimental/command.js +6 -5
- package/dist/cli/experimental/command.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +9 -8
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/plugin-manager-controller.d.ts.map +1 -1
- package/dist/cli/plugin-manager-controller.js +2 -1
- package/dist/cli/plugin-manager-controller.js.map +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +8 -5
- package/dist/cli/serve.js.map +1 -1
- package/dist/client/remote-session.d.ts.map +1 -1
- package/dist/client/remote-session.js +16 -9
- package/dist/client/remote-session.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-capability-contract.d.ts +0 -7
- package/dist/core/agent-capability-contract.d.ts.map +1 -1
- package/dist/core/agent-capability-contract.js +72 -68
- package/dist/core/agent-capability-contract.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +5 -4
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +28 -22
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-context.d.ts.map +1 -1
- package/dist/core/agent-session-context.js +18 -13
- package/dist/core/agent-session-context.js.map +1 -1
- package/dist/core/agent-session-model.d.ts.map +1 -1
- package/dist/core/agent-session-model.js +2 -1
- package/dist/core/agent-session-model.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +3 -2
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +7 -6
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-tools.d.ts.map +1 -1
- package/dist/core/agent-session-tools.js +3 -2
- package/dist/core/agent-session-tools.js.map +1 -1
- package/dist/core/agent-session.d.ts +40 -2
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +142 -34
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +11 -5
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +9 -6
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +2 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/embedded-sdk.d.ts.map +1 -1
- package/dist/core/embedded-sdk.js +10 -6
- package/dist/core/embedded-sdk.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +9 -4
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/extensions/agent-composition.d.ts.map +1 -1
- package/dist/core/extensions/agent-composition.js +26 -19
- package/dist/core/extensions/agent-composition.js.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.js +3 -2
- package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
- package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-lifecycle.js +20 -17
- package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
- package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-overflow-policy.js +2 -1
- package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -1
- package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-retry-policy.js +2 -1
- package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -1
- package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-skills.js +7 -6
- package/dist/core/extensions/bootstrap-skills.js.map +1 -1
- package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-tools.js +2 -1
- package/dist/core/extensions/bootstrap-tools.js.map +1 -1
- package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
- package/dist/core/extensions/capability-plugin.js +37 -13
- package/dist/core/extensions/capability-plugin.js.map +1 -1
- package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-events.js +17 -13
- package/dist/core/extensions/capability-runtime-events.js.map +1 -1
- package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-guards.js +16 -15
- package/dist/core/extensions/capability-runtime-guards.js.map +1 -1
- package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-manifest.js +52 -30
- package/dist/core/extensions/capability-runtime-manifest.js.map +1 -1
- package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-validation.js +66 -65
- package/dist/core/extensions/capability-runtime-validation.js.map +1 -1
- package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime.js +147 -127
- package/dist/core/extensions/capability-runtime.js.map +1 -1
- package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -1
- package/dist/core/extensions/compaction-memory-failure-mode.js +3 -2
- package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -1
- package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -1
- package/dist/core/extensions/context-strategy-binding.js +7 -4
- package/dist/core/extensions/context-strategy-binding.js.map +1 -1
- package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
- package/dist/core/extensions/lifecycle-catalog.js +290 -279
- package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
- package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -1
- package/dist/core/extensions/lifecycle-delivery-queue.js +3 -2
- package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -1
- package/dist/core/facade/coding-agent-facade.d.ts +6 -0
- package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
- package/dist/core/facade/coding-agent-facade.js +2 -0
- package/dist/core/facade/coding-agent-facade.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/i18n/index.d.ts +14 -0
- package/dist/core/i18n/index.d.ts.map +1 -0
- package/dist/core/i18n/index.js +67 -0
- package/dist/core/i18n/index.js.map +1 -0
- package/dist/core/i18n/locales/en/example.d.ts +7 -0
- package/dist/core/i18n/locales/en/example.d.ts.map +1 -0
- package/dist/core/i18n/locales/en/example.js +7 -0
- package/dist/core/i18n/locales/en/example.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/cli.d.ts +8 -0
- package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/cli.js +227 -0
- package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/common.d.ts +6 -0
- package/dist/core/i18n/locales/zh-cn/common.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/common.js +6 -0
- package/dist/core/i18n/locales/zh-cn/common.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +13 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js +173 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts +12 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +582 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.js +55 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts +11 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +455 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.js +191 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/example.d.ts +7 -0
- package/dist/core/i18n/locales/zh-cn/example.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/example.js +10 -0
- package/dist/core/i18n/locales/zh-cn/example.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/index.d.ts +2 -0
- package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/index.js +41 -0
- package/dist/core/i18n/locales/zh-cn/index.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts +10 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js +265 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.d.ts +11 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.js +67 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts +7 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.js +39 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts +10 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.js +15 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts +13 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +102 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts +12 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js +288 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js +79 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts +8 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.js +72 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.js.map +1 -0
- package/dist/core/keybindings.d.ts +15 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +18 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +5 -1
- package/dist/core/logger.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +8 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-install-host.d.ts.map +1 -1
- package/dist/core/package-install-host.js +4 -3
- package/dist/core/package-install-host.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +15 -10
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-resource-collection.d.ts.map +1 -1
- package/dist/core/package-resource-collection.js +2 -1
- package/dist/core/package-resource-collection.js.map +1 -1
- package/dist/core/package-source.d.ts.map +1 -1
- package/dist/core/package-source.js +3 -2
- package/dist/core/package-source.js.map +1 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +22 -13
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +6 -2
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +15 -5
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/sdk.d.ts +19 -5
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +74 -54
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +5 -2
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +2 -1
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +39 -29
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-storage.d.ts.map +1 -1
- package/dist/core/session-storage.js +3 -3
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/settings-manager.d.ts +11 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +27 -5
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +53 -32
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +25 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +11 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +9 -4
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +3 -2
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +2 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +6 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/durable/durable-service.d.ts.map +1 -1
- package/dist/durable/durable-service.js +25 -18
- package/dist/durable/durable-service.js.map +1 -1
- package/dist/host/checkpoint-commit.d.ts.map +1 -1
- package/dist/host/checkpoint-commit.js +2 -1
- package/dist/host/checkpoint-commit.js.map +1 -1
- package/dist/host/manual-compaction.d.ts.map +1 -1
- package/dist/host/manual-compaction.js +2 -1
- package/dist/host/manual-compaction.js.map +1 -1
- package/dist/host/output-projection.d.ts +0 -13
- package/dist/host/output-projection.d.ts.map +1 -1
- package/dist/host/output-projection.js +16 -2
- package/dist/host/output-projection.js.map +1 -1
- package/dist/host/summary-retry.d.ts.map +1 -1
- package/dist/host/summary-retry.js +3 -2
- package/dist/host/summary-retry.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +94 -58
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
- package/dist/modes/interactive/components/agents-view.js +18 -15
- package/dist/modes/interactive/components/agents-view.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +6 -5
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +12 -7
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +2 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +6 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +9 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +18 -15
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +2 -1
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-editor.js +5 -4
- package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
- package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-input.js +2 -1
- package/dist/modes/interactive/components/dialog-input.js.map +1 -1
- package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-selector.js +4 -3
- package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +11 -10
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +7 -4
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +3 -2
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +12 -11
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
- package/dist/modes/interactive/components/mermaid.js +6 -2
- package/dist/modes/interactive/components/mermaid.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +28 -16
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +10 -9
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/plugin-manager-entry.js +22 -13
- package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
- package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/plugin-selection-entry.js +27 -12
- package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
- package/dist/modes/interactive/components/queue-manager-selector.d.ts +60 -0
- package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/queue-manager-selector.js +166 -0
- package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +16 -14
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +43 -31
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +113 -96
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.js +5 -4
- package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +3 -2
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +4 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +14 -5
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +2 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +11 -4
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +8 -3
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-list.js +7 -6
- package/dist/modes/interactive/components/tree-list.js.map +1 -1
- package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-render.js +28 -23
- package/dist/modes/interactive/components/tree-render.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +9 -7
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +5 -4
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
- package/dist/modes/interactive/components/workflow-view.js +36 -21
- package/dist/modes/interactive/components/workflow-view.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +2 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-auth.js +71 -40
- package/dist/modes/interactive/interactive-auth.js.map +1 -1
- package/dist/modes/interactive/interactive-commands.d.ts +1 -0
- package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-commands.js +3 -0
- package/dist/modes/interactive/interactive-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-dialog-ui.js +5 -5
- package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-format.js +34 -18
- package/dist/modes/interactive/interactive-format.js.map +1 -1
- package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-helpers.js +7 -2
- package/dist/modes/interactive/interactive-helpers.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +327 -243
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.d.ts +9 -0
- package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +79 -25
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +5 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +26 -23
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +3 -2
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +3 -2
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +28 -13
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/plugins/ecosystem/catalog.d.ts.map +1 -1
- package/dist/plugins/ecosystem/catalog.js +3 -2
- package/dist/plugins/ecosystem/catalog.js.map +1 -1
- package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
- package/dist/plugins/ecosystem/cli.js +2 -1
- package/dist/plugins/ecosystem/cli.js.map +1 -1
- package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -1
- package/dist/plugins/ecosystem/default-plugin-market.js +3 -2
- package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -1
- package/dist/plugins/ecosystem/distribution.d.ts.map +1 -1
- package/dist/plugins/ecosystem/distribution.js +2 -1
- package/dist/plugins/ecosystem/distribution.js.map +1 -1
- package/dist/plugins/ecosystem/installer.d.ts.map +1 -1
- package/dist/plugins/ecosystem/installer.js +3 -2
- package/dist/plugins/ecosystem/installer.js.map +1 -1
- package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-disk-registry-source.js +20 -17
- package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-distribution-host.js +35 -34
- package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.js +35 -34
- package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.js +9 -8
- package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-persistence.js +4 -3
- package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js +21 -5
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-trust-root.js +10 -9
- package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -1
- package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-registry-source.js +31 -30
- package/dist/plugins/ecosystem/node-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-release-package-source.js +30 -29
- package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-tar-writer.js +11 -10
- package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -1
- package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-url-package-source.js +21 -20
- package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -1
- package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -1
- package/dist/plugins/ecosystem/plugin-acquisition.js +3 -2
- package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.js +2 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -1
- package/dist/plugins/ecosystem/registry.d.ts.map +1 -1
- package/dist/plugins/ecosystem/registry.js +35 -32
- package/dist/plugins/ecosystem/registry.js.map +1 -1
- package/dist/plugins/ecosystem/resolver.d.ts.map +1 -1
- package/dist/plugins/ecosystem/resolver.js +3 -2
- package/dist/plugins/ecosystem/resolver.js.map +1 -1
- package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -1
- package/dist/plugins/ecosystem/selection-store.js +11 -10
- package/dist/plugins/ecosystem/selection-store.js.map +1 -1
- package/dist/plugins/ecosystem/selection.d.ts.map +1 -1
- package/dist/plugins/ecosystem/selection.js +8 -7
- package/dist/plugins/ecosystem/selection.js.map +1 -1
- package/dist/plugins/ecosystem/state.d.ts.map +1 -1
- package/dist/plugins/ecosystem/state.js +24 -23
- package/dist/plugins/ecosystem/state.js.map +1 -1
- package/dist/plugins/ecosystem/updates.d.ts.map +1 -1
- package/dist/plugins/ecosystem/updates.js +5 -4
- package/dist/plugins/ecosystem/updates.js.map +1 -1
- package/dist/plugins/mcp-http.d.ts +0 -17
- package/dist/plugins/mcp-http.d.ts.map +1 -1
- package/dist/plugins/mcp-http.js +30 -7
- package/dist/plugins/mcp-http.js.map +1 -1
- package/dist/plugins/plugin-supervisor.d.ts.map +1 -1
- package/dist/plugins/plugin-supervisor.js +19 -1
- package/dist/plugins/plugin-supervisor.js.map +1 -1
- package/dist/profile/first-roles.d.ts.map +1 -1
- package/dist/profile/first-roles.js +10 -1
- package/dist/profile/first-roles.js.map +1 -1
- package/dist/profile/goal-plugin.d.ts.map +1 -1
- package/dist/profile/goal-plugin.js +24 -5
- package/dist/profile/goal-plugin.js.map +1 -1
- package/dist/profile/identity.d.ts.map +1 -1
- package/dist/profile/identity.js +7 -6
- package/dist/profile/identity.js.map +1 -1
- package/dist/profile/lock.d.ts.map +1 -1
- package/dist/profile/lock.js +15 -1
- package/dist/profile/lock.js.map +1 -1
- package/dist/profile/plan-plugin.d.ts.map +1 -1
- package/dist/profile/plan-plugin.js +26 -13
- package/dist/profile/plan-plugin.js.map +1 -1
- package/dist/profile/plugin-profiles.d.ts.map +1 -1
- package/dist/profile/plugin-profiles.js +2 -1
- package/dist/profile/plugin-profiles.js.map +1 -1
- package/dist/profile/policy-manifest.d.ts.map +1 -1
- package/dist/profile/policy-manifest.js +5 -4
- package/dist/profile/policy-manifest.js.map +1 -1
- package/dist/profile/profile-registry.d.ts +0 -12
- package/dist/profile/profile-registry.d.ts.map +1 -1
- package/dist/profile/profile-registry.js +14 -1
- package/dist/profile/profile-registry.js.map +1 -1
- package/dist/profile/role-catalog.d.ts +0 -1
- package/dist/profile/role-catalog.d.ts.map +1 -1
- package/dist/profile/role-catalog.js +17 -15
- package/dist/profile/role-catalog.js.map +1 -1
- package/dist/profile/role-orchestrator.d.ts.map +1 -1
- package/dist/profile/role-orchestrator.js +8 -7
- package/dist/profile/role-orchestrator.js.map +1 -1
- package/dist/profile/role-runner.d.ts.map +1 -1
- package/dist/profile/role-runner.js +3 -2
- package/dist/profile/role-runner.js.map +1 -1
- package/dist/profile/root-facade.d.ts.map +1 -1
- package/dist/profile/root-facade.js +2 -1
- package/dist/profile/root-facade.js.map +1 -1
- package/dist/profile/skill-discovery-wiring.d.ts.map +1 -1
- package/dist/profile/skill-discovery-wiring.js +7 -2
- package/dist/profile/skill-discovery-wiring.js.map +1 -1
- package/dist/profile/state-store.d.ts.map +1 -1
- package/dist/profile/state-store.js +13 -9
- package/dist/profile/state-store.js.map +1 -1
- package/dist/profile/todo-plugin.d.ts.map +1 -1
- package/dist/profile/todo-plugin.js +9 -4
- package/dist/profile/todo-plugin.js.map +1 -1
- package/dist/profiles/builtin-suites.d.ts +13 -6
- package/dist/profiles/builtin-suites.d.ts.map +1 -1
- package/dist/profiles/builtin-suites.js +15 -6
- package/dist/profiles/builtin-suites.js.map +1 -1
- package/dist/profiles/suite-loader.d.ts +25 -1
- package/dist/profiles/suite-loader.d.ts.map +1 -1
- package/dist/profiles/suite-loader.js +34 -9
- package/dist/profiles/suite-loader.js.map +1 -1
- package/dist/remote/server-entry.d.ts.map +1 -1
- package/dist/remote/server-entry.js +3 -2
- package/dist/remote/server-entry.js.map +1 -1
- package/dist/remote/session-source.d.ts.map +1 -1
- package/dist/remote/session-source.js +8 -4
- package/dist/remote/session-source.js.map +1 -1
- package/dist/share/session-share.d.ts.map +1 -1
- package/dist/share/session-share.js +14 -2
- package/dist/share/session-share.js.map +1 -1
- package/dist/testing/plugin-testkit.d.ts.map +1 -1
- package/dist/testing/plugin-testkit.js +4 -3
- package/dist/testing/plugin-testkit.js.map +1 -1
- package/dist/testing/runtime-delivery-queue.d.ts.map +1 -1
- package/dist/testing/runtime-delivery-queue.js +2 -1
- package/dist/testing/runtime-delivery-queue.js.map +1 -1
- package/dist/testing/session-plugin-testkit.d.ts.map +1 -1
- package/dist/testing/session-plugin-testkit.js +10 -7
- package/dist/testing/session-plugin-testkit.js.map +1 -1
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js +2 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +7 -6
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js +3 -2
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +9 -8
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +23 -13
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +5 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/keybindings.md +3 -0
- package/docs/quickstart.md +1 -1
- package/docs/settings.md +1 -0
- package/docs/terminal-setup.md +2 -3
- package/docs/usage.md +6 -5
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/with-deps/plugin.json +1 -1
- package/package.json +1 -1
- package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t } from "../../core/i18n/index.js";
|
|
1
2
|
const NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1 = 1;
|
|
2
3
|
const DEFAULT_TIMEOUT_MS_V1 = 15_000;
|
|
3
4
|
const MAX_TIMEOUT_MS_V1 = 120_000;
|
|
@@ -18,7 +19,7 @@ export class NodeHttpPluginRegistrySourceErrorV1 extends Error {
|
|
|
18
19
|
function boundedPositive(value, fallback, maximum, label) {
|
|
19
20
|
const result = value ?? fallback;
|
|
20
21
|
if (!Number.isSafeInteger(result) || result <= 0 || result > maximum) {
|
|
21
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",
|
|
22
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("{label} must be a positive integer at most {maximum}", { label, maximum }));
|
|
22
23
|
}
|
|
23
24
|
return result;
|
|
24
25
|
}
|
|
@@ -28,13 +29,13 @@ function allowedOrigin(value) {
|
|
|
28
29
|
parsed = new URL(value);
|
|
29
30
|
}
|
|
30
31
|
catch {
|
|
31
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Allowed registry origin is invalid");
|
|
32
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Allowed registry origin is invalid"));
|
|
32
33
|
}
|
|
33
34
|
if ((parsed.protocol !== "http:" && parsed.protocol !== "https:") || parsed.username || parsed.password) {
|
|
34
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Allowed registry origin must be an http(s) origin without credentials");
|
|
35
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Allowed registry origin must be an http(s) origin without credentials"));
|
|
35
36
|
}
|
|
36
37
|
if (parsed.pathname !== "/" || parsed.search !== "" || parsed.hash !== "") {
|
|
37
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Allowed registry origin must not include a path, query, or fragment");
|
|
38
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Allowed registry origin must not include a path, query, or fragment"));
|
|
38
39
|
}
|
|
39
40
|
return parsed.origin;
|
|
40
41
|
}
|
|
@@ -44,16 +45,16 @@ function endpointUrl(value, origins) {
|
|
|
44
45
|
parsed = new URL(value);
|
|
45
46
|
}
|
|
46
47
|
catch {
|
|
47
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Plugin registry URL is invalid");
|
|
48
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Plugin registry URL is invalid"));
|
|
48
49
|
}
|
|
49
50
|
if ((parsed.protocol !== "http:" && parsed.protocol !== "https:") || parsed.username || parsed.password) {
|
|
50
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Plugin registry URL must use http(s) without credentials");
|
|
51
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Plugin registry URL must use http(s) without credentials"));
|
|
51
52
|
}
|
|
52
53
|
if (parsed.search !== "" || parsed.hash !== "") {
|
|
53
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Plugin registry URL must not include a query or fragment");
|
|
54
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Plugin registry URL must not include a query or fragment"));
|
|
54
55
|
}
|
|
55
56
|
if (!origins.has(parsed.origin)) {
|
|
56
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Plugin registry origin is not allowed");
|
|
57
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Plugin registry origin is not allowed"));
|
|
57
58
|
}
|
|
58
59
|
return parsed;
|
|
59
60
|
}
|
|
@@ -62,11 +63,11 @@ function responseLength(response) {
|
|
|
62
63
|
if (raw === null)
|
|
63
64
|
return undefined;
|
|
64
65
|
if (!/^\d+$/u.test(raw)) {
|
|
65
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", "Plugin registry response length is invalid");
|
|
66
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", t("Plugin registry response length is invalid"));
|
|
66
67
|
}
|
|
67
68
|
const value = Number(raw);
|
|
68
69
|
if (!Number.isSafeInteger(value)) {
|
|
69
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", "Plugin registry response length is invalid");
|
|
70
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", t("Plugin registry response length is invalid"));
|
|
70
71
|
}
|
|
71
72
|
return value;
|
|
72
73
|
}
|
|
@@ -132,7 +133,7 @@ function discardResponseBody(response) {
|
|
|
132
133
|
}
|
|
133
134
|
async function readBody(response, maxBytes, signal) {
|
|
134
135
|
if (response.body === null) {
|
|
135
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", "Plugin registry response has no body");
|
|
136
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", t("Plugin registry response has no body"));
|
|
136
137
|
}
|
|
137
138
|
const reader = response.body.getReader();
|
|
138
139
|
const chunks = [];
|
|
@@ -140,13 +141,13 @@ async function readBody(response, maxBytes, signal) {
|
|
|
140
141
|
try {
|
|
141
142
|
for (;;) {
|
|
142
143
|
if (signal.aborted)
|
|
143
|
-
throw new DOMException("aborted", "AbortError");
|
|
144
|
+
throw new DOMException(t("aborted"), "AbortError");
|
|
144
145
|
const item = await awaitBeforeAbort(reader.read(), signal);
|
|
145
146
|
if (item.done)
|
|
146
147
|
break;
|
|
147
148
|
total += item.value.byteLength;
|
|
148
149
|
if (total > maxBytes) {
|
|
149
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large", "Plugin registry response exceeds the configured size limit");
|
|
150
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large", t("Plugin registry response exceeds the configured size limit"));
|
|
150
151
|
}
|
|
151
152
|
chunks.push(item.value);
|
|
152
153
|
}
|
|
@@ -168,16 +169,16 @@ function parseDocument(bytes) {
|
|
|
168
169
|
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
169
170
|
}
|
|
170
171
|
catch {
|
|
171
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", "Plugin registry response is not valid JSON");
|
|
172
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", t("Plugin registry response is not valid JSON"));
|
|
172
173
|
}
|
|
173
174
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
174
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", "Plugin registry document is invalid");
|
|
175
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", t("Plugin registry document is invalid"));
|
|
175
176
|
}
|
|
176
177
|
const document = value;
|
|
177
178
|
if (Object.keys(document).some((key) => key !== "version" && key !== "entries") ||
|
|
178
179
|
document.version !== 1 ||
|
|
179
180
|
!Array.isArray(document.entries)) {
|
|
180
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", "Plugin registry document is invalid");
|
|
181
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", t("Plugin registry document is invalid"));
|
|
181
182
|
}
|
|
182
183
|
return document.entries;
|
|
183
184
|
}
|
|
@@ -195,9 +196,9 @@ function sanitizedSourceError(error) {
|
|
|
195
196
|
code !== "request_timed_out" &&
|
|
196
197
|
code !== "invalid_response" &&
|
|
197
198
|
code !== "response_too_large") {
|
|
198
|
-
return new NodeHttpPluginRegistrySourceErrorV1("request_failed", "Plugin registry request failed");
|
|
199
|
+
return new NodeHttpPluginRegistrySourceErrorV1("request_failed", t("Plugin registry request failed"));
|
|
199
200
|
}
|
|
200
|
-
return new NodeHttpPluginRegistrySourceErrorV1(code, "Plugin registry request failed");
|
|
201
|
+
return new NodeHttpPluginRegistrySourceErrorV1(code, t("Plugin registry request failed"));
|
|
201
202
|
}
|
|
202
203
|
/**
|
|
203
204
|
* Creates a bounded, allowlisted HTTP registry reader. It only transports
|
|
@@ -207,10 +208,10 @@ function sanitizedSourceError(error) {
|
|
|
207
208
|
export function createNodeHttpPluginRegistrySourceV1(options) {
|
|
208
209
|
const transport = options.fetch ?? globalThis.fetch;
|
|
209
210
|
if (typeof transport !== "function") {
|
|
210
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "Node fetch is unavailable");
|
|
211
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("Node fetch is unavailable"));
|
|
211
212
|
}
|
|
212
213
|
if (!Array.isArray(options.allowedOrigins) || options.allowedOrigins.length === 0) {
|
|
213
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "At least one allowed registry origin is required");
|
|
214
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("At least one allowed registry origin is required"));
|
|
214
215
|
}
|
|
215
216
|
const origins = new Set(options.allowedOrigins.map(allowedOrigin));
|
|
216
217
|
const endpoint = endpointUrl(options.url, origins);
|
|
@@ -218,7 +219,7 @@ export function createNodeHttpPluginRegistrySourceV1(options) {
|
|
|
218
219
|
const maxResponseBytes = boundedPositive(options.maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES_V1, MAX_RESPONSE_BYTES_V1, "maxResponseBytes");
|
|
219
220
|
const userAgent = options.userAgent ?? "agent-forge-plugin-registry/1";
|
|
220
221
|
if (userAgent.length === 0 || userAgent.length > 256 || /[\r\n]/u.test(userAgent)) {
|
|
221
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", "userAgent is invalid");
|
|
222
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration", t("userAgent is invalid"));
|
|
222
223
|
}
|
|
223
224
|
const source = endpoint.origin + endpoint.pathname;
|
|
224
225
|
return {
|
|
@@ -226,14 +227,14 @@ export function createNodeHttpPluginRegistrySourceV1(options) {
|
|
|
226
227
|
source,
|
|
227
228
|
list: async ({ signal } = {}) => {
|
|
228
229
|
if (isCallerCancelled(signal)) {
|
|
229
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("cancelled", "Plugin registry request was cancelled");
|
|
230
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("cancelled", t("Plugin registry request was cancelled"));
|
|
230
231
|
}
|
|
231
232
|
const request = requestController(signal, timeoutMs);
|
|
232
233
|
let response;
|
|
233
234
|
try {
|
|
234
235
|
const transportResponse = Promise.resolve().then(() => {
|
|
235
236
|
if (request.signal.aborted)
|
|
236
|
-
throw new DOMException("aborted", "AbortError");
|
|
237
|
+
throw new DOMException(t("aborted"), "AbortError");
|
|
237
238
|
return transport(endpoint.toString(), {
|
|
238
239
|
method: "GET",
|
|
239
240
|
headers: {
|
|
@@ -251,30 +252,30 @@ export function createNodeHttpPluginRegistrySourceV1(options) {
|
|
|
251
252
|
const receivedResponse = await awaitBeforeAbort(transportResponse, request.signal);
|
|
252
253
|
response = receivedResponse;
|
|
253
254
|
if (receivedResponse.status < 200 || receivedResponse.status >= 300) {
|
|
254
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("request_failed", "Plugin registry request did not succeed");
|
|
255
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("request_failed", t("Plugin registry request did not succeed"));
|
|
255
256
|
}
|
|
256
257
|
if (!isJsonResponse(receivedResponse)) {
|
|
257
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", "Plugin registry response must be JSON");
|
|
258
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response", t("Plugin registry response must be JSON"));
|
|
258
259
|
}
|
|
259
260
|
const length = responseLength(receivedResponse);
|
|
260
261
|
if (length !== undefined && length > maxResponseBytes) {
|
|
261
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large", "Plugin registry response exceeds the configured size limit");
|
|
262
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large", t("Plugin registry response exceeds the configured size limit"));
|
|
262
263
|
}
|
|
263
264
|
return parseDocument(await readBody(receivedResponse, maxResponseBytes, request.signal));
|
|
264
265
|
}
|
|
265
266
|
catch (error) {
|
|
266
267
|
if (isCallerCancelled(signal)) {
|
|
267
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("cancelled", "Plugin registry request was cancelled");
|
|
268
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("cancelled", t("Plugin registry request was cancelled"));
|
|
268
269
|
}
|
|
269
270
|
if (request.timedOut()) {
|
|
270
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("request_timed_out", "Plugin registry request timed out");
|
|
271
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("request_timed_out", t("Plugin registry request timed out"));
|
|
271
272
|
}
|
|
272
273
|
if (error instanceof NodeHttpPluginRegistrySourceErrorV1)
|
|
273
274
|
throw sanitizedSourceError(error);
|
|
274
275
|
if (isAbortLike(error)) {
|
|
275
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("cancelled", "Plugin registry request was cancelled");
|
|
276
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("cancelled", t("Plugin registry request was cancelled"));
|
|
276
277
|
}
|
|
277
|
-
throw new NodeHttpPluginRegistrySourceErrorV1("request_failed", "Plugin registry request failed");
|
|
278
|
+
throw new NodeHttpPluginRegistrySourceErrorV1("request_failed", t("Plugin registry request failed"));
|
|
278
279
|
}
|
|
279
280
|
finally {
|
|
280
281
|
request.cleanup();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-registry-source.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-registry-source.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PluginRegistryManifestEnvelopeV1, PluginRegistrySourceV1 } from \"./registry.ts\";\n\nconst NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1 = 1 as const;\nconst DEFAULT_TIMEOUT_MS_V1 = 15_000;\nconst MAX_TIMEOUT_MS_V1 = 120_000;\nconst DEFAULT_MAX_RESPONSE_BYTES_V1 = 4 * 1024 * 1024;\nconst MAX_RESPONSE_BYTES_V1 = 8 * 1024 * 1024;\n\nexport type NodeHttpPluginRegistrySourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"request_failed\"\n\t| \"request_timed_out\"\n\t| \"invalid_response\"\n\t| \"response_too_large\";\n\n/**\n * Deliberately does not retain transport exceptions or response bodies: callers\n * must not turn registry diagnostics into a credential or path disclosure.\n */\nexport class NodeHttpPluginRegistrySourceErrorV1 extends Error {\n\treadonly code: NodeHttpPluginRegistrySourceErrorCodeV1;\n\n\tconstructor(code: NodeHttpPluginRegistrySourceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeHttpPluginRegistrySourceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface NodeHttpPluginRegistrySourceOptionsV1 {\n\t/** Absolute endpoint returning the versioned JSON registry document. */\n\treadonly url: string | URL;\n\t/** Exact http(s) origins the host has intentionally allowed. */\n\treadonly allowedOrigins: readonly string[];\n\t/** Real fetch or deterministic test replacement. */\n\treadonly fetch?: typeof globalThis.fetch;\n\treadonly requestTimeoutMs?: number;\n\treadonly maxResponseBytes?: number;\n\treadonly userAgent?: string;\n}\n\nexport interface NodeHttpPluginRegistrySourceV1 extends PluginRegistrySourceV1 {\n\treadonly version: typeof NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1;\n\t/** Sanitized endpoint identity: never contains credentials, query, or fragment. */\n\treadonly source: string;\n}\n\ninterface RegistryDocumentV1 {\n\treadonly version: 1;\n\treadonly entries: readonly PluginRegistryManifestEnvelopeV1[];\n}\n\nfunction boundedPositive(value: number | undefined, fallback: number, maximum: number, label: string): number {\n\tconst result = value ?? fallback;\n\tif (!Number.isSafeInteger(result) || result <= 0 || result > maximum) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t`${label} must be a positive integer at most ${maximum}`,\n\t\t);\n\t}\n\treturn result;\n}\n\nfunction allowedOrigin(value: string): string {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", \"Allowed registry origin is invalid\");\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t\"Allowed registry origin must be an http(s) origin without credentials\",\n\t\t);\n\t}\n\tif (parsed.pathname !== \"/\" || parsed.search !== \"\" || parsed.hash !== \"\") {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t\"Allowed registry origin must not include a path, query, or fragment\",\n\t\t);\n\t}\n\treturn parsed.origin;\n}\n\nfunction endpointUrl(value: string | URL, origins: ReadonlySet<string>): URL {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", \"Plugin registry URL is invalid\");\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t\"Plugin registry URL must use http(s) without credentials\",\n\t\t);\n\t}\n\tif (parsed.search !== \"\" || parsed.hash !== \"\") {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t\"Plugin registry URL must not include a query or fragment\",\n\t\t);\n\t}\n\tif (!origins.has(parsed.origin)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", \"Plugin registry origin is not allowed\");\n\t}\n\treturn parsed;\n}\n\nfunction responseLength(response: Response): number | undefined {\n\tconst raw = response.headers.get(\"content-length\");\n\tif (raw === null) return undefined;\n\tif (!/^\\d+$/u.test(raw)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", \"Plugin registry response length is invalid\");\n\t}\n\tconst value = Number(raw);\n\tif (!Number.isSafeInteger(value)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", \"Plugin registry response length is invalid\");\n\t}\n\treturn value;\n}\n\nfunction isJsonResponse(response: Response): boolean {\n\tconst contentType = response.headers.get(\"content-type\");\n\tif (contentType === null) return false;\n\tconst mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\treturn mediaType === \"application/json\" || mediaType === \"application/vnd.agent-forge.plugin-registry+json\";\n}\n\nfunction requestController(\n\tparent: AbortSignal | undefined,\n\ttimeoutMs: number,\n): {\n\treadonly signal: AbortSignal;\n\treadonly timedOut: () => boolean;\n\treadonly cleanup: () => void;\n} {\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst abort = () => controller.abort(parent?.reason);\n\tif (parent?.aborted === true) abort();\n\telse parent?.addEventListener(\"abort\", abort, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\treturn {\n\t\tsignal: controller.signal,\n\t\ttimedOut: () => timedOut,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tparent?.removeEventListener(\"abort\", abort);\n\t\t},\n\t};\n}\n\nfunction abortPromise(signal: AbortSignal): { readonly promise: Promise<never>; readonly cleanup: () => void } {\n\tlet rejectAbort: (() => void) | undefined;\n\tconst promise = new Promise<never>((_resolve, reject) => {\n\t\trejectAbort = () => reject(new DOMException(\"aborted\", \"AbortError\"));\n\t\tif (signal.aborted) rejectAbort();\n\t\telse signal.addEventListener(\"abort\", rejectAbort, { once: true });\n\t});\n\treturn {\n\t\tpromise,\n\t\tcleanup: () => {\n\t\t\tif (rejectAbort !== undefined) signal.removeEventListener(\"abort\", rejectAbort);\n\t\t},\n\t};\n}\n\nasync function awaitBeforeAbort<T>(operation: Promise<T>, signal: AbortSignal): Promise<T> {\n\tconst abort = abortPromise(signal);\n\ttry {\n\t\treturn await Promise.race([operation, abort.promise]);\n\t} finally {\n\t\tabort.cleanup();\n\t}\n}\n\nfunction discardResponseBody(response: Response | undefined): void {\n\tconst responseBody = response?.body;\n\tif (responseBody !== undefined && responseBody !== null) {\n\t\tvoid responseBody.cancel().catch(() => undefined);\n\t}\n}\n\nasync function readBody(response: Response, maxBytes: number, signal: AbortSignal): Promise<Uint8Array> {\n\tif (response.body === null) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", \"Plugin registry response has no body\");\n\t}\n\tconst reader = response.body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tif (signal.aborted) throw new DOMException(\"aborted\", \"AbortError\");\n\t\t\tconst item = await awaitBeforeAbort(reader.read(), signal);\n\t\t\tif (item.done) break;\n\t\t\ttotal += item.value.byteLength;\n\t\t\tif (total > maxBytes) {\n\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\"response_too_large\",\n\t\t\t\t\t\"Plugin registry response exceeds the configured size limit\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tchunks.push(item.value);\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n\tconst bytes = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tbytes.set(chunk, offset);\n\t\toffset += chunk.byteLength;\n\t}\n\treturn bytes;\n}\n\nfunction parseDocument(bytes: Uint8Array): readonly PluginRegistryManifestEnvelopeV1[] {\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes));\n\t} catch {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", \"Plugin registry response is not valid JSON\");\n\t}\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", \"Plugin registry document is invalid\");\n\t}\n\tconst document = value as Record<string, unknown>;\n\tif (\n\t\tObject.keys(document).some((key) => key !== \"version\" && key !== \"entries\") ||\n\t\tdocument.version !== 1 ||\n\t\t!Array.isArray(document.entries)\n\t) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", \"Plugin registry document is invalid\");\n\t}\n\treturn document.entries as unknown as RegistryDocumentV1[\"entries\"];\n}\n\nfunction isAbortLike(error: unknown): boolean {\n\treturn error instanceof DOMException && error.name === \"AbortError\";\n}\n\nfunction isCallerCancelled(signal: AbortSignal | undefined): boolean {\n\treturn signal?.aborted === true;\n}\n\nfunction sanitizedSourceError(error: NodeHttpPluginRegistrySourceErrorV1): NodeHttpPluginRegistrySourceErrorV1 {\n\tconst code: unknown = error.code;\n\tif (\n\t\tcode !== \"cancelled\" &&\n\t\tcode !== \"invalid_configuration\" &&\n\t\tcode !== \"request_failed\" &&\n\t\tcode !== \"request_timed_out\" &&\n\t\tcode !== \"invalid_response\" &&\n\t\tcode !== \"response_too_large\"\n\t) {\n\t\treturn new NodeHttpPluginRegistrySourceErrorV1(\"request_failed\", \"Plugin registry request failed\");\n\t}\n\treturn new NodeHttpPluginRegistrySourceErrorV1(code, \"Plugin registry request failed\");\n}\n\n/**\n * Creates a bounded, allowlisted HTTP registry reader. It only transports\n * metadata to the existing registry verifier; package bytes, trust decisions,\n * and installation remain separate host-owned capabilities.\n */\nexport function createNodeHttpPluginRegistrySourceV1(\n\toptions: NodeHttpPluginRegistrySourceOptionsV1,\n): NodeHttpPluginRegistrySourceV1 {\n\tconst transport = options.fetch ?? globalThis.fetch;\n\tif (typeof transport !== \"function\") {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", \"Node fetch is unavailable\");\n\t}\n\tif (!Array.isArray(options.allowedOrigins) || options.allowedOrigins.length === 0) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t\"At least one allowed registry origin is required\",\n\t\t);\n\t}\n\tconst origins = new Set(options.allowedOrigins.map(allowedOrigin));\n\tconst endpoint = endpointUrl(options.url, origins);\n\tconst timeoutMs = boundedPositive(\n\t\toptions.requestTimeoutMs,\n\t\tDEFAULT_TIMEOUT_MS_V1,\n\t\tMAX_TIMEOUT_MS_V1,\n\t\t\"requestTimeoutMs\",\n\t);\n\tconst maxResponseBytes = boundedPositive(\n\t\toptions.maxResponseBytes,\n\t\tDEFAULT_MAX_RESPONSE_BYTES_V1,\n\t\tMAX_RESPONSE_BYTES_V1,\n\t\t\"maxResponseBytes\",\n\t);\n\tconst userAgent = options.userAgent ?? \"agent-forge-plugin-registry/1\";\n\tif (userAgent.length === 0 || userAgent.length > 256 || /[\\r\\n]/u.test(userAgent)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", \"userAgent is invalid\");\n\t}\n\tconst source = endpoint.origin + endpoint.pathname;\n\n\treturn {\n\t\tversion: NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1,\n\t\tsource,\n\t\tlist: async ({ signal } = {}) => {\n\t\t\tif (isCallerCancelled(signal)) {\n\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"cancelled\", \"Plugin registry request was cancelled\");\n\t\t\t}\n\t\t\tconst request = requestController(signal, timeoutMs);\n\t\t\tlet response: Response | undefined;\n\t\t\ttry {\n\t\t\t\tconst transportResponse = Promise.resolve().then(() => {\n\t\t\t\t\tif (request.signal.aborted) throw new DOMException(\"aborted\", \"AbortError\");\n\t\t\t\t\treturn transport(endpoint.toString(), {\n\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: \"application/vnd.agent-forge.plugin-registry+json, application/json\",\n\t\t\t\t\t\t\t\"user-agent\": userAgent,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tredirect: \"error\",\n\t\t\t\t\t\tsignal: request.signal,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tvoid transportResponse.then(\n\t\t\t\t\t(lateResponse) => {\n\t\t\t\t\t\tif (request.signal.aborted) discardResponseBody(lateResponse);\n\t\t\t\t\t},\n\t\t\t\t\t() => undefined,\n\t\t\t\t);\n\t\t\t\tconst receivedResponse = await awaitBeforeAbort(transportResponse, request.signal);\n\t\t\t\tresponse = receivedResponse;\n\t\t\t\tif (receivedResponse.status < 200 || receivedResponse.status >= 300) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\t\"request_failed\",\n\t\t\t\t\t\t\"Plugin registry request did not succeed\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!isJsonResponse(receivedResponse)) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\t\"invalid_response\",\n\t\t\t\t\t\t\"Plugin registry response must be JSON\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst length = responseLength(receivedResponse);\n\t\t\t\tif (length !== undefined && length > maxResponseBytes) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\t\"response_too_large\",\n\t\t\t\t\t\t\"Plugin registry response exceeds the configured size limit\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn parseDocument(await readBody(receivedResponse, maxResponseBytes, request.signal));\n\t\t\t} catch (error) {\n\t\t\t\tif (isCallerCancelled(signal)) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"cancelled\", \"Plugin registry request was cancelled\");\n\t\t\t\t}\n\t\t\t\tif (request.timedOut()) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"request_timed_out\", \"Plugin registry request timed out\");\n\t\t\t\t}\n\t\t\t\tif (error instanceof NodeHttpPluginRegistrySourceErrorV1) throw sanitizedSourceError(error);\n\t\t\t\tif (isAbortLike(error)) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"cancelled\", \"Plugin registry request was cancelled\");\n\t\t\t\t}\n\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"request_failed\", \"Plugin registry request failed\");\n\t\t\t} finally {\n\t\t\t\trequest.cleanup();\n\t\t\t\tdiscardResponseBody(response);\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"node-registry-source.js","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-registry-source.ts"],"names":[],"mappings":"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","sourcesContent":["import { t } from \"../../core/i18n/index.ts\";\nimport type { PluginRegistryManifestEnvelopeV1, PluginRegistrySourceV1 } from \"./registry.ts\";\n\nconst NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1 = 1 as const;\nconst DEFAULT_TIMEOUT_MS_V1 = 15_000;\nconst MAX_TIMEOUT_MS_V1 = 120_000;\nconst DEFAULT_MAX_RESPONSE_BYTES_V1 = 4 * 1024 * 1024;\nconst MAX_RESPONSE_BYTES_V1 = 8 * 1024 * 1024;\n\nexport type NodeHttpPluginRegistrySourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"request_failed\"\n\t| \"request_timed_out\"\n\t| \"invalid_response\"\n\t| \"response_too_large\";\n\n/**\n * Deliberately does not retain transport exceptions or response bodies: callers\n * must not turn registry diagnostics into a credential or path disclosure.\n */\nexport class NodeHttpPluginRegistrySourceErrorV1 extends Error {\n\treadonly code: NodeHttpPluginRegistrySourceErrorCodeV1;\n\n\tconstructor(code: NodeHttpPluginRegistrySourceErrorCodeV1, message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeHttpPluginRegistrySourceErrorV1\";\n\t\tthis.code = code;\n\t}\n}\n\nexport interface NodeHttpPluginRegistrySourceOptionsV1 {\n\t/** Absolute endpoint returning the versioned JSON registry document. */\n\treadonly url: string | URL;\n\t/** Exact http(s) origins the host has intentionally allowed. */\n\treadonly allowedOrigins: readonly string[];\n\t/** Real fetch or deterministic test replacement. */\n\treadonly fetch?: typeof globalThis.fetch;\n\treadonly requestTimeoutMs?: number;\n\treadonly maxResponseBytes?: number;\n\treadonly userAgent?: string;\n}\n\nexport interface NodeHttpPluginRegistrySourceV1 extends PluginRegistrySourceV1 {\n\treadonly version: typeof NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1;\n\t/** Sanitized endpoint identity: never contains credentials, query, or fragment. */\n\treadonly source: string;\n}\n\ninterface RegistryDocumentV1 {\n\treadonly version: 1;\n\treadonly entries: readonly PluginRegistryManifestEnvelopeV1[];\n}\n\nfunction boundedPositive(value: number | undefined, fallback: number, maximum: number, label: string): number {\n\tconst result = value ?? fallback;\n\tif (!Number.isSafeInteger(result) || result <= 0 || result > maximum) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"{label} must be a positive integer at most {maximum}\", { label, maximum }),\n\t\t);\n\t}\n\treturn result;\n}\n\nfunction allowedOrigin(value: string): string {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", t(\"Allowed registry origin is invalid\"));\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"Allowed registry origin must be an http(s) origin without credentials\"),\n\t\t);\n\t}\n\tif (parsed.pathname !== \"/\" || parsed.search !== \"\" || parsed.hash !== \"\") {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"Allowed registry origin must not include a path, query, or fragment\"),\n\t\t);\n\t}\n\treturn parsed.origin;\n}\n\nfunction endpointUrl(value: string | URL, origins: ReadonlySet<string>): URL {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", t(\"Plugin registry URL is invalid\"));\n\t}\n\tif ((parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") || parsed.username || parsed.password) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"Plugin registry URL must use http(s) without credentials\"),\n\t\t);\n\t}\n\tif (parsed.search !== \"\" || parsed.hash !== \"\") {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"Plugin registry URL must not include a query or fragment\"),\n\t\t);\n\t}\n\tif (!origins.has(parsed.origin)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"Plugin registry origin is not allowed\"),\n\t\t);\n\t}\n\treturn parsed;\n}\n\nfunction responseLength(response: Response): number | undefined {\n\tconst raw = response.headers.get(\"content-length\");\n\tif (raw === null) return undefined;\n\tif (!/^\\d+$/u.test(raw)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_response\",\n\t\t\tt(\"Plugin registry response length is invalid\"),\n\t\t);\n\t}\n\tconst value = Number(raw);\n\tif (!Number.isSafeInteger(value)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_response\",\n\t\t\tt(\"Plugin registry response length is invalid\"),\n\t\t);\n\t}\n\treturn value;\n}\n\nfunction isJsonResponse(response: Response): boolean {\n\tconst contentType = response.headers.get(\"content-type\");\n\tif (contentType === null) return false;\n\tconst mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\treturn mediaType === \"application/json\" || mediaType === \"application/vnd.agent-forge.plugin-registry+json\";\n}\n\nfunction requestController(\n\tparent: AbortSignal | undefined,\n\ttimeoutMs: number,\n): {\n\treadonly signal: AbortSignal;\n\treadonly timedOut: () => boolean;\n\treadonly cleanup: () => void;\n} {\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst abort = () => controller.abort(parent?.reason);\n\tif (parent?.aborted === true) abort();\n\telse parent?.addEventListener(\"abort\", abort, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\treturn {\n\t\tsignal: controller.signal,\n\t\ttimedOut: () => timedOut,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tparent?.removeEventListener(\"abort\", abort);\n\t\t},\n\t};\n}\n\nfunction abortPromise(signal: AbortSignal): { readonly promise: Promise<never>; readonly cleanup: () => void } {\n\tlet rejectAbort: (() => void) | undefined;\n\tconst promise = new Promise<never>((_resolve, reject) => {\n\t\trejectAbort = () => reject(new DOMException(\"aborted\", \"AbortError\"));\n\t\tif (signal.aborted) rejectAbort();\n\t\telse signal.addEventListener(\"abort\", rejectAbort, { once: true });\n\t});\n\treturn {\n\t\tpromise,\n\t\tcleanup: () => {\n\t\t\tif (rejectAbort !== undefined) signal.removeEventListener(\"abort\", rejectAbort);\n\t\t},\n\t};\n}\n\nasync function awaitBeforeAbort<T>(operation: Promise<T>, signal: AbortSignal): Promise<T> {\n\tconst abort = abortPromise(signal);\n\ttry {\n\t\treturn await Promise.race([operation, abort.promise]);\n\t} finally {\n\t\tabort.cleanup();\n\t}\n}\n\nfunction discardResponseBody(response: Response | undefined): void {\n\tconst responseBody = response?.body;\n\tif (responseBody !== undefined && responseBody !== null) {\n\t\tvoid responseBody.cancel().catch(() => undefined);\n\t}\n}\n\nasync function readBody(response: Response, maxBytes: number, signal: AbortSignal): Promise<Uint8Array> {\n\tif (response.body === null) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", t(\"Plugin registry response has no body\"));\n\t}\n\tconst reader = response.body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tif (signal.aborted) throw new DOMException(t(\"aborted\"), \"AbortError\");\n\t\t\tconst item = await awaitBeforeAbort(reader.read(), signal);\n\t\t\tif (item.done) break;\n\t\t\ttotal += item.value.byteLength;\n\t\t\tif (total > maxBytes) {\n\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\"response_too_large\",\n\t\t\t\t\tt(\"Plugin registry response exceeds the configured size limit\"),\n\t\t\t\t);\n\t\t\t}\n\t\t\tchunks.push(item.value);\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n\tconst bytes = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tbytes.set(chunk, offset);\n\t\toffset += chunk.byteLength;\n\t}\n\treturn bytes;\n}\n\nfunction parseDocument(bytes: Uint8Array): readonly PluginRegistryManifestEnvelopeV1[] {\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes));\n\t} catch {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_response\",\n\t\t\tt(\"Plugin registry response is not valid JSON\"),\n\t\t);\n\t}\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", t(\"Plugin registry document is invalid\"));\n\t}\n\tconst document = value as Record<string, unknown>;\n\tif (\n\t\tObject.keys(document).some((key) => key !== \"version\" && key !== \"entries\") ||\n\t\tdocument.version !== 1 ||\n\t\t!Array.isArray(document.entries)\n\t) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_response\", t(\"Plugin registry document is invalid\"));\n\t}\n\treturn document.entries as unknown as RegistryDocumentV1[\"entries\"];\n}\n\nfunction isAbortLike(error: unknown): boolean {\n\treturn error instanceof DOMException && error.name === \"AbortError\";\n}\n\nfunction isCallerCancelled(signal: AbortSignal | undefined): boolean {\n\treturn signal?.aborted === true;\n}\n\nfunction sanitizedSourceError(error: NodeHttpPluginRegistrySourceErrorV1): NodeHttpPluginRegistrySourceErrorV1 {\n\tconst code: unknown = error.code;\n\tif (\n\t\tcode !== \"cancelled\" &&\n\t\tcode !== \"invalid_configuration\" &&\n\t\tcode !== \"request_failed\" &&\n\t\tcode !== \"request_timed_out\" &&\n\t\tcode !== \"invalid_response\" &&\n\t\tcode !== \"response_too_large\"\n\t) {\n\t\treturn new NodeHttpPluginRegistrySourceErrorV1(\"request_failed\", t(\"Plugin registry request failed\"));\n\t}\n\treturn new NodeHttpPluginRegistrySourceErrorV1(code, t(\"Plugin registry request failed\"));\n}\n\n/**\n * Creates a bounded, allowlisted HTTP registry reader. It only transports\n * metadata to the existing registry verifier; package bytes, trust decisions,\n * and installation remain separate host-owned capabilities.\n */\nexport function createNodeHttpPluginRegistrySourceV1(\n\toptions: NodeHttpPluginRegistrySourceOptionsV1,\n): NodeHttpPluginRegistrySourceV1 {\n\tconst transport = options.fetch ?? globalThis.fetch;\n\tif (typeof transport !== \"function\") {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", t(\"Node fetch is unavailable\"));\n\t}\n\tif (!Array.isArray(options.allowedOrigins) || options.allowedOrigins.length === 0) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"At least one allowed registry origin is required\"),\n\t\t);\n\t}\n\tconst origins = new Set(options.allowedOrigins.map(allowedOrigin));\n\tconst endpoint = endpointUrl(options.url, origins);\n\tconst timeoutMs = boundedPositive(\n\t\toptions.requestTimeoutMs,\n\t\tDEFAULT_TIMEOUT_MS_V1,\n\t\tMAX_TIMEOUT_MS_V1,\n\t\t\"requestTimeoutMs\",\n\t);\n\tconst maxResponseBytes = boundedPositive(\n\t\toptions.maxResponseBytes,\n\t\tDEFAULT_MAX_RESPONSE_BYTES_V1,\n\t\tMAX_RESPONSE_BYTES_V1,\n\t\t\"maxResponseBytes\",\n\t);\n\tconst userAgent = options.userAgent ?? \"agent-forge-plugin-registry/1\";\n\tif (userAgent.length === 0 || userAgent.length > 256 || /[\\r\\n]/u.test(userAgent)) {\n\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"invalid_configuration\", t(\"userAgent is invalid\"));\n\t}\n\tconst source = endpoint.origin + endpoint.pathname;\n\n\treturn {\n\t\tversion: NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1,\n\t\tsource,\n\t\tlist: async ({ signal } = {}) => {\n\t\t\tif (isCallerCancelled(signal)) {\n\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"cancelled\", t(\"Plugin registry request was cancelled\"));\n\t\t\t}\n\t\t\tconst request = requestController(signal, timeoutMs);\n\t\t\tlet response: Response | undefined;\n\t\t\ttry {\n\t\t\t\tconst transportResponse = Promise.resolve().then(() => {\n\t\t\t\t\tif (request.signal.aborted) throw new DOMException(t(\"aborted\"), \"AbortError\");\n\t\t\t\t\treturn transport(endpoint.toString(), {\n\t\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: \"application/vnd.agent-forge.plugin-registry+json, application/json\",\n\t\t\t\t\t\t\t\"user-agent\": userAgent,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tredirect: \"error\",\n\t\t\t\t\t\tsignal: request.signal,\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tvoid transportResponse.then(\n\t\t\t\t\t(lateResponse) => {\n\t\t\t\t\t\tif (request.signal.aborted) discardResponseBody(lateResponse);\n\t\t\t\t\t},\n\t\t\t\t\t() => undefined,\n\t\t\t\t);\n\t\t\t\tconst receivedResponse = await awaitBeforeAbort(transportResponse, request.signal);\n\t\t\t\tresponse = receivedResponse;\n\t\t\t\tif (receivedResponse.status < 200 || receivedResponse.status >= 300) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\t\"request_failed\",\n\t\t\t\t\t\tt(\"Plugin registry request did not succeed\"),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!isJsonResponse(receivedResponse)) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\t\"invalid_response\",\n\t\t\t\t\t\tt(\"Plugin registry response must be JSON\"),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst length = responseLength(receivedResponse);\n\t\t\t\tif (length !== undefined && length > maxResponseBytes) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\t\"response_too_large\",\n\t\t\t\t\t\tt(\"Plugin registry response exceeds the configured size limit\"),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn parseDocument(await readBody(receivedResponse, maxResponseBytes, request.signal));\n\t\t\t} catch (error) {\n\t\t\t\tif (isCallerCancelled(signal)) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"cancelled\", t(\"Plugin registry request was cancelled\"));\n\t\t\t\t}\n\t\t\t\tif (request.timedOut()) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\n\t\t\t\t\t\t\"request_timed_out\",\n\t\t\t\t\t\tt(\"Plugin registry request timed out\"),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (error instanceof NodeHttpPluginRegistrySourceErrorV1) throw sanitizedSourceError(error);\n\t\t\t\tif (isAbortLike(error)) {\n\t\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"cancelled\", t(\"Plugin registry request was cancelled\"));\n\t\t\t\t}\n\t\t\t\tthrow new NodeHttpPluginRegistrySourceErrorV1(\"request_failed\", t(\"Plugin registry request failed\"));\n\t\t\t} finally {\n\t\t\t\trequest.cleanup();\n\t\t\t\tdiscardResponseBody(response);\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-release-package-source.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-release-package-source.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,mCAAmC,GAC5C,WAAW,GACX,uBAAuB,GACvB,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,yBAAyB,GACzB,yBAAyB,GACzB,cAAc,CAAC;AAElB,qBAAa,+BAAgC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,EAAE,mCAAmC,CAAC;IACnD,6FAA6F;IAC7F,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAEpC,YACC,IAAI,EAAE,mCAAmC,EACzC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,EAMjD;CACD;AAED,MAAM,WAAW,iCAAiC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,yDAAyD;IACzD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE;QACtC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;QAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;QACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;KAC9B,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAC1C;AAwND,sDAAsD;AACtD,wBAAgB,gCAAgC,CAC/C,OAAO,GAAE,iCAAsC,GAC7C,0BAA0B,CAsJ5B","sourcesContent":["import { downloadNodeUrlPackageV1 } from \"./node-url-package-source.ts\";\n\n/**\n * GitHub/Gitee release plugin package source (design\n * `插件独立分发与启动装配设计.md` §4.6 \"GitHub\"/\"Gitee\" rows). Two-step\n * protocol: resolve one release through the repo's release API — the exact\n * tag endpoint when a tag is given, otherwise the first non-draft entry of\n * the first releases page in API order (no client-side sorting) — then pick\n * the release's single `.zip`/`.tgz` asset and download it with the same\n * bounded http(s) semantics as custom URL packages (redirect-per-hop, budget,\n * timeout, optional strong sha256). Zero or multiple matching assets are\n * explicit structured errors listing the asset names; nothing is guessed.\n * Authentication is optional: GitHub uses an `Authorization: Bearer` header,\n * Gitee an `access_token` query parameter. Anonymous rate limits (403/429\n * with `X-RateLimit-Remaining: 0`, or any 429) surface as `rate_limited`\n * carrying the advertised `X-RateLimit-Reset` epoch; there is no retry.\n */\n\nconst DEFAULT_GITHUB_API_ORIGIN_V1 = \"https://api.github.com\";\nconst DEFAULT_GITEE_API_ORIGIN_V1 = \"https://gitee.com/api/v5\";\nconst DEFAULT_TIMEOUT_MS_V1 = 15_000;\nconst MAX_TIMEOUT_MS_V1 = 120_000;\nconst DEFAULT_MAX_RESPONSE_BYTES_V1 = 8 * 1024 * 1024;\nconst MAX_RESPONSE_BYTES_V1 = 16 * 1024 * 1024;\nconst DEFAULT_MAX_ASSET_BYTES_V1 = 128 * 1024 * 1024;\nconst MAX_ASSET_BYTES_V1 = 512 * 1024 * 1024;\nconst DEFAULT_REDIRECTS_V1 = 3;\nconst MAX_REDIRECTS_V1 = 5;\nconst REDIRECT_STATUS = new Set([301, 302, 303, 307, 308]);\n\nexport type NodeReleasePackageSourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"request_failed\"\n\t| \"request_timed_out\"\n\t| \"invalid_response\"\n\t| \"response_too_large\"\n\t| \"release_not_found\"\n\t| \"release_asset_not_found\"\n\t| \"release_asset_ambiguous\"\n\t| \"rate_limited\";\n\nexport class NodeReleasePackageSourceErrorV1 extends Error {\n\treadonly code: NodeReleasePackageSourceErrorCodeV1;\n\t/** Unix epoch seconds advertised by `X-RateLimit-Reset`; present only for `rate_limited`. */\n\treadonly resetEpochSeconds?: number;\n\n\tconstructor(\n\t\tcode: NodeReleasePackageSourceErrorCodeV1,\n\t\tmessage: string,\n\t\toptions?: { readonly resetEpochSeconds?: number },\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeReleasePackageSourceErrorV1\";\n\t\tthis.code = code;\n\t\tif (options?.resetEpochSeconds !== undefined) this.resetEpochSeconds = options.resetEpochSeconds;\n\t}\n}\n\nexport interface NodeReleasePackageSourceOptionsV1 {\n\t/** Bare http(s) GitHub API origin; defaults to `https://api.github.com`. */\n\treadonly githubApiOrigin?: string;\n\t/** Bare http(s) Gitee API origin; defaults to `https://gitee.com/api/v5`. */\n\treadonly giteeApiOrigin?: string;\n\t/** Optional GitHub API token sent as a bearer header. */\n\treadonly githubToken?: string;\n\t/** Optional Gitee API token sent as an `access_token` query parameter. */\n\treadonly giteeToken?: string;\n\t/** Real fetch or a deterministic test replacement. */\n\treadonly fetch?: typeof globalThis.fetch;\n\treadonly requestTimeoutMs?: number;\n\treadonly maxResponseBytes?: number;\n\treadonly maxAssetBytes?: number;\n\treadonly maxRedirects?: number;\n\treadonly userAgent?: string;\n}\n\nexport interface NodeReleaseAssetDownloadV1 {\n\treadonly bytes: Uint8Array;\n\treadonly mediaType: \"application/zip\" | \"application/gzip\";\n\treadonly sha256Hex: string;\n\t/** `github:<owner>/<repo>@<tag|latest>` or the `gitee:` equivalent. */\n\treadonly sourceLabel: string;\n}\n\nexport interface NodeReleasePackageSourceV1 {\n\treadonly version: 1;\n\treadonly downloadReleaseAsset: (input: {\n\t\treadonly kind: \"github\" | \"gitee\";\n\t\treadonly owner: string;\n\t\treadonly repo: string;\n\t\treadonly tag?: string;\n\t\treadonly expectedDigestHex?: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => Promise<NodeReleaseAssetDownloadV1>;\n}\n\ninterface ReleaseAssetShapeV1 {\n\treadonly name?: unknown;\n\treadonly browser_download_url?: unknown;\n}\n\ninterface ReleaseShapeV1 {\n\treadonly draft?: unknown;\n\treadonly assets?: unknown;\n}\n\nfunction boundedPositive(value: number | undefined, fallback: number, maximum: number, label: string): number {\n\tconst result = value ?? fallback;\n\tif (!Number.isSafeInteger(result) || result <= 0 || result > maximum)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t`${label} must be a positive integer at most ${maximum}`,\n\t\t);\n\treturn result;\n}\n\nfunction boundedToken(value: string | undefined, label: string): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (value.length === 0 || value.length > 4096 || /[\\r\\n\\s]/u.test(value))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", `${label} is invalid`);\n\treturn value;\n}\n\nfunction apiOrigin(value: string, label: string): { readonly origin: string; readonly pathPrefix: string } {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", `${label} is invalid`);\n\t}\n\tif (\n\t\t(parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") ||\n\t\tparsed.username !== \"\" ||\n\t\tparsed.password !== \"\"\n\t)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t`${label} must be http(s) without credentials`,\n\t\t);\n\tif (parsed.search !== \"\" || parsed.hash !== \"\")\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t`${label} must not include a query or fragment`,\n\t\t);\n\t// The Gitee default origin carries the `/api/v5` path prefix. The prefix is\n\t// kept as a plain string because a URL normalizes an empty pathname back\n\t// to \"/\", which would reintroduce a double slash when joining endpoints.\n\tconst trimmed = parsed.pathname.replace(/\\/+$/u, \"\");\n\treturn { origin: parsed.origin, pathPrefix: trimmed === \"\" || trimmed === \"/\" ? \"\" : trimmed.replace(/^\\//u, \"\") };\n}\n\nfunction jsonBytes(value: Uint8Array): unknown {\n\ttry {\n\t\treturn JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(value));\n\t} catch {\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release API response is not valid JSON\");\n\t}\n}\n\nfunction parseReleaseList(bytes: Uint8Array): readonly ReleaseShapeV1[] {\n\tconst value = jsonBytes(bytes);\n\tif (!Array.isArray(value))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release API response is not a release list\");\n\treturn value as readonly ReleaseShapeV1[];\n}\n\nfunction parseReleaseObject(bytes: Uint8Array): ReleaseShapeV1 {\n\tconst value = jsonBytes(bytes);\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release API response is not a release object\");\n\treturn value as ReleaseShapeV1;\n}\n\n/** First non-draft entry in API order; the array itself is the ordering contract. */\nfunction firstPublishedRelease(releases: readonly ReleaseShapeV1[]): ReleaseShapeV1 {\n\tconst published = releases.find((release) => release.draft !== true);\n\tif (published === undefined)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"release_not_found\", \"repo has no published release\");\n\treturn published;\n}\n\ninterface ReleaseAssetNameV1 {\n\treadonly name: string;\n\treadonly url: unknown;\n}\n\n/** Assets with a usable name; entries without a string name are ignored as API noise. */\nfunction namedAssets(release: ReleaseShapeV1): readonly ReleaseAssetNameV1[] {\n\tif (release.assets === undefined) return [];\n\tif (!Array.isArray(release.assets))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release assets are invalid\");\n\tconst entries: ReleaseAssetNameV1[] = [];\n\tfor (const asset of release.assets) {\n\t\tif (typeof asset !== \"object\" || asset === null) continue;\n\t\tconst shape = asset as ReleaseAssetShapeV1;\n\t\tif (typeof shape.name !== \"string\" || shape.name.length === 0) continue;\n\t\tentries.push({ name: shape.name, url: shape.browser_download_url });\n\t}\n\treturn entries;\n}\n\nfunction isPackageAssetName(name: string): boolean {\n\tconst value = name.toLowerCase();\n\treturn value.endsWith(\".zip\") || value.endsWith(\".tgz\");\n}\n\n/** Select the release's single `.zip`/`.tgz` asset and return its download URL. */\nfunction selectPackageAssetUrl(release: ReleaseShapeV1): string {\n\tconst assets = namedAssets(release);\n\tconst candidates = assets.filter((asset) => isPackageAssetName(asset.name));\n\tconst assetNames = assets.map((asset) => asset.name).join(\", \");\n\tif (candidates.length === 0)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"release_asset_not_found\",\n\t\t\tassetNames.length === 0 ? \"release has no assets\" : `assets: ${assetNames}`,\n\t\t);\n\tif (candidates.length > 1)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"release_asset_ambiguous\",\n\t\t\t`candidates: ${candidates.map((asset) => asset.name).join(\", \")}`,\n\t\t);\n\tconst chosen = candidates[0]!;\n\tif (typeof chosen.url !== \"string\" || chosen.url.length === 0)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release asset has no download URL\");\n\treturn chosen.url;\n}\n\nfunction isAbortLike(error: unknown): boolean {\n\treturn error instanceof Error && (error.name === \"AbortError\" || error.name === \"AbortSignalError\");\n}\n\ninterface RequestSignal {\n\treadonly signal: AbortSignal;\n\treadonly timedOut: () => boolean;\n\treadonly cleanup: () => void;\n}\n\nfunction requestSignal(parent: AbortSignal | undefined, timeoutMs: number): RequestSignal {\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst abort = () => controller.abort(parent?.reason);\n\tif (parent?.aborted === true) abort();\n\telse parent?.addEventListener(\"abort\", abort, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\treturn {\n\t\tsignal: controller.signal,\n\t\ttimedOut: () => timedOut,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tparent?.removeEventListener(\"abort\", abort);\n\t\t},\n\t};\n}\n\nfunction isJsonResponse(response: Response): boolean {\n\tconst contentType = response.headers.get(\"content-type\");\n\tif (contentType === null) return false;\n\tconst mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\treturn mediaType === \"application/json\" || mediaType === \"application/vnd.github+json\";\n}\n\n/**\n * Rate-limit verdict for 403/429 responses: any 429, and a 403 whose\n * `X-RateLimit-Remaining` is exactly `0`. The reset epoch is passed through\n * verbatim when present and integer-like; absent headers stay absent.\n */\nfunction rateLimitState(response: Response): { readonly limited: boolean; readonly resetEpochSeconds?: number } {\n\tconst limited =\n\t\tresponse.status === 429 || (response.status === 403 && response.headers.get(\"x-ratelimit-remaining\") === \"0\");\n\tif (!limited) return { limited: false };\n\tconst reset = response.headers.get(\"x-ratelimit-reset\");\n\tconst resetValue = reset === null ? Number.NaN : Number.parseInt(reset, 10);\n\tif (!Number.isSafeInteger(resetValue) || resetValue < 0) return { limited: true };\n\treturn { limited: true, resetEpochSeconds: resetValue };\n}\n\nasync function readBody(response: Response, maxBytes: number, signal: AbortSignal): Promise<Uint8Array> {\n\tif (response.body === null)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release API response has no body\");\n\tconst reader = response.body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tif (signal.aborted) throw new DOMException(\"aborted\", \"AbortError\");\n\t\t\tconst item = await reader.read();\n\t\t\tif (item.done) break;\n\t\t\ttotal += item.value.byteLength;\n\t\t\tif (total > maxBytes)\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\t\t\"response_too_large\",\n\t\t\t\t\t\"release API response exceeds the configured size limit\",\n\t\t\t\t);\n\t\t\tchunks.push(item.value);\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n\tconst bytes = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tbytes.set(chunk, offset);\n\t\toffset += chunk.byteLength;\n\t}\n\treturn bytes;\n}\n\n/** Create the bounded GitHub/Gitee release reader. */\nexport function createNodeReleasePackageSourceV1(\n\toptions: NodeReleasePackageSourceOptionsV1 = {},\n): NodeReleasePackageSourceV1 {\n\tconst transport = options.fetch ?? globalThis.fetch;\n\tif (typeof transport !== \"function\")\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", \"Node fetch is unavailable\");\n\tconst githubOrigin = apiOrigin(options.githubApiOrigin ?? DEFAULT_GITHUB_API_ORIGIN_V1, \"githubApiOrigin\");\n\tconst giteeOrigin = apiOrigin(options.giteeApiOrigin ?? DEFAULT_GITEE_API_ORIGIN_V1, \"giteeApiOrigin\");\n\tconst githubToken = boundedToken(options.githubToken, \"githubToken\");\n\tconst giteeToken = boundedToken(options.giteeToken, \"giteeToken\");\n\tconst timeoutMs = boundedPositive(\n\t\toptions.requestTimeoutMs,\n\t\tDEFAULT_TIMEOUT_MS_V1,\n\t\tMAX_TIMEOUT_MS_V1,\n\t\t\"requestTimeoutMs\",\n\t);\n\tconst maxResponseBytes = boundedPositive(\n\t\toptions.maxResponseBytes,\n\t\tDEFAULT_MAX_RESPONSE_BYTES_V1,\n\t\tMAX_RESPONSE_BYTES_V1,\n\t\t\"maxResponseBytes\",\n\t);\n\tconst maxAssetBytes = boundedPositive(\n\t\toptions.maxAssetBytes,\n\t\tDEFAULT_MAX_ASSET_BYTES_V1,\n\t\tMAX_ASSET_BYTES_V1,\n\t\t\"maxAssetBytes\",\n\t);\n\tconst maxRedirects = options.maxRedirects ?? DEFAULT_REDIRECTS_V1;\n\tif (!Number.isSafeInteger(maxRedirects) || maxRedirects < 0 || maxRedirects > MAX_REDIRECTS_V1)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\t`maxRedirects must be an integer between 0 and ${MAX_REDIRECTS_V1}`,\n\t\t);\n\tconst userAgent = options.userAgent ?? \"agent-forge-plugin-release/1\";\n\tif (userAgent.length === 0 || userAgent.length > 256 || /[\\r\\n]/u.test(userAgent))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", \"userAgent is invalid\");\n\n\tconst fetchReleaseJson = async (\n\t\turl: URL,\n\t\theaders: Readonly<Record<string, string>>,\n\t\tparentSignal: AbortSignal | undefined,\n\t): Promise<Uint8Array> => {\n\t\tlet current = url;\n\t\tfor (let redirect = 0; ; redirect += 1) {\n\t\t\tconst request = requestSignal(parentSignal, timeoutMs);\n\t\t\tlet response: Response;\n\t\t\ttry {\n\t\t\t\tresponse = await transport(current.toString(), {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: { accept: \"application/json\", \"user-agent\": userAgent, ...headers },\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\tsignal: request.signal,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\trequest.cleanup();\n\t\t\t\tif (request.timedOut())\n\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_timed_out\", \"release API request timed out\");\n\t\t\t\tif (isAbortLike(error))\n\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"cancelled\", \"release API request was cancelled\");\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_failed\", \"release API request failed\");\n\t\t\t}\n\t\t\tif (!REDIRECT_STATUS.has(response.status)) {\n\t\t\t\ttry {\n\t\t\t\t\tif (response.status === 404)\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"release_not_found\", \"repo or release was not found\");\n\t\t\t\t\tconst limit = rateLimitState(response);\n\t\t\t\t\tif (limit.limited) {\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\tlimit.resetEpochSeconds === undefined\n\t\t\t\t\t\t\t\t? \"rate limit was exceeded\"\n\t\t\t\t\t\t\t\t: `rate limit resets at ${new Date(limit.resetEpochSeconds * 1000).toISOString()}`;\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"rate_limited\", message, {\n\t\t\t\t\t\t\t...(limit.resetEpochSeconds === undefined ? {} : { resetEpochSeconds: limit.resetEpochSeconds }),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (response.status < 200 || response.status >= 300)\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_failed\", \"release API request did not succeed\");\n\t\t\t\t\tif (!isJsonResponse(response))\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release API response must be JSON\");\n\t\t\t\t\tconst bytes = await readBody(response, maxResponseBytes, request.signal);\n\t\t\t\t\treturn bytes;\n\t\t\t\t} finally {\n\t\t\t\t\tawait response.body?.cancel().catch(() => undefined);\n\t\t\t\t\trequest.cleanup();\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tawait response.body?.cancel().catch(() => undefined);\n\t\t\trequest.cleanup();\n\t\t\tif (location === null || redirect >= maxRedirects)\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_failed\", \"release API redirect limit exceeded\");\n\t\t\tlet next: URL;\n\t\t\ttry {\n\t\t\t\tnext = new URL(location, current);\n\t\t\t} catch {\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release API redirect target is invalid\");\n\t\t\t}\n\t\t\tif ((next.protocol !== \"http:\" && next.protocol !== \"https:\") || next.username !== \"\" || next.password !== \"\")\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", \"release API redirect must stay http(s)\");\n\t\t\tcurrent = next;\n\t\t}\n\t};\n\n\tconst downloadReleaseAsset: NodeReleasePackageSourceV1[\"downloadReleaseAsset\"] = async (input) => {\n\t\tif (input.signal?.aborted === true)\n\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"cancelled\", \"release asset download was cancelled\");\n\t\tconst sourceLabel = `${input.kind}:${input.owner}/${input.repo}@${input.tag ?? \"latest\"}`;\n\t\tconst base = input.kind === \"github\" ? githubOrigin : giteeOrigin;\n\t\tconst segments = [\n\t\t\tbase.pathPrefix === \"\" ? undefined : base.pathPrefix,\n\t\t\t\"repos\",\n\t\t\tencodeURIComponent(input.owner),\n\t\t\tencodeURIComponent(input.repo),\n\t\t\t\"releases\",\n\t\t\t...(input.tag === undefined ? [] : [\"tags\", encodeURIComponent(input.tag)]),\n\t\t].filter((segment): segment is string => segment !== undefined);\n\t\tconst endpoint = new URL(`${base.origin}/${segments.join(\"/\")}`);\n\t\tconst headers: Readonly<Record<string, string>> =\n\t\t\tinput.kind === \"github\"\n\t\t\t\t? {\n\t\t\t\t\t\t\"x-github-api-version\": \"2022-11-28\",\n\t\t\t\t\t\t...(githubToken === undefined ? {} : { authorization: `Bearer ${githubToken}` }),\n\t\t\t\t\t}\n\t\t\t\t: {};\n\t\tif (input.kind === \"gitee\" && giteeToken !== undefined) endpoint.searchParams.set(\"access_token\", giteeToken);\n\t\tconst payload = await fetchReleaseJson(endpoint, headers, input.signal);\n\t\tconst release =\n\t\t\tinput.tag === undefined ? firstPublishedRelease(parseReleaseList(payload)) : parseReleaseObject(payload);\n\t\tconst assetUrl = selectPackageAssetUrl(release);\n\t\tconst download = await downloadNodeUrlPackageV1(\n\t\t\t{\n\t\t\t\t...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n\t\t\t\trequestTimeoutMs: timeoutMs,\n\t\t\t\tmaxPackageBytes: maxAssetBytes,\n\t\t\t\tuserAgent,\n\t\t\t},\n\t\t\t{\n\t\t\t\turl: assetUrl,\n\t\t\t\t...(input.expectedDigestHex === undefined ? {} : { expectedDigestHex: input.expectedDigestHex }),\n\t\t\t\tsignal: input.signal,\n\t\t\t},\n\t\t);\n\t\treturn {\n\t\t\tbytes: download.bytes,\n\t\t\tmediaType: download.mediaType,\n\t\t\tsha256Hex: download.digestHex,\n\t\t\tsourceLabel,\n\t\t};\n\t};\n\n\treturn { version: 1, downloadReleaseAsset };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"node-release-package-source.d.ts","sourceRoot":"","sources":["../../../src/plugins/ecosystem/node-release-package-source.ts"],"names":[],"mappings":"AA+BA,MAAM,MAAM,mCAAmC,GAC5C,WAAW,GACX,uBAAuB,GACvB,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,yBAAyB,GACzB,yBAAyB,GACzB,cAAc,CAAC;AAElB,qBAAa,+BAAgC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,EAAE,mCAAmC,CAAC;IACnD,6FAA6F;IAC7F,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAEpC,YACC,IAAI,EAAE,mCAAmC,EACzC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,EAMjD;CACD;AAED,MAAM,WAAW,iCAAiC;IACjD,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,yDAAyD;IACzD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,iBAAiB,GAAG,kBAAkB,CAAC;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE;QACtC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;QAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;QACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;KAC9B,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAC1C;AAwND,sDAAsD;AACtD,wBAAgB,gCAAgC,CAC/C,OAAO,GAAE,iCAAsC,GAC7C,0BAA0B,CAsJ5B","sourcesContent":["import { t } from \"../../core/i18n/index.ts\";\nimport { downloadNodeUrlPackageV1 } from \"./node-url-package-source.ts\";\n\n/**\n * GitHub/Gitee release plugin package source (design\n * `插件独立分发与启动装配设计.md` §4.6 \"GitHub\"/\"Gitee\" rows). Two-step\n * protocol: resolve one release through the repo's release API — the exact\n * tag endpoint when a tag is given, otherwise the first non-draft entry of\n * the first releases page in API order (no client-side sorting) — then pick\n * the release's single `.zip`/`.tgz` asset and download it with the same\n * bounded http(s) semantics as custom URL packages (redirect-per-hop, budget,\n * timeout, optional strong sha256). Zero or multiple matching assets are\n * explicit structured errors listing the asset names; nothing is guessed.\n * Authentication is optional: GitHub uses an `Authorization: Bearer` header,\n * Gitee an `access_token` query parameter. Anonymous rate limits (403/429\n * with `X-RateLimit-Remaining: 0`, or any 429) surface as `rate_limited`\n * carrying the advertised `X-RateLimit-Reset` epoch; there is no retry.\n */\n\nconst DEFAULT_GITHUB_API_ORIGIN_V1 = \"https://api.github.com\";\nconst DEFAULT_GITEE_API_ORIGIN_V1 = \"https://gitee.com/api/v5\";\nconst DEFAULT_TIMEOUT_MS_V1 = 15_000;\nconst MAX_TIMEOUT_MS_V1 = 120_000;\nconst DEFAULT_MAX_RESPONSE_BYTES_V1 = 8 * 1024 * 1024;\nconst MAX_RESPONSE_BYTES_V1 = 16 * 1024 * 1024;\nconst DEFAULT_MAX_ASSET_BYTES_V1 = 128 * 1024 * 1024;\nconst MAX_ASSET_BYTES_V1 = 512 * 1024 * 1024;\nconst DEFAULT_REDIRECTS_V1 = 3;\nconst MAX_REDIRECTS_V1 = 5;\nconst REDIRECT_STATUS = new Set([301, 302, 303, 307, 308]);\n\nexport type NodeReleasePackageSourceErrorCodeV1 =\n\t| \"cancelled\"\n\t| \"invalid_configuration\"\n\t| \"request_failed\"\n\t| \"request_timed_out\"\n\t| \"invalid_response\"\n\t| \"response_too_large\"\n\t| \"release_not_found\"\n\t| \"release_asset_not_found\"\n\t| \"release_asset_ambiguous\"\n\t| \"rate_limited\";\n\nexport class NodeReleasePackageSourceErrorV1 extends Error {\n\treadonly code: NodeReleasePackageSourceErrorCodeV1;\n\t/** Unix epoch seconds advertised by `X-RateLimit-Reset`; present only for `rate_limited`. */\n\treadonly resetEpochSeconds?: number;\n\n\tconstructor(\n\t\tcode: NodeReleasePackageSourceErrorCodeV1,\n\t\tmessage: string,\n\t\toptions?: { readonly resetEpochSeconds?: number },\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"NodeReleasePackageSourceErrorV1\";\n\t\tthis.code = code;\n\t\tif (options?.resetEpochSeconds !== undefined) this.resetEpochSeconds = options.resetEpochSeconds;\n\t}\n}\n\nexport interface NodeReleasePackageSourceOptionsV1 {\n\t/** Bare http(s) GitHub API origin; defaults to `https://api.github.com`. */\n\treadonly githubApiOrigin?: string;\n\t/** Bare http(s) Gitee API origin; defaults to `https://gitee.com/api/v5`. */\n\treadonly giteeApiOrigin?: string;\n\t/** Optional GitHub API token sent as a bearer header. */\n\treadonly githubToken?: string;\n\t/** Optional Gitee API token sent as an `access_token` query parameter. */\n\treadonly giteeToken?: string;\n\t/** Real fetch or a deterministic test replacement. */\n\treadonly fetch?: typeof globalThis.fetch;\n\treadonly requestTimeoutMs?: number;\n\treadonly maxResponseBytes?: number;\n\treadonly maxAssetBytes?: number;\n\treadonly maxRedirects?: number;\n\treadonly userAgent?: string;\n}\n\nexport interface NodeReleaseAssetDownloadV1 {\n\treadonly bytes: Uint8Array;\n\treadonly mediaType: \"application/zip\" | \"application/gzip\";\n\treadonly sha256Hex: string;\n\t/** `github:<owner>/<repo>@<tag|latest>` or the `gitee:` equivalent. */\n\treadonly sourceLabel: string;\n}\n\nexport interface NodeReleasePackageSourceV1 {\n\treadonly version: 1;\n\treadonly downloadReleaseAsset: (input: {\n\t\treadonly kind: \"github\" | \"gitee\";\n\t\treadonly owner: string;\n\t\treadonly repo: string;\n\t\treadonly tag?: string;\n\t\treadonly expectedDigestHex?: string;\n\t\treadonly signal?: AbortSignal;\n\t}) => Promise<NodeReleaseAssetDownloadV1>;\n}\n\ninterface ReleaseAssetShapeV1 {\n\treadonly name?: unknown;\n\treadonly browser_download_url?: unknown;\n}\n\ninterface ReleaseShapeV1 {\n\treadonly draft?: unknown;\n\treadonly assets?: unknown;\n}\n\nfunction boundedPositive(value: number | undefined, fallback: number, maximum: number, label: string): number {\n\tconst result = value ?? fallback;\n\tif (!Number.isSafeInteger(result) || result <= 0 || result > maximum)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"{label} must be a positive integer at most {maximum}\", { label, maximum }),\n\t\t);\n\treturn result;\n}\n\nfunction boundedToken(value: string | undefined, label: string): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (value.length === 0 || value.length > 4096 || /[\\r\\n\\s]/u.test(value))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", t(\"{label} is invalid\", { label }));\n\treturn value;\n}\n\nfunction apiOrigin(value: string, label: string): { readonly origin: string; readonly pathPrefix: string } {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(value);\n\t} catch {\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", t(\"{label} is invalid\", { label }));\n\t}\n\tif (\n\t\t(parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") ||\n\t\tparsed.username !== \"\" ||\n\t\tparsed.password !== \"\"\n\t)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"{label} must be http(s) without credentials\", { label }),\n\t\t);\n\tif (parsed.search !== \"\" || parsed.hash !== \"\")\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"{label} must not include a query or fragment\", { label }),\n\t\t);\n\t// The Gitee default origin carries the `/api/v5` path prefix. The prefix is\n\t// kept as a plain string because a URL normalizes an empty pathname back\n\t// to \"/\", which would reintroduce a double slash when joining endpoints.\n\tconst trimmed = parsed.pathname.replace(/\\/+$/u, \"\");\n\treturn { origin: parsed.origin, pathPrefix: trimmed === \"\" || trimmed === \"/\" ? \"\" : trimmed.replace(/^\\//u, \"\") };\n}\n\nfunction jsonBytes(value: Uint8Array): unknown {\n\ttry {\n\t\treturn JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(value));\n\t} catch {\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release API response is not valid JSON\"));\n\t}\n}\n\nfunction parseReleaseList(bytes: Uint8Array): readonly ReleaseShapeV1[] {\n\tconst value = jsonBytes(bytes);\n\tif (!Array.isArray(value))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release API response is not a release list\"));\n\treturn value as readonly ReleaseShapeV1[];\n}\n\nfunction parseReleaseObject(bytes: Uint8Array): ReleaseShapeV1 {\n\tconst value = jsonBytes(bytes);\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release API response is not a release object\"));\n\treturn value as ReleaseShapeV1;\n}\n\n/** First non-draft entry in API order; the array itself is the ordering contract. */\nfunction firstPublishedRelease(releases: readonly ReleaseShapeV1[]): ReleaseShapeV1 {\n\tconst published = releases.find((release) => release.draft !== true);\n\tif (published === undefined)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"release_not_found\", t(\"repo has no published release\"));\n\treturn published;\n}\n\ninterface ReleaseAssetNameV1 {\n\treadonly name: string;\n\treadonly url: unknown;\n}\n\n/** Assets with a usable name; entries without a string name are ignored as API noise. */\nfunction namedAssets(release: ReleaseShapeV1): readonly ReleaseAssetNameV1[] {\n\tif (release.assets === undefined) return [];\n\tif (!Array.isArray(release.assets))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release assets are invalid\"));\n\tconst entries: ReleaseAssetNameV1[] = [];\n\tfor (const asset of release.assets) {\n\t\tif (typeof asset !== \"object\" || asset === null) continue;\n\t\tconst shape = asset as ReleaseAssetShapeV1;\n\t\tif (typeof shape.name !== \"string\" || shape.name.length === 0) continue;\n\t\tentries.push({ name: shape.name, url: shape.browser_download_url });\n\t}\n\treturn entries;\n}\n\nfunction isPackageAssetName(name: string): boolean {\n\tconst value = name.toLowerCase();\n\treturn value.endsWith(\".zip\") || value.endsWith(\".tgz\");\n}\n\n/** Select the release's single `.zip`/`.tgz` asset and return its download URL. */\nfunction selectPackageAssetUrl(release: ReleaseShapeV1): string {\n\tconst assets = namedAssets(release);\n\tconst candidates = assets.filter((asset) => isPackageAssetName(asset.name));\n\tconst assetNames = assets.map((asset) => asset.name).join(\", \");\n\tif (candidates.length === 0)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"release_asset_not_found\",\n\t\t\tassetNames.length === 0 ? t(\"release has no assets\") : t(\"assets: {names}\", { names: assetNames }),\n\t\t);\n\tif (candidates.length > 1)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"release_asset_ambiguous\",\n\t\t\tt(\"candidates: {names}\", { names: candidates.map((asset) => asset.name).join(\", \") }),\n\t\t);\n\tconst chosen = candidates[0]!;\n\tif (typeof chosen.url !== \"string\" || chosen.url.length === 0)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release asset has no download URL\"));\n\treturn chosen.url;\n}\n\nfunction isAbortLike(error: unknown): boolean {\n\treturn error instanceof Error && (error.name === \"AbortError\" || error.name === \"AbortSignalError\");\n}\n\ninterface RequestSignal {\n\treadonly signal: AbortSignal;\n\treadonly timedOut: () => boolean;\n\treadonly cleanup: () => void;\n}\n\nfunction requestSignal(parent: AbortSignal | undefined, timeoutMs: number): RequestSignal {\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst abort = () => controller.abort(parent?.reason);\n\tif (parent?.aborted === true) abort();\n\telse parent?.addEventListener(\"abort\", abort, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\treturn {\n\t\tsignal: controller.signal,\n\t\ttimedOut: () => timedOut,\n\t\tcleanup: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tparent?.removeEventListener(\"abort\", abort);\n\t\t},\n\t};\n}\n\nfunction isJsonResponse(response: Response): boolean {\n\tconst contentType = response.headers.get(\"content-type\");\n\tif (contentType === null) return false;\n\tconst mediaType = contentType.split(\";\", 1)[0]?.trim().toLowerCase();\n\treturn mediaType === \"application/json\" || mediaType === \"application/vnd.github+json\";\n}\n\n/**\n * Rate-limit verdict for 403/429 responses: any 429, and a 403 whose\n * `X-RateLimit-Remaining` is exactly `0`. The reset epoch is passed through\n * verbatim when present and integer-like; absent headers stay absent.\n */\nfunction rateLimitState(response: Response): { readonly limited: boolean; readonly resetEpochSeconds?: number } {\n\tconst limited =\n\t\tresponse.status === 429 || (response.status === 403 && response.headers.get(\"x-ratelimit-remaining\") === \"0\");\n\tif (!limited) return { limited: false };\n\tconst reset = response.headers.get(\"x-ratelimit-reset\");\n\tconst resetValue = reset === null ? Number.NaN : Number.parseInt(reset, 10);\n\tif (!Number.isSafeInteger(resetValue) || resetValue < 0) return { limited: true };\n\treturn { limited: true, resetEpochSeconds: resetValue };\n}\n\nasync function readBody(response: Response, maxBytes: number, signal: AbortSignal): Promise<Uint8Array> {\n\tif (response.body === null)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release API response has no body\"));\n\tconst reader = response.body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet total = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tif (signal.aborted) throw new DOMException(t(\"aborted\"), \"AbortError\");\n\t\t\tconst item = await reader.read();\n\t\t\tif (item.done) break;\n\t\t\ttotal += item.value.byteLength;\n\t\t\tif (total > maxBytes)\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\t\t\"response_too_large\",\n\t\t\t\t\tt(\"release API response exceeds the configured size limit\"),\n\t\t\t\t);\n\t\t\tchunks.push(item.value);\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n\tconst bytes = new Uint8Array(total);\n\tlet offset = 0;\n\tfor (const chunk of chunks) {\n\t\tbytes.set(chunk, offset);\n\t\toffset += chunk.byteLength;\n\t}\n\treturn bytes;\n}\n\n/** Create the bounded GitHub/Gitee release reader. */\nexport function createNodeReleasePackageSourceV1(\n\toptions: NodeReleasePackageSourceOptionsV1 = {},\n): NodeReleasePackageSourceV1 {\n\tconst transport = options.fetch ?? globalThis.fetch;\n\tif (typeof transport !== \"function\")\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", t(\"Node fetch is unavailable\"));\n\tconst githubOrigin = apiOrigin(options.githubApiOrigin ?? DEFAULT_GITHUB_API_ORIGIN_V1, \"githubApiOrigin\");\n\tconst giteeOrigin = apiOrigin(options.giteeApiOrigin ?? DEFAULT_GITEE_API_ORIGIN_V1, \"giteeApiOrigin\");\n\tconst githubToken = boundedToken(options.githubToken, \"githubToken\");\n\tconst giteeToken = boundedToken(options.giteeToken, \"giteeToken\");\n\tconst timeoutMs = boundedPositive(\n\t\toptions.requestTimeoutMs,\n\t\tDEFAULT_TIMEOUT_MS_V1,\n\t\tMAX_TIMEOUT_MS_V1,\n\t\t\"requestTimeoutMs\",\n\t);\n\tconst maxResponseBytes = boundedPositive(\n\t\toptions.maxResponseBytes,\n\t\tDEFAULT_MAX_RESPONSE_BYTES_V1,\n\t\tMAX_RESPONSE_BYTES_V1,\n\t\t\"maxResponseBytes\",\n\t);\n\tconst maxAssetBytes = boundedPositive(\n\t\toptions.maxAssetBytes,\n\t\tDEFAULT_MAX_ASSET_BYTES_V1,\n\t\tMAX_ASSET_BYTES_V1,\n\t\t\"maxAssetBytes\",\n\t);\n\tconst maxRedirects = options.maxRedirects ?? DEFAULT_REDIRECTS_V1;\n\tif (!Number.isSafeInteger(maxRedirects) || maxRedirects < 0 || maxRedirects > MAX_REDIRECTS_V1)\n\t\tthrow new NodeReleasePackageSourceErrorV1(\n\t\t\t\"invalid_configuration\",\n\t\t\tt(\"maxRedirects must be an integer between 0 and {max}\", { max: MAX_REDIRECTS_V1 }),\n\t\t);\n\tconst userAgent = options.userAgent ?? \"agent-forge-plugin-release/1\";\n\tif (userAgent.length === 0 || userAgent.length > 256 || /[\\r\\n]/u.test(userAgent))\n\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_configuration\", t(\"userAgent is invalid\"));\n\n\tconst fetchReleaseJson = async (\n\t\turl: URL,\n\t\theaders: Readonly<Record<string, string>>,\n\t\tparentSignal: AbortSignal | undefined,\n\t): Promise<Uint8Array> => {\n\t\tlet current = url;\n\t\tfor (let redirect = 0; ; redirect += 1) {\n\t\t\tconst request = requestSignal(parentSignal, timeoutMs);\n\t\t\tlet response: Response;\n\t\t\ttry {\n\t\t\t\tresponse = await transport(current.toString(), {\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: { accept: \"application/json\", \"user-agent\": userAgent, ...headers },\n\t\t\t\t\tredirect: \"manual\",\n\t\t\t\t\tsignal: request.signal,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\trequest.cleanup();\n\t\t\t\tif (request.timedOut())\n\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_timed_out\", t(\"release API request timed out\"));\n\t\t\t\tif (isAbortLike(error))\n\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"cancelled\", t(\"release API request was cancelled\"));\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_failed\", t(\"release API request failed\"));\n\t\t\t}\n\t\t\tif (!REDIRECT_STATUS.has(response.status)) {\n\t\t\t\ttry {\n\t\t\t\t\tif (response.status === 404)\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"release_not_found\", t(\"repo or release was not found\"));\n\t\t\t\t\tconst limit = rateLimitState(response);\n\t\t\t\t\tif (limit.limited) {\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\tlimit.resetEpochSeconds === undefined\n\t\t\t\t\t\t\t\t? \"rate limit was exceeded\"\n\t\t\t\t\t\t\t\t: `rate limit resets at ${new Date(limit.resetEpochSeconds * 1000).toISOString()}`;\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"rate_limited\", message, {\n\t\t\t\t\t\t\t...(limit.resetEpochSeconds === undefined ? {} : { resetEpochSeconds: limit.resetEpochSeconds }),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tif (response.status < 200 || response.status >= 300)\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_failed\", t(\"release API request did not succeed\"));\n\t\t\t\t\tif (!isJsonResponse(response))\n\t\t\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release API response must be JSON\"));\n\t\t\t\t\tconst bytes = await readBody(response, maxResponseBytes, request.signal);\n\t\t\t\t\treturn bytes;\n\t\t\t\t} finally {\n\t\t\t\t\tawait response.body?.cancel().catch(() => undefined);\n\t\t\t\t\trequest.cleanup();\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst location = response.headers.get(\"location\");\n\t\t\tawait response.body?.cancel().catch(() => undefined);\n\t\t\trequest.cleanup();\n\t\t\tif (location === null || redirect >= maxRedirects)\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"request_failed\", t(\"release API redirect limit exceeded\"));\n\t\t\tlet next: URL;\n\t\t\ttry {\n\t\t\t\tnext = new URL(location, current);\n\t\t\t} catch {\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release API redirect target is invalid\"));\n\t\t\t}\n\t\t\tif ((next.protocol !== \"http:\" && next.protocol !== \"https:\") || next.username !== \"\" || next.password !== \"\")\n\t\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"invalid_response\", t(\"release API redirect must stay http(s)\"));\n\t\t\tcurrent = next;\n\t\t}\n\t};\n\n\tconst downloadReleaseAsset: NodeReleasePackageSourceV1[\"downloadReleaseAsset\"] = async (input) => {\n\t\tif (input.signal?.aborted === true)\n\t\t\tthrow new NodeReleasePackageSourceErrorV1(\"cancelled\", t(\"release asset download was cancelled\"));\n\t\tconst sourceLabel = `${input.kind}:${input.owner}/${input.repo}@${input.tag ?? \"latest\"}`;\n\t\tconst base = input.kind === \"github\" ? githubOrigin : giteeOrigin;\n\t\tconst segments = [\n\t\t\tbase.pathPrefix === \"\" ? undefined : base.pathPrefix,\n\t\t\t\"repos\",\n\t\t\tencodeURIComponent(input.owner),\n\t\t\tencodeURIComponent(input.repo),\n\t\t\t\"releases\",\n\t\t\t...(input.tag === undefined ? [] : [\"tags\", encodeURIComponent(input.tag)]),\n\t\t].filter((segment): segment is string => segment !== undefined);\n\t\tconst endpoint = new URL(`${base.origin}/${segments.join(\"/\")}`);\n\t\tconst headers: Readonly<Record<string, string>> =\n\t\t\tinput.kind === \"github\"\n\t\t\t\t? {\n\t\t\t\t\t\t\"x-github-api-version\": \"2022-11-28\",\n\t\t\t\t\t\t...(githubToken === undefined ? {} : { authorization: `Bearer ${githubToken}` }),\n\t\t\t\t\t}\n\t\t\t\t: {};\n\t\tif (input.kind === \"gitee\" && giteeToken !== undefined) endpoint.searchParams.set(\"access_token\", giteeToken);\n\t\tconst payload = await fetchReleaseJson(endpoint, headers, input.signal);\n\t\tconst release =\n\t\t\tinput.tag === undefined ? firstPublishedRelease(parseReleaseList(payload)) : parseReleaseObject(payload);\n\t\tconst assetUrl = selectPackageAssetUrl(release);\n\t\tconst download = await downloadNodeUrlPackageV1(\n\t\t\t{\n\t\t\t\t...(options.fetch === undefined ? {} : { fetch: options.fetch }),\n\t\t\t\trequestTimeoutMs: timeoutMs,\n\t\t\t\tmaxPackageBytes: maxAssetBytes,\n\t\t\t\tuserAgent,\n\t\t\t},\n\t\t\t{\n\t\t\t\turl: assetUrl,\n\t\t\t\t...(input.expectedDigestHex === undefined ? {} : { expectedDigestHex: input.expectedDigestHex }),\n\t\t\t\tsignal: input.signal,\n\t\t\t},\n\t\t);\n\t\treturn {\n\t\t\tbytes: download.bytes,\n\t\t\tmediaType: download.mediaType,\n\t\t\tsha256Hex: download.digestHex,\n\t\t\tsourceLabel,\n\t\t};\n\t};\n\n\treturn { version: 1, downloadReleaseAsset };\n}\n"]}
|