@ai-agent-forge/agent-forge 0.86.7 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +10 -11
- package/dist/artifacts/artifact-store.d.ts.map +1 -1
- package/dist/artifacts/artifact-store.js +9 -5
- package/dist/artifacts/artifact-store.js.map +1 -1
- package/dist/bundle/.build-manifest.json +430 -413
- package/dist/bundle/chunks/{chunk-A7GUOX2H.js → chunk-6ZKDNZHA.js} +5 -1
- package/dist/bundle/chunks/chunk-HLJEVRWP.js +13 -0
- package/dist/bundle/chunks/chunk-YGHQME4V.js +1456 -0
- package/dist/bundle/chunks/image-resize-worker.js +12 -1
- package/dist/bundle/chunks/{virtual-modules-3IZ4MYSQ.js → virtual-modules-KZ5DRH7Q.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/client.js +1 -1
- package/dist/bundle/index.js +2 -2
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +231 -185
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts.map +1 -1
- package/dist/cli/auth-check.js +17 -4
- package/dist/cli/auth-check.js.map +1 -1
- package/dist/cli/auth-command.d.ts.map +1 -1
- package/dist/cli/auth-command.js +15 -9
- package/dist/cli/auth-command.js.map +1 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +14 -7
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/cli/experimental/command.d.ts.map +1 -1
- package/dist/cli/experimental/command.js +6 -5
- package/dist/cli/experimental/command.js.map +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +9 -8
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/plugin-manager-controller.d.ts.map +1 -1
- package/dist/cli/plugin-manager-controller.js +2 -1
- package/dist/cli/plugin-manager-controller.js.map +1 -1
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +8 -5
- package/dist/cli/serve.js.map +1 -1
- package/dist/client/remote-session.d.ts.map +1 -1
- package/dist/client/remote-session.js +16 -9
- package/dist/client/remote-session.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-capability-contract.d.ts +0 -7
- package/dist/core/agent-capability-contract.d.ts.map +1 -1
- package/dist/core/agent-capability-contract.js +72 -68
- package/dist/core/agent-capability-contract.js.map +1 -1
- package/dist/core/agent-session-bash.d.ts.map +1 -1
- package/dist/core/agent-session-bash.js +5 -4
- package/dist/core/agent-session-bash.js.map +1 -1
- package/dist/core/agent-session-compaction.d.ts +6 -10
- package/dist/core/agent-session-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-compaction.js +35 -133
- package/dist/core/agent-session-compaction.js.map +1 -1
- package/dist/core/agent-session-context.d.ts.map +1 -1
- package/dist/core/agent-session-context.js +18 -13
- package/dist/core/agent-session-context.js.map +1 -1
- package/dist/core/agent-session-internal.d.ts +0 -6
- package/dist/core/agent-session-internal.d.ts.map +1 -1
- package/dist/core/agent-session-internal.js.map +1 -1
- package/dist/core/agent-session-model.d.ts.map +1 -1
- package/dist/core/agent-session-model.js +2 -1
- package/dist/core/agent-session-model.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +3 -3
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +7 -6
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session-tools.d.ts.map +1 -1
- package/dist/core/agent-session-tools.js +3 -2
- package/dist/core/agent-session-tools.js.map +1 -1
- package/dist/core/agent-session.d.ts +40 -22
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +147 -67
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js +11 -5
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +9 -6
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +2 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/embedded-sdk.d.ts.map +1 -1
- package/dist/core/embedded-sdk.js +10 -6
- package/dist/core/embedded-sdk.js.map +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +9 -4
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/extensions/agent-composition.d.ts.map +1 -1
- package/dist/core/extensions/agent-composition.js +26 -19
- package/dist/core/extensions/agent-composition.js.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-agent-loop.js +3 -2
- package/dist/core/extensions/bootstrap-agent-loop.js.map +1 -1
- package/dist/core/extensions/bootstrap-compaction-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-compaction-policy.js +0 -34
- package/dist/core/extensions/bootstrap-compaction-policy.js.map +1 -1
- package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-lifecycle.js +20 -17
- package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
- package/dist/core/extensions/bootstrap-overflow-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-overflow-policy.js +2 -1
- package/dist/core/extensions/bootstrap-overflow-policy.js.map +1 -1
- package/dist/core/extensions/bootstrap-retry-policy.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-retry-policy.js +4 -3
- package/dist/core/extensions/bootstrap-retry-policy.js.map +1 -1
- package/dist/core/extensions/bootstrap-skills.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-skills.js +7 -6
- package/dist/core/extensions/bootstrap-skills.js.map +1 -1
- package/dist/core/extensions/bootstrap-tools.d.ts.map +1 -1
- package/dist/core/extensions/bootstrap-tools.js +2 -1
- package/dist/core/extensions/bootstrap-tools.js.map +1 -1
- package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
- package/dist/core/extensions/capability-plugin.js +37 -13
- package/dist/core/extensions/capability-plugin.js.map +1 -1
- package/dist/core/extensions/capability-runtime-events.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-events.js +17 -13
- package/dist/core/extensions/capability-runtime-events.js.map +1 -1
- package/dist/core/extensions/capability-runtime-guards.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-guards.js +16 -15
- package/dist/core/extensions/capability-runtime-guards.js.map +1 -1
- package/dist/core/extensions/capability-runtime-manifest.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-manifest.js +52 -30
- package/dist/core/extensions/capability-runtime-manifest.js.map +1 -1
- package/dist/core/extensions/capability-runtime-validation.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime-validation.js +66 -65
- package/dist/core/extensions/capability-runtime-validation.js.map +1 -1
- package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
- package/dist/core/extensions/capability-runtime.js +147 -127
- package/dist/core/extensions/capability-runtime.js.map +1 -1
- package/dist/core/extensions/compaction-memory-failure-mode.d.ts.map +1 -1
- package/dist/core/extensions/compaction-memory-failure-mode.js +3 -2
- package/dist/core/extensions/compaction-memory-failure-mode.js.map +1 -1
- package/dist/core/extensions/context-strategy-binding.d.ts.map +1 -1
- package/dist/core/extensions/context-strategy-binding.js +7 -4
- package/dist/core/extensions/context-strategy-binding.js.map +1 -1
- package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
- package/dist/core/extensions/lifecycle-catalog.js +290 -279
- package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
- package/dist/core/extensions/lifecycle-delivery-queue.d.ts.map +1 -1
- package/dist/core/extensions/lifecycle-delivery-queue.js +3 -2
- package/dist/core/extensions/lifecycle-delivery-queue.js.map +1 -1
- package/dist/core/extensions/provider-failover.d.ts +7 -3
- package/dist/core/extensions/provider-failover.d.ts.map +1 -1
- package/dist/core/extensions/provider-failover.js +9 -8
- package/dist/core/extensions/provider-failover.js.map +1 -1
- package/dist/core/facade/coding-agent-facade.d.ts +6 -6
- package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
- package/dist/core/facade/coding-agent-facade.js +2 -3
- package/dist/core/facade/coding-agent-facade.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/i18n/index.d.ts +14 -0
- package/dist/core/i18n/index.d.ts.map +1 -0
- package/dist/core/i18n/index.js +67 -0
- package/dist/core/i18n/index.js.map +1 -0
- package/dist/core/i18n/locales/en/example.d.ts +7 -0
- package/dist/core/i18n/locales/en/example.d.ts.map +1 -0
- package/dist/core/i18n/locales/en/example.js +7 -0
- package/dist/core/i18n/locales/en/example.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/cli.d.ts +8 -0
- package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/cli.js +229 -0
- package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/common.d.ts +6 -0
- package/dist/core/i18n/locales/zh-cn/common.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/common.js +6 -0
- package/dist/core/i18n/locales/zh-cn/common.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts +13 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js +173 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-core.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts +12 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js +582 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-extensions.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.js +55 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts +11 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +455 -0
- package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.js +191 -0
- package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/example.d.ts +7 -0
- package/dist/core/i18n/locales/zh-cn/example.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/example.js +10 -0
- package/dist/core/i18n/locales/zh-cn/example.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/index.d.ts +2 -0
- package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/index.js +41 -0
- package/dist/core/i18n/locales/zh-cn/index.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts +10 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js +267 -0
- package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.d.ts +11 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.js +67 -0
- package/dist/core/i18n/locales/zh-cn/keybindings.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts +7 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.js +39 -0
- package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts +10 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.js +15 -0
- package/dist/core/i18n/locales/zh-cn/tui-builtin.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts +13 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +102 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts +12 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js +286 -0
- package/dist/core/i18n/locales/zh-cn/tui-components-selectors.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts +9 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js +79 -0
- package/dist/core/i18n/locales/zh-cn/tui-interactive-misc.js.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts +8 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.d.ts.map +1 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.js +72 -0
- package/dist/core/i18n/locales/zh-cn/tui-self-owned.js.map +1 -0
- package/dist/core/keybindings.d.ts +15 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +18 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +5 -1
- package/dist/core/logger.js.map +1 -1
- package/dist/core/model-config.d.ts +0 -1
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +9 -1
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +11 -7
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-install-host.d.ts.map +1 -1
- package/dist/core/package-install-host.js +4 -3
- package/dist/core/package-install-host.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +15 -10
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-resource-collection.d.ts.map +1 -1
- package/dist/core/package-resource-collection.js +2 -1
- package/dist/core/package-resource-collection.js.map +1 -1
- package/dist/core/package-source.d.ts.map +1 -1
- package/dist/core/package-source.js +3 -2
- package/dist/core/package-source.js.map +1 -1
- package/dist/core/provider-composer.d.ts +2 -2
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +29 -21
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +6 -2
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +15 -5
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/sdk.d.ts +27 -5
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +80 -55
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts.map +1 -1
- package/dist/core/session-cwd.js +5 -2
- package/dist/core/session-cwd.js.map +1 -1
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +2 -1
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +39 -29
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-storage.d.ts.map +1 -1
- package/dist/core/session-storage.js +3 -3
- package/dist/core/session-storage.js.map +1 -1
- package/dist/core/settings-manager.d.ts +20 -20
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +47 -59
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +53 -32
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +25 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +11 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +9 -4
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +4 -3
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +3 -2
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +2 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +6 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/durable/durable-service.d.ts.map +1 -1
- package/dist/durable/durable-service.js +25 -18
- package/dist/durable/durable-service.js.map +1 -1
- package/dist/host/checkpoint-commit.d.ts.map +1 -1
- package/dist/host/checkpoint-commit.js +2 -1
- package/dist/host/checkpoint-commit.js.map +1 -1
- package/dist/host/manual-compaction.d.ts.map +1 -1
- package/dist/host/manual-compaction.js +2 -1
- package/dist/host/manual-compaction.js.map +1 -1
- package/dist/host/output-projection.d.ts +0 -13
- package/dist/host/output-projection.d.ts.map +1 -1
- package/dist/host/output-projection.js +16 -2
- package/dist/host/output-projection.js.map +1 -1
- package/dist/host/summary-retry.d.ts.map +1 -1
- package/dist/host/summary-retry.js +3 -2
- package/dist/host/summary-retry.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +97 -60
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
- package/dist/modes/interactive/components/agents-view.js +18 -15
- package/dist/modes/interactive/components/agents-view.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +6 -5
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +12 -7
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +2 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +6 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +9 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +18 -15
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +2 -1
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-editor.js +5 -4
- package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
- package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-input.js +2 -1
- package/dist/modes/interactive/components/dialog-input.js.map +1 -1
- package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/dialog-selector.js +4 -3
- package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +11 -10
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +0 -2
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +8 -10
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +3 -2
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +12 -11
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
- package/dist/modes/interactive/components/mermaid.js +6 -2
- package/dist/modes/interactive/components/mermaid.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +28 -16
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +10 -9
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/plugin-manager-entry.js +22 -13
- package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
- package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/plugin-selection-entry.js +27 -12
- package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
- package/dist/modes/interactive/components/queue-manager-selector.d.ts +60 -0
- package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/queue-manager-selector.js +166 -0
- package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +16 -14
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +43 -31
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -6
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +115 -120
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.js +5 -4
- package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +3 -2
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +4 -3
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +14 -5
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +2 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +11 -4
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +8 -3
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-list.js +7 -6
- package/dist/modes/interactive/components/tree-list.js.map +1 -1
- package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-render.js +28 -23
- package/dist/modes/interactive/components/tree-render.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +9 -7
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +5 -4
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
- package/dist/modes/interactive/components/workflow-view.js +36 -21
- package/dist/modes/interactive/components/workflow-view.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +2 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-auth.js +71 -40
- package/dist/modes/interactive/interactive-auth.js.map +1 -1
- package/dist/modes/interactive/interactive-commands.d.ts +1 -0
- package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-commands.js +3 -0
- package/dist/modes/interactive/interactive-commands.js.map +1 -1
- package/dist/modes/interactive/interactive-dialog-ui.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-dialog-ui.js +5 -5
- package/dist/modes/interactive/interactive-dialog-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-format.js +34 -18
- package/dist/modes/interactive/interactive-format.js.map +1 -1
- package/dist/modes/interactive/interactive-helpers.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-helpers.js +7 -2
- package/dist/modes/interactive/interactive-helpers.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +350 -279
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.d.ts +9 -0
- package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +79 -25
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +5 -1
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +26 -23
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +3 -2
- package/dist/modes/json-event.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +0 -8
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +3 -14
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +0 -9
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +0 -19
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +28 -13
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/plugins/ecosystem/catalog.d.ts.map +1 -1
- package/dist/plugins/ecosystem/catalog.js +3 -2
- package/dist/plugins/ecosystem/catalog.js.map +1 -1
- package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
- package/dist/plugins/ecosystem/cli.js +2 -1
- package/dist/plugins/ecosystem/cli.js.map +1 -1
- package/dist/plugins/ecosystem/default-plugin-market.d.ts.map +1 -1
- package/dist/plugins/ecosystem/default-plugin-market.js +3 -2
- package/dist/plugins/ecosystem/default-plugin-market.js.map +1 -1
- package/dist/plugins/ecosystem/distribution.d.ts.map +1 -1
- package/dist/plugins/ecosystem/distribution.js +2 -1
- package/dist/plugins/ecosystem/distribution.js.map +1 -1
- package/dist/plugins/ecosystem/installer.d.ts.map +1 -1
- package/dist/plugins/ecosystem/installer.js +3 -2
- package/dist/plugins/ecosystem/installer.js.map +1 -1
- package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-disk-registry-source.js +20 -17
- package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-distribution-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-distribution-host.js +35 -34
- package/dist/plugins/ecosystem/node-distribution-host.js.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-npm-registry-source.js +35 -34
- package/dist/plugins/ecosystem/node-npm-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.js +9 -8
- package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-persistence.js +4 -3
- package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +9 -2
- package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js +44 -5
- package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-trust-root.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-plugin-trust-root.js +10 -9
- package/dist/plugins/ecosystem/node-plugin-trust-root.js.map +1 -1
- package/dist/plugins/ecosystem/node-registry-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-registry-source.js +31 -30
- package/dist/plugins/ecosystem/node-registry-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-release-package-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-release-package-source.js +30 -29
- package/dist/plugins/ecosystem/node-release-package-source.js.map +1 -1
- package/dist/plugins/ecosystem/node-tar-writer.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-tar-writer.js +11 -10
- package/dist/plugins/ecosystem/node-tar-writer.js.map +1 -1
- package/dist/plugins/ecosystem/node-url-package-source.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-url-package-source.js +21 -20
- package/dist/plugins/ecosystem/node-url-package-source.js.map +1 -1
- package/dist/plugins/ecosystem/plugin-acquisition.d.ts.map +1 -1
- package/dist/plugins/ecosystem/plugin-acquisition.js +3 -2
- package/dist/plugins/ecosystem/plugin-acquisition.js.map +1 -1
- package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +9 -1
- package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
- package/dist/plugins/ecosystem/plugin-bootstrap.js +5 -0
- package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.d.ts.map +1 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.js +2 -1
- package/dist/plugins/ecosystem/registry-cli-adapter.js.map +1 -1
- package/dist/plugins/ecosystem/registry.d.ts.map +1 -1
- package/dist/plugins/ecosystem/registry.js +35 -32
- package/dist/plugins/ecosystem/registry.js.map +1 -1
- package/dist/plugins/ecosystem/resolver.d.ts.map +1 -1
- package/dist/plugins/ecosystem/resolver.js +3 -2
- package/dist/plugins/ecosystem/resolver.js.map +1 -1
- package/dist/plugins/ecosystem/selection-store.d.ts.map +1 -1
- package/dist/plugins/ecosystem/selection-store.js +11 -10
- package/dist/plugins/ecosystem/selection-store.js.map +1 -1
- package/dist/plugins/ecosystem/selection.d.ts.map +1 -1
- package/dist/plugins/ecosystem/selection.js +8 -7
- package/dist/plugins/ecosystem/selection.js.map +1 -1
- package/dist/plugins/ecosystem/state.d.ts.map +1 -1
- package/dist/plugins/ecosystem/state.js +24 -23
- package/dist/plugins/ecosystem/state.js.map +1 -1
- package/dist/plugins/ecosystem/updates.d.ts.map +1 -1
- package/dist/plugins/ecosystem/updates.js +5 -4
- package/dist/plugins/ecosystem/updates.js.map +1 -1
- package/dist/plugins/mcp-http.d.ts +0 -17
- package/dist/plugins/mcp-http.d.ts.map +1 -1
- package/dist/plugins/mcp-http.js +30 -7
- package/dist/plugins/mcp-http.js.map +1 -1
- package/dist/plugins/plugin-supervisor.d.ts.map +1 -1
- package/dist/plugins/plugin-supervisor.js +19 -1
- package/dist/plugins/plugin-supervisor.js.map +1 -1
- package/dist/profile/first-roles.d.ts.map +1 -1
- package/dist/profile/first-roles.js +10 -1
- package/dist/profile/first-roles.js.map +1 -1
- package/dist/profile/goal-plugin.d.ts.map +1 -1
- package/dist/profile/goal-plugin.js +24 -5
- package/dist/profile/goal-plugin.js.map +1 -1
- package/dist/profile/identity.d.ts.map +1 -1
- package/dist/profile/identity.js +7 -6
- package/dist/profile/identity.js.map +1 -1
- package/dist/profile/lock.d.ts.map +1 -1
- package/dist/profile/lock.js +15 -1
- package/dist/profile/lock.js.map +1 -1
- package/dist/profile/plan-plugin.d.ts.map +1 -1
- package/dist/profile/plan-plugin.js +26 -13
- package/dist/profile/plan-plugin.js.map +1 -1
- package/dist/profile/plugin-profiles.d.ts.map +1 -1
- package/dist/profile/plugin-profiles.js +2 -1
- package/dist/profile/plugin-profiles.js.map +1 -1
- package/dist/profile/policy-manifest.d.ts.map +1 -1
- package/dist/profile/policy-manifest.js +5 -4
- package/dist/profile/policy-manifest.js.map +1 -1
- package/dist/profile/profile-registry.d.ts +0 -12
- package/dist/profile/profile-registry.d.ts.map +1 -1
- package/dist/profile/profile-registry.js +14 -1
- package/dist/profile/profile-registry.js.map +1 -1
- package/dist/profile/role-catalog.d.ts +0 -1
- package/dist/profile/role-catalog.d.ts.map +1 -1
- package/dist/profile/role-catalog.js +17 -15
- package/dist/profile/role-catalog.js.map +1 -1
- package/dist/profile/role-orchestrator.d.ts.map +1 -1
- package/dist/profile/role-orchestrator.js +8 -7
- package/dist/profile/role-orchestrator.js.map +1 -1
- package/dist/profile/role-runner.d.ts.map +1 -1
- package/dist/profile/role-runner.js +3 -2
- package/dist/profile/role-runner.js.map +1 -1
- package/dist/profile/root-facade.d.ts.map +1 -1
- package/dist/profile/root-facade.js +2 -1
- package/dist/profile/root-facade.js.map +1 -1
- package/dist/profile/skill-discovery-wiring.d.ts.map +1 -1
- package/dist/profile/skill-discovery-wiring.js +7 -2
- package/dist/profile/skill-discovery-wiring.js.map +1 -1
- package/dist/profile/state-store.d.ts.map +1 -1
- package/dist/profile/state-store.js +13 -9
- package/dist/profile/state-store.js.map +1 -1
- package/dist/profile/todo-plugin.d.ts.map +1 -1
- package/dist/profile/todo-plugin.js +9 -4
- package/dist/profile/todo-plugin.js.map +1 -1
- package/dist/profiles/builtin-suites.d.ts +13 -6
- package/dist/profiles/builtin-suites.d.ts.map +1 -1
- package/dist/profiles/builtin-suites.js +15 -6
- package/dist/profiles/builtin-suites.js.map +1 -1
- package/dist/profiles/suite-loader.d.ts +25 -1
- package/dist/profiles/suite-loader.d.ts.map +1 -1
- package/dist/profiles/suite-loader.js +34 -9
- package/dist/profiles/suite-loader.js.map +1 -1
- package/dist/remote/server-entry.d.ts.map +1 -1
- package/dist/remote/server-entry.js +3 -2
- package/dist/remote/server-entry.js.map +1 -1
- package/dist/remote/session-source.d.ts.map +1 -1
- package/dist/remote/session-source.js +8 -4
- package/dist/remote/session-source.js.map +1 -1
- package/dist/share/session-share.d.ts.map +1 -1
- package/dist/share/session-share.js +14 -2
- package/dist/share/session-share.js.map +1 -1
- package/dist/testing/plugin-testkit.d.ts.map +1 -1
- package/dist/testing/plugin-testkit.js +4 -3
- package/dist/testing/plugin-testkit.js.map +1 -1
- package/dist/testing/runtime-delivery-queue.d.ts.map +1 -1
- package/dist/testing/runtime-delivery-queue.js +2 -1
- package/dist/testing/runtime-delivery-queue.js.map +1 -1
- package/dist/testing/session-plugin-testkit.d.ts.map +1 -1
- package/dist/testing/session-plugin-testkit.js +10 -7
- package/dist/testing/session-plugin-testkit.js.map +1 -1
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js +2 -1
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +7 -6
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/image-resize-worker.d.ts.map +1 -1
- package/dist/utils/image-resize-worker.js +3 -2
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/photon.d.ts +2 -2
- package/dist/utils/photon.d.ts.map +1 -1
- package/dist/utils/photon.js +2 -2
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +9 -8
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +23 -13
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +5 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +1 -3
- package/docs/docs.json +4 -0
- package/docs/index.md +1 -0
- package/docs/keybindings.md +3 -0
- package/docs/mcp.md +103 -0
- package/docs/models.md +14 -22
- package/docs/providers.md +0 -1
- package/docs/quickstart.md +1 -1
- package/docs/rpc.md +1 -26
- package/docs/sdk.md +4 -6
- package/docs/settings.md +10 -12
- package/docs/skills.md +1 -9
- package/docs/terminal-setup.md +2 -3
- package/docs/usage.md +7 -6
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/with-deps/plugin.json +1 -1
- package/examples/sdk/10-settings.ts +2 -4
- package/examples/sdk/12-full-control.ts +1 -2
- package/package.json +1 -3
- package/dist/bundle/chunks/chunk-EALJ5DDX.js +0 -1452
- package/dist/core/extensions/microcompact.d.ts +0 -80
- package/dist/core/extensions/microcompact.d.ts.map +0 -1
- package/dist/core/extensions/microcompact.js +0 -134
- package/dist/core/extensions/microcompact.js.map +0 -1
- package/dist/server/create-harness.d.ts +0 -26
- package/dist/server/create-harness.d.ts.map +0 -1
- package/dist/server/create-harness.js +0 -106
- package/dist/server/create-harness.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-selection-entry.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-selection-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host-owned plugin selection entry for the config screen.\n *\n * This component deliberately renders only counts and bounded status. The\n * catalog, selection IDs, adapters, paths, credentials, and plugin payloads\n * stay behind the injected host contract.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginSelectionControllerResultV1,\n\tPluginSelectionControllerV1,\n\tPluginSelectionUiPluginV1,\n\tPluginSelectionUiProfileV1,\n\tPluginSelectionUiSnapshotV1,\n} from \"../../../cli/plugin-selection-controller.ts\";\nimport type { PluginCatalogSnapshotV1 } from \"../../../plugins/ecosystem/catalog.ts\";\nimport type { PluginSelectionV1 } from \"../../../plugins/ecosystem/selection.ts\";\nimport type {\n\tPluginSelectionStoreDiagnosticCodeV1,\n\tPluginSelectionStoreReadResultV1,\n\tPluginSelectionStoreV1,\n} from \"../../../plugins/ecosystem/selection-store.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nconst MAX_PROFILE_ID_CHARS = 128;\nconst MAX_SELECTION_IDS = 128;\nconst MAX_CATALOG_ENTRIES = 256;\nconst MAX_DIAGNOSTIC_CODES = 16;\n\nexport interface PluginSelectionSummaryV1 {\n\treadonly present: boolean;\n\treadonly selectedCount: number;\n\treadonly disabledCount: number;\n\treadonly truncated: boolean;\n}\n\nexport interface PluginCatalogSummaryV1 {\n\treadonly present: boolean;\n\treadonly entryCount: number;\n\treadonly readyCount: number;\n\treadonly unavailableCount: number;\n\treadonly truncated: boolean;\n}\n\nexport type PluginSelectionEntryStatusV1 = \"ready\" | \"missing\" | \"unsupported\" | \"invalid\" | \"cancelled\";\n\nexport interface PluginSelectionOpenContextV1 {\n\treadonly profileId: string;\n\treadonly status: PluginSelectionEntryStatusV1;\n\treadonly selection: PluginSelectionSummaryV1;\n\treadonly catalog: PluginCatalogSummaryV1;\n\treadonly diagnosticCodes: readonly PluginSelectionStoreDiagnosticCodeV1[];\n}\n\nexport type PluginSelectionEntryOpenResultV1 = PluginSelectionOpenContextV1;\n\nexport interface PluginSelectionEntryOptionsV1 {\n\treadonly profileId: string;\n\treadonly store?: PluginSelectionStoreV1;\n\treadonly selection?: PluginSelectionV1;\n\treadonly catalog?: PluginCatalogSnapshotV1;\n\treadonly controller?: PluginSelectionControllerV1;\n\treadonly snapshot?: PluginSelectionUiSnapshotV1;\n\t/** Host callback that opens the independent plugin selection surface. */\n\treadonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nfunction boundedCount(value: readonly unknown[] | undefined, maximum: number): { count: number; truncated: boolean } {\n\tif (value === undefined) return { count: 0, truncated: false };\n\treturn { count: Math.min(value.length, maximum), truncated: value.length > maximum };\n}\n\nexport function summarizePluginSelectionV1(selection: PluginSelectionV1 | undefined): PluginSelectionSummaryV1 {\n\tif (selection === undefined) {\n\t\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n\t}\n\tconst selected = boundedCount(selection.selectedPluginIds, MAX_SELECTION_IDS);\n\tconst disabled = boundedCount(selection.disabledPluginIds, MAX_SELECTION_IDS);\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tselectedCount: selected.count,\n\t\tdisabledCount: disabled.count,\n\t\ttruncated: selected.truncated || disabled.truncated,\n\t});\n}\n\nexport function summarizePluginCatalogV1(catalog: PluginCatalogSnapshotV1 | undefined): PluginCatalogSummaryV1 {\n\tif (catalog === undefined) {\n\t\treturn Object.freeze({ present: false, entryCount: 0, readyCount: 0, unavailableCount: 0, truncated: false });\n\t}\n\tconst entries = catalog.entries.slice(0, MAX_CATALOG_ENTRIES);\n\tconst readyCount = entries.filter((entry) => entry.resolution.status === \"installed-ready\").length;\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tentryCount: entries.length,\n\t\treadyCount,\n\t\tunavailableCount: entries.length - readyCount,\n\t\ttruncated: catalog.truncated || catalog.entries.length > MAX_CATALOG_ENTRIES,\n\t});\n}\n\nfunction validateProfileId(profileId: string): string {\n\tif (\n\t\ttypeof profileId !== \"string\" ||\n\t\tprofileId.trim().length === 0 ||\n\t\tprofileId.length > MAX_PROFILE_ID_CHARS ||\n\t\t/[\\u0000-\\u001f]/u.test(profileId)\n\t) {\n\t\tthrow new Error(\"invalid plugin selection profile ID\");\n\t}\n\treturn profileId;\n}\n\nfunction emptySelectionSummary(): PluginSelectionSummaryV1 {\n\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n}\n\nfunction diagnosticCodes(result: PluginSelectionStoreReadResultV1): readonly PluginSelectionStoreDiagnosticCodeV1[] {\n\tif (result.status === \"ok\" || result.status === \"missing\") return Object.freeze([]);\n\treturn Object.freeze(result.diagnostics.slice(0, MAX_DIAGNOSTIC_CODES).map((item) => item.code));\n}\n\nfunction selectionForProfile(\n\tresult: Extract<PluginSelectionStoreReadResultV1, { readonly status: \"ok\" | \"missing\" }>,\n\tprofileId: string,\n): PluginSelectionV1 | undefined {\n\treturn result.snapshot.selections.find((selection) => selection.profileId === profileId);\n}\n\n/**\n * A non-focusable entry. The surrounding config selector can expose\n * `openPluginSelection()` to its host without assigning plugin actions to the\n * legacy resource list or inventing a new global key binding.\n */\nexport class PluginSelectionEntryComponent implements Component, Focusable {\n\tprivate readonly profileId: string;\n\tprivate readonly store?: PluginSelectionStoreV1;\n\tprivate readonly controller?: PluginSelectionControllerV1;\n\tprivate readonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate selection: PluginSelectionSummaryV1;\n\tprivate readonly catalog: PluginCatalogSummaryV1;\n\tprivate uiProfile?: PluginSelectionUiProfileV1;\n\tprivate uiPluginIndex = 0;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginSelectionEntryOptionsV1) {\n\t\tthis.profileId = validateProfileId(options.profileId);\n\t\tif (options.selection !== undefined && options.selection.profileId !== this.profileId) {\n\t\t\tthrow new Error(\"plugin selection profile does not match the entry profile\");\n\t\t}\n\t\tthis.store = options.store;\n\t\tthis.controller = options.controller;\n\t\tthis.onOpen = options.onOpen;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tthis.selection = summarizePluginSelectionV1(options.selection);\n\t\tthis.catalog = summarizePluginCatalogV1(options.catalog);\n\t\tthis.uiProfile = options.snapshot?.profiles.find((profile) => profile.profileId === this.profileId);\n\t}\n\n\tprivate hasHostEntry(): boolean {\n\t\treturn this.store !== undefined || this.controller !== undefined || this.onOpen !== undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this.hasHostEntry()) {\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"dim\", \" Plugins: unsupported (host selection entry not injected)\"),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tif (this._focused && this.uiProfile !== undefined) {\n\t\t\tconst lines = [truncateToWidth(theme.bold(` Plugins · ${this.uiProfile.profileId}`), width, \"...\")];\n\t\t\tfor (const [index, plugin] of this.uiProfile.plugins.entries()) {\n\t\t\t\tconst cursor = index === this.uiPluginIndex ? \">\" : \" \";\n\t\t\t\tconst state = plugin.state === \"selected\" ? \"on\" : plugin.state === \"disabled\" ? \"off\" : \"available\";\n\t\t\t\tconst availability = plugin.availability === \"ready\" ? \"ready\" : \"unavailable\";\n\t\t\t\tlines.push(truncateToWidth(` ${cursor} [${state}] ${plugin.pluginId} (${availability})`, width, \"...\"));\n\t\t\t}\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", \" Enter/Space toggle · Esc close\"), width, \"...\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selectionText = this.selection.present\n\t\t\t? `selected ${this.selection.selectedCount}, disabled ${this.selection.disabledCount}${\n\t\t\t\t\tthis.selection.truncated ? \", bounded\" : \"\"\n\t\t\t\t}`\n\t\t\t: this.store === undefined\n\t\t\t\t? \"selection pending\"\n\t\t\t\t: \"selection not loaded\";\n\t\tconst catalogText = this.catalog.present\n\t\t\t? `catalog ${this.catalog.entryCount} (${this.catalog.readyCount} ready, ${this.catalog.unavailableCount} unavailable${\n\t\t\t\t\tthis.catalog.truncated ? \", bounded\" : \"\"\n\t\t\t\t})`\n\t\t\t: \"catalog unavailable\";\n\t\tconst suffix = this.onOpen === undefined ? \"host store\" : \"open via host callback\";\n\t\treturn [\n\t\t\ttruncateToWidth(\n\t\t\t\ttheme.fg(\"muted\", ` Plugins: profile ${this.profileId} · ${selectionText} · ${catalogText} · ${suffix}`),\n\t\t\t\twidth,\n\t\t\t\t\"...\",\n\t\t\t),\n\t\t];\n\t}\n\n\tprivate setUiSnapshot(result: PluginSelectionControllerResultV1): void {\n\t\tif (result.status !== \"ok\") return;\n\t\tthis.uiProfile = result.snapshot.profiles.find((profile) => profile.profileId === this.profileId);\n\t\tif (this.uiProfile !== undefined) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiPluginIndex, Math.max(0, this.uiProfile.plugins.length - 1));\n\t\t}\n\t}\n\n\tprivate currentUiPlugin(): PluginSelectionUiPluginV1 | undefined {\n\t\treturn this.uiProfile?.plugins[this.uiPluginIndex];\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused || this.uiProfile === undefined) return;\n\t\tconst keybindings = getKeybindings();\n\t\tif (keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.uiPluginIndex = Math.max(0, this.uiPluginIndex - 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiProfile.plugins.length - 1, this.uiPluginIndex + 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (!keybindings.matches(data, \"tui.select.confirm\") && data !== \" \") return;\n\t\tconst plugin = this.currentUiPlugin();\n\t\tif (\n\t\t\tplugin === undefined ||\n\t\t\tthis.controller === undefined ||\n\t\t\t(plugin.state === \"disabled\" && plugin.availability !== \"ready\")\n\t\t)\n\t\t\treturn;\n\t\tvoid this.controller\n\t\t\t.toggle({ profileId: this.profileId, pluginId: plugin.pluginId })\n\t\t\t.then((result) => {\n\t\t\t\tthis.setUiSnapshot(result);\n\t\t\t\tthis.requestRender?.();\n\t\t\t})\n\t\t\t.catch(() => this.requestRender?.());\n\t}\n\n\t/** Read the bounded selection DTO and invoke the host-owned entry callback. */\n\tasync openPluginSelection(): Promise<PluginSelectionEntryOpenResultV1> {\n\t\tlet controllerResult: PluginSelectionControllerResultV1 | undefined;\n\t\tif (this.controller !== undefined) {\n\t\t\tcontrollerResult = await this.controller.getSnapshot();\n\t\t\tthis.setUiSnapshot(controllerResult);\n\t\t}\n\t\tlet status: PluginSelectionEntryStatusV1 = this.hasHostEntry() ? \"ready\" : \"unsupported\";\n\t\tlet selection = this.selection;\n\t\tlet codes: readonly PluginSelectionStoreDiagnosticCodeV1[] = Object.freeze([]);\n\t\tif (controllerResult?.status === \"error\") {\n\t\t\tstatus = controllerResult.code === \"store-cancelled\" ? \"cancelled\" : \"invalid\";\n\t\t}\n\n\t\tif (this.store !== undefined) {\n\t\t\tconst result = await this.store.read();\n\t\t\tcodes = diagnosticCodes(result);\n\t\t\tif (result.status === \"ok\" || result.status === \"missing\") {\n\t\t\t\tconst storedSelection = selectionForProfile(result, this.profileId);\n\t\t\t\tselection = summarizePluginSelectionV1(storedSelection);\n\t\t\t\tstatus = result.status === \"ok\" ? \"ready\" : \"missing\";\n\t\t\t} else {\n\t\t\t\tselection = emptySelectionSummary();\n\t\t\t\tstatus = result.status;\n\t\t\t}\n\t\t\tthis.selection = selection;\n\t\t}\n\n\t\tconst context: PluginSelectionOpenContextV1 = Object.freeze({\n\t\t\tprofileId: this.profileId,\n\t\t\tstatus,\n\t\t\tselection,\n\t\t\tcatalog: this.catalog,\n\t\t\tdiagnosticCodes: codes,\n\t\t});\n\t\tif (this.onOpen !== undefined) await this.onOpen(context);\n\t\treturn context;\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectionSummary(): PluginSelectionSummaryV1 {\n\t\treturn this.selection;\n\t}\n\n\tgetCatalogSummary(): PluginCatalogSummaryV1 {\n\t\treturn this.catalog;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plugin-selection-entry.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/plugin-selection-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Host-owned plugin selection entry for the config screen.\n *\n * This component deliberately renders only counts and bounded status. The\n * catalog, selection IDs, adapters, paths, credentials, and plugin payloads\n * stay behind the injected host contract.\n */\n\nimport { type Component, type Focusable, getKeybindings, truncateToWidth } from \"@agent-forge/tui\";\nimport type {\n\tPluginSelectionControllerResultV1,\n\tPluginSelectionControllerV1,\n\tPluginSelectionUiPluginV1,\n\tPluginSelectionUiProfileV1,\n\tPluginSelectionUiSnapshotV1,\n} from \"../../../cli/plugin-selection-controller.ts\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport type { PluginCatalogSnapshotV1 } from \"../../../plugins/ecosystem/catalog.ts\";\nimport type { PluginSelectionV1 } from \"../../../plugins/ecosystem/selection.ts\";\nimport type {\n\tPluginSelectionStoreDiagnosticCodeV1,\n\tPluginSelectionStoreReadResultV1,\n\tPluginSelectionStoreV1,\n} from \"../../../plugins/ecosystem/selection-store.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nconst MAX_PROFILE_ID_CHARS = 128;\nconst MAX_SELECTION_IDS = 128;\nconst MAX_CATALOG_ENTRIES = 256;\nconst MAX_DIAGNOSTIC_CODES = 16;\n\nexport interface PluginSelectionSummaryV1 {\n\treadonly present: boolean;\n\treadonly selectedCount: number;\n\treadonly disabledCount: number;\n\treadonly truncated: boolean;\n}\n\nexport interface PluginCatalogSummaryV1 {\n\treadonly present: boolean;\n\treadonly entryCount: number;\n\treadonly readyCount: number;\n\treadonly unavailableCount: number;\n\treadonly truncated: boolean;\n}\n\nexport type PluginSelectionEntryStatusV1 = \"ready\" | \"missing\" | \"unsupported\" | \"invalid\" | \"cancelled\";\n\nexport interface PluginSelectionOpenContextV1 {\n\treadonly profileId: string;\n\treadonly status: PluginSelectionEntryStatusV1;\n\treadonly selection: PluginSelectionSummaryV1;\n\treadonly catalog: PluginCatalogSummaryV1;\n\treadonly diagnosticCodes: readonly PluginSelectionStoreDiagnosticCodeV1[];\n}\n\nexport type PluginSelectionEntryOpenResultV1 = PluginSelectionOpenContextV1;\n\nexport interface PluginSelectionEntryOptionsV1 {\n\treadonly profileId: string;\n\treadonly store?: PluginSelectionStoreV1;\n\treadonly selection?: PluginSelectionV1;\n\treadonly catalog?: PluginCatalogSnapshotV1;\n\treadonly controller?: PluginSelectionControllerV1;\n\treadonly snapshot?: PluginSelectionUiSnapshotV1;\n\t/** Host callback that opens the independent plugin selection surface. */\n\treadonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\t/** Called when the entry is closed after keyboard focus was transferred to it. */\n\treadonly onClose?: () => void;\n\t/** Request a render after an asynchronous host operation completes. */\n\treadonly requestRender?: () => void;\n}\n\nfunction boundedCount(value: readonly unknown[] | undefined, maximum: number): { count: number; truncated: boolean } {\n\tif (value === undefined) return { count: 0, truncated: false };\n\treturn { count: Math.min(value.length, maximum), truncated: value.length > maximum };\n}\n\nexport function summarizePluginSelectionV1(selection: PluginSelectionV1 | undefined): PluginSelectionSummaryV1 {\n\tif (selection === undefined) {\n\t\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n\t}\n\tconst selected = boundedCount(selection.selectedPluginIds, MAX_SELECTION_IDS);\n\tconst disabled = boundedCount(selection.disabledPluginIds, MAX_SELECTION_IDS);\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tselectedCount: selected.count,\n\t\tdisabledCount: disabled.count,\n\t\ttruncated: selected.truncated || disabled.truncated,\n\t});\n}\n\nexport function summarizePluginCatalogV1(catalog: PluginCatalogSnapshotV1 | undefined): PluginCatalogSummaryV1 {\n\tif (catalog === undefined) {\n\t\treturn Object.freeze({ present: false, entryCount: 0, readyCount: 0, unavailableCount: 0, truncated: false });\n\t}\n\tconst entries = catalog.entries.slice(0, MAX_CATALOG_ENTRIES);\n\tconst readyCount = entries.filter((entry) => entry.resolution.status === \"installed-ready\").length;\n\treturn Object.freeze({\n\t\tpresent: true,\n\t\tentryCount: entries.length,\n\t\treadyCount,\n\t\tunavailableCount: entries.length - readyCount,\n\t\ttruncated: catalog.truncated || catalog.entries.length > MAX_CATALOG_ENTRIES,\n\t});\n}\n\nfunction validateProfileId(profileId: string): string {\n\tif (\n\t\ttypeof profileId !== \"string\" ||\n\t\tprofileId.trim().length === 0 ||\n\t\tprofileId.length > MAX_PROFILE_ID_CHARS ||\n\t\t/[\\u0000-\\u001f]/u.test(profileId)\n\t) {\n\t\tthrow new Error(t(\"invalid plugin selection profile ID\"));\n\t}\n\treturn profileId;\n}\n\nfunction emptySelectionSummary(): PluginSelectionSummaryV1 {\n\treturn Object.freeze({ present: false, selectedCount: 0, disabledCount: 0, truncated: false });\n}\n\nfunction diagnosticCodes(result: PluginSelectionStoreReadResultV1): readonly PluginSelectionStoreDiagnosticCodeV1[] {\n\tif (result.status === \"ok\" || result.status === \"missing\") return Object.freeze([]);\n\treturn Object.freeze(result.diagnostics.slice(0, MAX_DIAGNOSTIC_CODES).map((item) => item.code));\n}\n\nfunction selectionForProfile(\n\tresult: Extract<PluginSelectionStoreReadResultV1, { readonly status: \"ok\" | \"missing\" }>,\n\tprofileId: string,\n): PluginSelectionV1 | undefined {\n\treturn result.snapshot.selections.find((selection) => selection.profileId === profileId);\n}\n\n/**\n * A non-focusable entry. The surrounding config selector can expose\n * `openPluginSelection()` to its host without assigning plugin actions to the\n * legacy resource list or inventing a new global key binding.\n */\nexport class PluginSelectionEntryComponent implements Component, Focusable {\n\tprivate readonly profileId: string;\n\tprivate readonly store?: PluginSelectionStoreV1;\n\tprivate readonly controller?: PluginSelectionControllerV1;\n\tprivate readonly onOpen?: (context: PluginSelectionOpenContextV1) => void | Promise<void>;\n\tprivate readonly onClose?: () => void;\n\tprivate readonly requestRender?: () => void;\n\tprivate selection: PluginSelectionSummaryV1;\n\tprivate readonly catalog: PluginCatalogSummaryV1;\n\tprivate uiProfile?: PluginSelectionUiProfileV1;\n\tprivate uiPluginIndex = 0;\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tconstructor(options: PluginSelectionEntryOptionsV1) {\n\t\tthis.profileId = validateProfileId(options.profileId);\n\t\tif (options.selection !== undefined && options.selection.profileId !== this.profileId) {\n\t\t\tthrow new Error(t(\"plugin selection profile does not match the entry profile\"));\n\t\t}\n\t\tthis.store = options.store;\n\t\tthis.controller = options.controller;\n\t\tthis.onOpen = options.onOpen;\n\t\tthis.onClose = options.onClose;\n\t\tthis.requestRender = options.requestRender;\n\t\tthis.selection = summarizePluginSelectionV1(options.selection);\n\t\tthis.catalog = summarizePluginCatalogV1(options.catalog);\n\t\tthis.uiProfile = options.snapshot?.profiles.find((profile) => profile.profileId === this.profileId);\n\t}\n\n\tprivate hasHostEntry(): boolean {\n\t\treturn this.store !== undefined || this.controller !== undefined || this.onOpen !== undefined;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (!this.hasHostEntry()) {\n\t\t\treturn [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.fg(\"dim\", ` ${t(\"Plugins: unsupported (host selection entry not injected)\")}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\n\t\tif (this._focused && this.uiProfile !== undefined) {\n\t\t\tconst lines = [\n\t\t\t\ttruncateToWidth(\n\t\t\t\t\ttheme.bold(` ${t(\"Plugins · {profile}\", { profile: this.uiProfile.profileId })}`),\n\t\t\t\t\twidth,\n\t\t\t\t\t\"...\",\n\t\t\t\t),\n\t\t\t];\n\t\t\tfor (const [index, plugin] of this.uiProfile.plugins.entries()) {\n\t\t\t\tconst cursor = index === this.uiPluginIndex ? \">\" : \" \";\n\t\t\t\tconst state = plugin.state === \"selected\" ? \"on\" : plugin.state === \"disabled\" ? \"off\" : \"available\";\n\t\t\t\tconst availability = plugin.availability === \"ready\" ? \"ready\" : \"unavailable\";\n\t\t\t\tlines.push(truncateToWidth(` ${cursor} [${state}] ${plugin.pluginId} (${availability})`, width, \"...\"));\n\t\t\t}\n\t\t\tlines.push(truncateToWidth(theme.fg(\"dim\", ` ${t(\"Enter/Space toggle · Esc close\")}`), width, \"...\"));\n\t\t\treturn lines;\n\t\t}\n\n\t\tconst selectionText = this.selection.present\n\t\t\t? t(\"selected {selected}, disabled {disabled}\", {\n\t\t\t\t\tselected: this.selection.selectedCount,\n\t\t\t\t\tdisabled: this.selection.disabledCount,\n\t\t\t\t}) + (this.selection.truncated ? t(\", bounded\") : \"\")\n\t\t\t: this.store === undefined\n\t\t\t\t? t(\"selection pending\")\n\t\t\t\t: t(\"selection not loaded\");\n\t\tconst catalogText = this.catalog.present\n\t\t\t? t(\"catalog {count} ({ready} ready, {unavailable} unavailable)\", {\n\t\t\t\t\tcount: this.catalog.entryCount,\n\t\t\t\t\tready: this.catalog.readyCount,\n\t\t\t\t\tunavailable: this.catalog.unavailableCount,\n\t\t\t\t}) + (this.catalog.truncated ? t(\", bounded\") : \"\")\n\t\t\t: t(\"catalog unavailable\");\n\t\tconst suffix = this.onOpen === undefined ? t(\"host store\") : t(\"open via host callback\");\n\t\treturn [\n\t\t\ttruncateToWidth(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\t` ${t(\"Plugins: profile {profile} · {selection} · {catalog} · {suffix}\", {\n\t\t\t\t\t\tprofile: this.profileId,\n\t\t\t\t\t\tselection: selectionText,\n\t\t\t\t\t\tcatalog: catalogText,\n\t\t\t\t\t\tsuffix,\n\t\t\t\t\t})}`,\n\t\t\t\t),\n\t\t\t\twidth,\n\t\t\t\t\"...\",\n\t\t\t),\n\t\t];\n\t}\n\n\tprivate setUiSnapshot(result: PluginSelectionControllerResultV1): void {\n\t\tif (result.status !== \"ok\") return;\n\t\tthis.uiProfile = result.snapshot.profiles.find((profile) => profile.profileId === this.profileId);\n\t\tif (this.uiProfile !== undefined) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiPluginIndex, Math.max(0, this.uiProfile.plugins.length - 1));\n\t\t}\n\t}\n\n\tprivate currentUiPlugin(): PluginSelectionUiPluginV1 | undefined {\n\t\treturn this.uiProfile?.plugins[this.uiPluginIndex];\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (!this._focused || this.uiProfile === undefined) return;\n\t\tconst keybindings = getKeybindings();\n\t\tif (keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.uiPluginIndex = Math.max(0, this.uiPluginIndex - 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.uiPluginIndex = Math.min(this.uiProfile.plugins.length - 1, this.uiPluginIndex + 1);\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis._focused = false;\n\t\t\tthis.onClose?.();\n\t\t\tthis.requestRender?.();\n\t\t\treturn;\n\t\t}\n\t\tif (!keybindings.matches(data, \"tui.select.confirm\") && data !== \" \") return;\n\t\tconst plugin = this.currentUiPlugin();\n\t\tif (\n\t\t\tplugin === undefined ||\n\t\t\tthis.controller === undefined ||\n\t\t\t(plugin.state === \"disabled\" && plugin.availability !== \"ready\")\n\t\t)\n\t\t\treturn;\n\t\tvoid this.controller\n\t\t\t.toggle({ profileId: this.profileId, pluginId: plugin.pluginId })\n\t\t\t.then((result) => {\n\t\t\t\tthis.setUiSnapshot(result);\n\t\t\t\tthis.requestRender?.();\n\t\t\t})\n\t\t\t.catch(() => this.requestRender?.());\n\t}\n\n\t/** Read the bounded selection DTO and invoke the host-owned entry callback. */\n\tasync openPluginSelection(): Promise<PluginSelectionEntryOpenResultV1> {\n\t\tlet controllerResult: PluginSelectionControllerResultV1 | undefined;\n\t\tif (this.controller !== undefined) {\n\t\t\tcontrollerResult = await this.controller.getSnapshot();\n\t\t\tthis.setUiSnapshot(controllerResult);\n\t\t}\n\t\tlet status: PluginSelectionEntryStatusV1 = this.hasHostEntry() ? \"ready\" : \"unsupported\";\n\t\tlet selection = this.selection;\n\t\tlet codes: readonly PluginSelectionStoreDiagnosticCodeV1[] = Object.freeze([]);\n\t\tif (controllerResult?.status === \"error\") {\n\t\t\tstatus = controllerResult.code === \"store-cancelled\" ? \"cancelled\" : \"invalid\";\n\t\t}\n\n\t\tif (this.store !== undefined) {\n\t\t\tconst result = await this.store.read();\n\t\t\tcodes = diagnosticCodes(result);\n\t\t\tif (result.status === \"ok\" || result.status === \"missing\") {\n\t\t\t\tconst storedSelection = selectionForProfile(result, this.profileId);\n\t\t\t\tselection = summarizePluginSelectionV1(storedSelection);\n\t\t\t\tstatus = result.status === \"ok\" ? \"ready\" : \"missing\";\n\t\t\t} else {\n\t\t\t\tselection = emptySelectionSummary();\n\t\t\t\tstatus = result.status;\n\t\t\t}\n\t\t\tthis.selection = selection;\n\t\t}\n\n\t\tconst context: PluginSelectionOpenContextV1 = Object.freeze({\n\t\t\tprofileId: this.profileId,\n\t\t\tstatus,\n\t\t\tselection,\n\t\t\tcatalog: this.catalog,\n\t\t\tdiagnosticCodes: codes,\n\t\t});\n\t\tif (this.onOpen !== undefined) await this.onOpen(context);\n\t\treturn context;\n\t}\n\n\tinvalidate(): void {}\n\n\tgetSelectionSummary(): PluginSelectionSummaryV1 {\n\t\treturn this.selection;\n\t}\n\n\tgetCatalogSummary(): PluginCatalogSummaryV1 {\n\t\treturn this.catalog;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type Component, Container } from "@agent-forge/tui";
|
|
2
|
+
/** Which queue an entry belongs to; mirrors the session's queue names. */
|
|
3
|
+
export type QueueName = "steer" | "followUp";
|
|
4
|
+
/** One row in the manager: the owning queue plus the queued text. */
|
|
5
|
+
export interface QueuedMessageEntry {
|
|
6
|
+
queue: QueueName;
|
|
7
|
+
text: string;
|
|
8
|
+
}
|
|
9
|
+
/** Queue snapshot shape the component consumes (same shape as the facade read view). */
|
|
10
|
+
export interface QueuedMessageSnapshot {
|
|
11
|
+
steering: string[];
|
|
12
|
+
followUp: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Host surface the queue manager consumes. The component never touches the
|
|
16
|
+
* facade: every mutation goes through these callbacks, so tests inject plain
|
|
17
|
+
* functions and the host owns facade forwarding and the editor restore.
|
|
18
|
+
*/
|
|
19
|
+
export interface QueueManagerCallbacks {
|
|
20
|
+
/** Re-read both queues after an operation; the component rebuilds its rows. */
|
|
21
|
+
refresh(): QueuedMessageSnapshot;
|
|
22
|
+
/** Move the entry at group index `from` to `to` within `queue`; false when invalid. */
|
|
23
|
+
onReorder(queue: QueueName, from: number, to: number): boolean;
|
|
24
|
+
/** Remove the entry at group `index`; the removed text, or null when invalid. */
|
|
25
|
+
onRemove(queue: QueueName, index: number): string | null;
|
|
26
|
+
/** Remove the entry and put its text back into the editor; false when invalid. */
|
|
27
|
+
onRestore(queue: QueueName, index: number): boolean;
|
|
28
|
+
/** Close the manager (escape, restore, or both queues empty after a remove). */
|
|
29
|
+
onClose(): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Flat queued-message list with selection, grouped steering-first. All key
|
|
33
|
+
* handling goes through getKeybindings().matches — no hardcoded key values.
|
|
34
|
+
*/
|
|
35
|
+
declare class QueueManagerList implements Component {
|
|
36
|
+
private entries;
|
|
37
|
+
private steeringCount;
|
|
38
|
+
private selectedIndex;
|
|
39
|
+
private readonly callbacks;
|
|
40
|
+
constructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks);
|
|
41
|
+
invalidate(): void;
|
|
42
|
+
render(width: number): string[];
|
|
43
|
+
handleInput(keyData: string): void;
|
|
44
|
+
/** Rebuild rows from a fresh snapshot; steering entries stay in front. */
|
|
45
|
+
private applySnapshot;
|
|
46
|
+
/** Group and within-group index of the selected entry. */
|
|
47
|
+
private selectedLocation;
|
|
48
|
+
private groupLength;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Component that renders the queued-message manager (/queue-list): grouped
|
|
52
|
+
* steering/follow-up entries with reorder, remove, and restore actions.
|
|
53
|
+
*/
|
|
54
|
+
export declare class QueueManagerSelectorComponent extends Container {
|
|
55
|
+
private readonly list;
|
|
56
|
+
constructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks);
|
|
57
|
+
getMessageList(): QueueManagerList;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=queue-manager-selector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-manager-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/queue-manager-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAiD,MAAM,kBAAkB,CAAC;AAK5G,0EAA0E;AAC1E,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAE7C,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wFAAwF;AACxF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC,+EAA+E;IAC/E,OAAO,IAAI,qBAAqB,CAAC;IACjC,uFAAuF;IACvF,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,iFAAiF;IACjF,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzD,kFAAkF;IAClF,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACpD,gFAAgF;IAChF,OAAO,IAAI,IAAI,CAAC;CAChB;AASD;;;GAGG;AACH,cAAM,gBAAiB,YAAW,SAAS;IAC1C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,YAAY,QAAQ,EAAE,qBAAqB,EAAE,SAAS,EAAE,qBAAqB,EAG5E;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqB9B;IAED,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAyDjC;IAED,0EAA0E;IAC1E,OAAO,CAAC,aAAa;IAOrB,0DAA0D;IAC1D,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,WAAW;CAGnB;AAED;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,SAAS;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IAExC,YAAY,QAAQ,EAAE,qBAAqB,EAAE,SAAS,EAAE,qBAAqB,EAwB5E;IAED,cAAc,IAAI,gBAAgB,CAEjC;CACD","sourcesContent":["import { type Component, Container, getKeybindings, Spacer, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\n/** Which queue an entry belongs to; mirrors the session's queue names. */\nexport type QueueName = \"steer\" | \"followUp\";\n\n/** One row in the manager: the owning queue plus the queued text. */\nexport interface QueuedMessageEntry {\n\tqueue: QueueName;\n\ttext: string;\n}\n\n/** Queue snapshot shape the component consumes (same shape as the facade read view). */\nexport interface QueuedMessageSnapshot {\n\tsteering: string[];\n\tfollowUp: string[];\n}\n\n/**\n * Host surface the queue manager consumes. The component never touches the\n * facade: every mutation goes through these callbacks, so tests inject plain\n * functions and the host owns facade forwarding and the editor restore.\n */\nexport interface QueueManagerCallbacks {\n\t/** Re-read both queues after an operation; the component rebuilds its rows. */\n\trefresh(): QueuedMessageSnapshot;\n\t/** Move the entry at group index `from` to `to` within `queue`; false when invalid. */\n\tonReorder(queue: QueueName, from: number, to: number): boolean;\n\t/** Remove the entry at group `index`; the removed text, or null when invalid. */\n\tonRemove(queue: QueueName, index: number): string | null;\n\t/** Remove the entry and put its text back into the editor; false when invalid. */\n\tonRestore(queue: QueueName, index: number): boolean;\n\t/** Close the manager (escape, restore, or both queues empty after a remove). */\n\tonClose(): void;\n}\n\nfunction flatten(snapshot: QueuedMessageSnapshot): QueuedMessageEntry[] {\n\treturn [\n\t\t...snapshot.steering.map((text): QueuedMessageEntry => ({ queue: \"steer\", text })),\n\t\t...snapshot.followUp.map((text): QueuedMessageEntry => ({ queue: \"followUp\", text })),\n\t];\n}\n\n/**\n * Flat queued-message list with selection, grouped steering-first. All key\n * handling goes through getKeybindings().matches — no hardcoded key values.\n */\nclass QueueManagerList implements Component {\n\tprivate entries: QueuedMessageEntry[] = [];\n\tprivate steeringCount = 0;\n\tprivate selectedIndex = 0;\n\tprivate readonly callbacks: QueueManagerCallbacks;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tthis.callbacks = callbacks;\n\t\tthis.applySnapshot(snapshot);\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tif (this.entries.length === 0) return lines;\n\n\t\tif (this.steeringCount > 0) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Steering\")}`));\n\t\t}\n\t\tfor (let i = 0; i < this.entries.length; i++) {\n\t\t\tconst entry = this.entries[i];\n\t\t\tconst opensFollowUpGroup = entry.queue === \"followUp\" && (i === 0 || this.entries[i - 1]?.queue === \"steer\");\n\t\t\tif (opensFollowUpGroup) {\n\t\t\t\tif (i > 0) lines.push(\"\");\n\t\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Follow-up\")}`));\n\t\t\t}\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst cursor = isSelected ? theme.fg(\"accent\", \"› \") : \" \";\n\t\t\tconst normalized = entry.text.replace(/\\n/g, \" \").trim();\n\t\t\tconst truncated = truncateToWidth(normalized, width - 2);\n\t\t\tlines.push(cursor + (isSelected ? theme.bold(truncated) : truncated));\n\t\t}\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up/down move the selection across the flat list, wrapping at the ends\n\t\t// (same semantics as UserMessageList).\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.entries.length - 1 : this.selectedIndex - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.entries.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst moveUp = kb.matches(keyData, \"app.queue.moveUp\");\n\t\tconst moveDown = kb.matches(keyData, \"app.queue.moveDown\");\n\t\tif (moveUp || moveDown) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tconst target = index + (moveUp ? -1 : 1);\n\t\t\t// Reorder stays inside the selected entry's group (bounds guard\n\t\t\t// mirrors the scoped-models selector); the facade stays the final\n\t\t\t// authority — a stale snapshot returns false and nothing moves.\n\t\t\tif (target < 0 || target >= this.groupLength(queue)) return;\n\t\t\tif (this.callbacks.onReorder(queue, index, target)) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(Math.max(this.selectedIndex + (moveUp ? -1 : 1), 0), this.entries.length - 1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.queue.remove\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRemove(queue, index) !== null) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\t\t\tif (this.entries.length === 0) this.callbacks.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRestore(queue, index)) this.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** Rebuild rows from a fresh snapshot; steering entries stay in front. */\n\tprivate applySnapshot(snapshot: QueuedMessageSnapshot): void {\n\t\tthis.entries = flatten(snapshot);\n\t\tthis.steeringCount = snapshot.steering.length;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\tif (this.selectedIndex < 0) this.selectedIndex = 0;\n\t}\n\n\t/** Group and within-group index of the selected entry. */\n\tprivate selectedLocation(): { queue: QueueName; index: number | undefined } {\n\t\tconst entry = this.entries[this.selectedIndex];\n\t\tif (!entry) return { queue: \"steer\", index: undefined };\n\t\treturn {\n\t\t\tqueue: entry.queue,\n\t\t\tindex: entry.queue === \"steer\" ? this.selectedIndex : this.selectedIndex - this.steeringCount,\n\t\t};\n\t}\n\n\tprivate groupLength(queue: QueueName): number {\n\t\treturn this.entries.filter((entry) => entry.queue === queue).length;\n\t}\n}\n\n/**\n * Component that renders the queued-message manager (/queue-list): grouped\n * steering/follow-up entries with reorder, remove, and restore actions.\n */\nexport class QueueManagerSelectorComponent extends Container {\n\tprivate readonly list: QueueManagerList;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tsuper();\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.bold(t(\"Queued Messages\")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.list = new QueueManagerList(snapshot, callbacks);\n\t\tthis.addChild(this.list);\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(theme.fg(\"muted\", t(\"alt+up/alt+down move · delete remove · enter restore · esc close\")), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Auto-close when mounted with both queues empty (the host gates the\n\t\t// open on non-empty queues; this covers the queue draining in between).\n\t\tif (snapshot.steering.length === 0 && snapshot.followUp.length === 0) {\n\t\t\tsetTimeout(() => callbacks.onClose(), 100);\n\t\t}\n\t}\n\n\tgetMessageList(): QueueManagerList {\n\t\treturn this.list;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Container, getKeybindings, Spacer, Text, truncateToWidth } from "@agent-forge/tui";
|
|
2
|
+
import { t } from "../../../core/i18n/index.js";
|
|
3
|
+
import { theme } from "../theme/theme.js";
|
|
4
|
+
import { DynamicBorder } from "./dynamic-border.js";
|
|
5
|
+
function flatten(snapshot) {
|
|
6
|
+
return [
|
|
7
|
+
...snapshot.steering.map((text) => ({ queue: "steer", text })),
|
|
8
|
+
...snapshot.followUp.map((text) => ({ queue: "followUp", text })),
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Flat queued-message list with selection, grouped steering-first. All key
|
|
13
|
+
* handling goes through getKeybindings().matches — no hardcoded key values.
|
|
14
|
+
*/
|
|
15
|
+
class QueueManagerList {
|
|
16
|
+
entries = [];
|
|
17
|
+
steeringCount = 0;
|
|
18
|
+
selectedIndex = 0;
|
|
19
|
+
callbacks;
|
|
20
|
+
constructor(snapshot, callbacks) {
|
|
21
|
+
this.callbacks = callbacks;
|
|
22
|
+
this.applySnapshot(snapshot);
|
|
23
|
+
}
|
|
24
|
+
invalidate() {
|
|
25
|
+
// No cached state to invalidate currently
|
|
26
|
+
}
|
|
27
|
+
render(width) {
|
|
28
|
+
const lines = [];
|
|
29
|
+
if (this.entries.length === 0)
|
|
30
|
+
return lines;
|
|
31
|
+
if (this.steeringCount > 0) {
|
|
32
|
+
lines.push(theme.fg("muted", ` ${t("Steering")}`));
|
|
33
|
+
}
|
|
34
|
+
for (let i = 0; i < this.entries.length; i++) {
|
|
35
|
+
const entry = this.entries[i];
|
|
36
|
+
const opensFollowUpGroup = entry.queue === "followUp" && (i === 0 || this.entries[i - 1]?.queue === "steer");
|
|
37
|
+
if (opensFollowUpGroup) {
|
|
38
|
+
if (i > 0)
|
|
39
|
+
lines.push("");
|
|
40
|
+
lines.push(theme.fg("muted", ` ${t("Follow-up")}`));
|
|
41
|
+
}
|
|
42
|
+
const isSelected = i === this.selectedIndex;
|
|
43
|
+
const cursor = isSelected ? theme.fg("accent", "› ") : " ";
|
|
44
|
+
const normalized = entry.text.replace(/\n/g, " ").trim();
|
|
45
|
+
const truncated = truncateToWidth(normalized, width - 2);
|
|
46
|
+
lines.push(cursor + (isSelected ? theme.bold(truncated) : truncated));
|
|
47
|
+
}
|
|
48
|
+
return lines;
|
|
49
|
+
}
|
|
50
|
+
handleInput(keyData) {
|
|
51
|
+
const kb = getKeybindings();
|
|
52
|
+
// Up/down move the selection across the flat list, wrapping at the ends
|
|
53
|
+
// (same semantics as UserMessageList).
|
|
54
|
+
if (kb.matches(keyData, "tui.select.up")) {
|
|
55
|
+
if (this.entries.length === 0)
|
|
56
|
+
return;
|
|
57
|
+
this.selectedIndex = this.selectedIndex === 0 ? this.entries.length - 1 : this.selectedIndex - 1;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (kb.matches(keyData, "tui.select.down")) {
|
|
61
|
+
if (this.entries.length === 0)
|
|
62
|
+
return;
|
|
63
|
+
this.selectedIndex = this.selectedIndex === this.entries.length - 1 ? 0 : this.selectedIndex + 1;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const moveUp = kb.matches(keyData, "app.queue.moveUp");
|
|
67
|
+
const moveDown = kb.matches(keyData, "app.queue.moveDown");
|
|
68
|
+
if (moveUp || moveDown) {
|
|
69
|
+
if (this.entries.length === 0)
|
|
70
|
+
return;
|
|
71
|
+
const { queue, index } = this.selectedLocation();
|
|
72
|
+
if (index === undefined)
|
|
73
|
+
return;
|
|
74
|
+
const target = index + (moveUp ? -1 : 1);
|
|
75
|
+
// Reorder stays inside the selected entry's group (bounds guard
|
|
76
|
+
// mirrors the scoped-models selector); the facade stays the final
|
|
77
|
+
// authority — a stale snapshot returns false and nothing moves.
|
|
78
|
+
if (target < 0 || target >= this.groupLength(queue))
|
|
79
|
+
return;
|
|
80
|
+
if (this.callbacks.onReorder(queue, index, target)) {
|
|
81
|
+
this.applySnapshot(this.callbacks.refresh());
|
|
82
|
+
this.selectedIndex = Math.min(Math.max(this.selectedIndex + (moveUp ? -1 : 1), 0), this.entries.length - 1);
|
|
83
|
+
}
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (kb.matches(keyData, "app.queue.remove")) {
|
|
87
|
+
if (this.entries.length === 0)
|
|
88
|
+
return;
|
|
89
|
+
const { queue, index } = this.selectedLocation();
|
|
90
|
+
if (index === undefined)
|
|
91
|
+
return;
|
|
92
|
+
if (this.callbacks.onRemove(queue, index) !== null) {
|
|
93
|
+
this.applySnapshot(this.callbacks.refresh());
|
|
94
|
+
this.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);
|
|
95
|
+
if (this.entries.length === 0)
|
|
96
|
+
this.callbacks.onClose();
|
|
97
|
+
}
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (kb.matches(keyData, "tui.select.confirm")) {
|
|
101
|
+
if (this.entries.length === 0)
|
|
102
|
+
return;
|
|
103
|
+
const { queue, index } = this.selectedLocation();
|
|
104
|
+
if (index === undefined)
|
|
105
|
+
return;
|
|
106
|
+
if (this.callbacks.onRestore(queue, index))
|
|
107
|
+
this.callbacks.onClose();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (kb.matches(keyData, "tui.select.cancel")) {
|
|
111
|
+
this.callbacks.onClose();
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Rebuild rows from a fresh snapshot; steering entries stay in front. */
|
|
116
|
+
applySnapshot(snapshot) {
|
|
117
|
+
this.entries = flatten(snapshot);
|
|
118
|
+
this.steeringCount = snapshot.steering.length;
|
|
119
|
+
this.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);
|
|
120
|
+
if (this.selectedIndex < 0)
|
|
121
|
+
this.selectedIndex = 0;
|
|
122
|
+
}
|
|
123
|
+
/** Group and within-group index of the selected entry. */
|
|
124
|
+
selectedLocation() {
|
|
125
|
+
const entry = this.entries[this.selectedIndex];
|
|
126
|
+
if (!entry)
|
|
127
|
+
return { queue: "steer", index: undefined };
|
|
128
|
+
return {
|
|
129
|
+
queue: entry.queue,
|
|
130
|
+
index: entry.queue === "steer" ? this.selectedIndex : this.selectedIndex - this.steeringCount,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
groupLength(queue) {
|
|
134
|
+
return this.entries.filter((entry) => entry.queue === queue).length;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Component that renders the queued-message manager (/queue-list): grouped
|
|
139
|
+
* steering/follow-up entries with reorder, remove, and restore actions.
|
|
140
|
+
*/
|
|
141
|
+
export class QueueManagerSelectorComponent extends Container {
|
|
142
|
+
list;
|
|
143
|
+
constructor(snapshot, callbacks) {
|
|
144
|
+
super();
|
|
145
|
+
this.addChild(new Spacer(1));
|
|
146
|
+
this.addChild(new Text(theme.bold(t("Queued Messages")), 1, 0));
|
|
147
|
+
this.addChild(new Spacer(1));
|
|
148
|
+
this.addChild(new DynamicBorder());
|
|
149
|
+
this.addChild(new Spacer(1));
|
|
150
|
+
this.list = new QueueManagerList(snapshot, callbacks);
|
|
151
|
+
this.addChild(this.list);
|
|
152
|
+
this.addChild(new Spacer(1));
|
|
153
|
+
this.addChild(new Text(theme.fg("muted", t("alt+up/alt+down move · delete remove · enter restore · esc close")), 1, 0));
|
|
154
|
+
this.addChild(new Spacer(1));
|
|
155
|
+
this.addChild(new DynamicBorder());
|
|
156
|
+
// Auto-close when mounted with both queues empty (the host gates the
|
|
157
|
+
// open on non-empty queues; this covers the queue draining in between).
|
|
158
|
+
if (snapshot.steering.length === 0 && snapshot.followUp.length === 0) {
|
|
159
|
+
setTimeout(() => callbacks.onClose(), 100);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
getMessageList() {
|
|
163
|
+
return this.list;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=queue-manager-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-manager-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/queue-manager-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, Container, getKeybindings, Spacer, Text, truncateToWidth } from \"@agent-forge/tui\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\n/** Which queue an entry belongs to; mirrors the session's queue names. */\nexport type QueueName = \"steer\" | \"followUp\";\n\n/** One row in the manager: the owning queue plus the queued text. */\nexport interface QueuedMessageEntry {\n\tqueue: QueueName;\n\ttext: string;\n}\n\n/** Queue snapshot shape the component consumes (same shape as the facade read view). */\nexport interface QueuedMessageSnapshot {\n\tsteering: string[];\n\tfollowUp: string[];\n}\n\n/**\n * Host surface the queue manager consumes. The component never touches the\n * facade: every mutation goes through these callbacks, so tests inject plain\n * functions and the host owns facade forwarding and the editor restore.\n */\nexport interface QueueManagerCallbacks {\n\t/** Re-read both queues after an operation; the component rebuilds its rows. */\n\trefresh(): QueuedMessageSnapshot;\n\t/** Move the entry at group index `from` to `to` within `queue`; false when invalid. */\n\tonReorder(queue: QueueName, from: number, to: number): boolean;\n\t/** Remove the entry at group `index`; the removed text, or null when invalid. */\n\tonRemove(queue: QueueName, index: number): string | null;\n\t/** Remove the entry and put its text back into the editor; false when invalid. */\n\tonRestore(queue: QueueName, index: number): boolean;\n\t/** Close the manager (escape, restore, or both queues empty after a remove). */\n\tonClose(): void;\n}\n\nfunction flatten(snapshot: QueuedMessageSnapshot): QueuedMessageEntry[] {\n\treturn [\n\t\t...snapshot.steering.map((text): QueuedMessageEntry => ({ queue: \"steer\", text })),\n\t\t...snapshot.followUp.map((text): QueuedMessageEntry => ({ queue: \"followUp\", text })),\n\t];\n}\n\n/**\n * Flat queued-message list with selection, grouped steering-first. All key\n * handling goes through getKeybindings().matches — no hardcoded key values.\n */\nclass QueueManagerList implements Component {\n\tprivate entries: QueuedMessageEntry[] = [];\n\tprivate steeringCount = 0;\n\tprivate selectedIndex = 0;\n\tprivate readonly callbacks: QueueManagerCallbacks;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tthis.callbacks = callbacks;\n\t\tthis.applySnapshot(snapshot);\n\t}\n\n\tinvalidate(): void {\n\t\t// No cached state to invalidate currently\n\t}\n\n\trender(width: number): string[] {\n\t\tconst lines: string[] = [];\n\t\tif (this.entries.length === 0) return lines;\n\n\t\tif (this.steeringCount > 0) {\n\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Steering\")}`));\n\t\t}\n\t\tfor (let i = 0; i < this.entries.length; i++) {\n\t\t\tconst entry = this.entries[i];\n\t\t\tconst opensFollowUpGroup = entry.queue === \"followUp\" && (i === 0 || this.entries[i - 1]?.queue === \"steer\");\n\t\t\tif (opensFollowUpGroup) {\n\t\t\t\tif (i > 0) lines.push(\"\");\n\t\t\t\tlines.push(theme.fg(\"muted\", ` ${t(\"Follow-up\")}`));\n\t\t\t}\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst cursor = isSelected ? theme.fg(\"accent\", \"› \") : \" \";\n\t\t\tconst normalized = entry.text.replace(/\\n/g, \" \").trim();\n\t\t\tconst truncated = truncateToWidth(normalized, width - 2);\n\t\t\tlines.push(cursor + (isSelected ? theme.bold(truncated) : truncated));\n\t\t}\n\t\treturn lines;\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up/down move the selection across the flat list, wrapping at the ends\n\t\t// (same semantics as UserMessageList).\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.entries.length - 1 : this.selectedIndex - 1;\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.entries.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\treturn;\n\t\t}\n\n\t\tconst moveUp = kb.matches(keyData, \"app.queue.moveUp\");\n\t\tconst moveDown = kb.matches(keyData, \"app.queue.moveDown\");\n\t\tif (moveUp || moveDown) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tconst target = index + (moveUp ? -1 : 1);\n\t\t\t// Reorder stays inside the selected entry's group (bounds guard\n\t\t\t// mirrors the scoped-models selector); the facade stays the final\n\t\t\t// authority — a stale snapshot returns false and nothing moves.\n\t\t\tif (target < 0 || target >= this.groupLength(queue)) return;\n\t\t\tif (this.callbacks.onReorder(queue, index, target)) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(Math.max(this.selectedIndex + (moveUp ? -1 : 1), 0), this.entries.length - 1);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"app.queue.remove\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRemove(queue, index) !== null) {\n\t\t\t\tthis.applySnapshot(this.callbacks.refresh());\n\t\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\t\t\tif (this.entries.length === 0) this.callbacks.onClose();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tif (this.entries.length === 0) return;\n\t\t\tconst { queue, index } = this.selectedLocation();\n\t\t\tif (index === undefined) return;\n\t\t\tif (this.callbacks.onRestore(queue, index)) this.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\n\t\tif (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onClose();\n\t\t\treturn;\n\t\t}\n\t}\n\n\t/** Rebuild rows from a fresh snapshot; steering entries stay in front. */\n\tprivate applySnapshot(snapshot: QueuedMessageSnapshot): void {\n\t\tthis.entries = flatten(snapshot);\n\t\tthis.steeringCount = snapshot.steering.length;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.entries.length - 1);\n\t\tif (this.selectedIndex < 0) this.selectedIndex = 0;\n\t}\n\n\t/** Group and within-group index of the selected entry. */\n\tprivate selectedLocation(): { queue: QueueName; index: number | undefined } {\n\t\tconst entry = this.entries[this.selectedIndex];\n\t\tif (!entry) return { queue: \"steer\", index: undefined };\n\t\treturn {\n\t\t\tqueue: entry.queue,\n\t\t\tindex: entry.queue === \"steer\" ? this.selectedIndex : this.selectedIndex - this.steeringCount,\n\t\t};\n\t}\n\n\tprivate groupLength(queue: QueueName): number {\n\t\treturn this.entries.filter((entry) => entry.queue === queue).length;\n\t}\n}\n\n/**\n * Component that renders the queued-message manager (/queue-list): grouped\n * steering/follow-up entries with reorder, remove, and restore actions.\n */\nexport class QueueManagerSelectorComponent extends Container {\n\tprivate readonly list: QueueManagerList;\n\n\tconstructor(snapshot: QueuedMessageSnapshot, callbacks: QueueManagerCallbacks) {\n\t\tsuper();\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.bold(t(\"Queued Messages\")), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.list = new QueueManagerList(snapshot, callbacks);\n\t\tthis.addChild(this.list);\n\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(\n\t\t\tnew Text(theme.fg(\"muted\", t(\"alt+up/alt+down move · delete remove · enter restore · esc close\")), 1, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Auto-close when mounted with both queues empty (the host gates the\n\t\t// open on non-empty queues; this covers the queue draining in between).\n\t\tif (snapshot.steering.length === 0 && snapshot.followUp.length === 0) {\n\t\t\tsetTimeout(() => callbacks.onClose(), 100);\n\t\t}\n\t}\n\n\tgetMessageList(): QueueManagerList {\n\t\treturn this.list;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scoped-models-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/scoped-models-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAA+B,KAAK,EAAgB,MAAM,kBAAkB,CAAC;AA8D/G,MAAM,WAAW,YAAY;IAC5B,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC/B,wFAAwF;IACxF,QAAQ,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,sEAAsE;IACtE,SAAS,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,QAAQ,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,SAAU,YAAW,SAAS;IAChF,OAAO,CAAC,UAAU,CAAsC;IACxD,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,aAAa,CAAmB;IACxC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IACD,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,UAAU,CAAO;IACzB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAC,CAAO;IAEjC,YAAY,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EA0C3D;IAED,YAAY,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAgBnF;IAED,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAE7E;IAED,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,aAAa;IAqBrB,OAAO,CAAC,OAAO;IAef,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAoDlB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAoH9B;IAED,cAAc,IAAI,KAAK,CAEtB;CACD","sourcesContent":["import type { Api, Model } from \"@agent-forge/ai\";\nimport { Container, type Focusable, fuzzyFilter, getKeybindings, Input, Spacer, Text } from \"@agent-forge/tui\";\nimport { getModelSearchText } from \"../model-search.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyDisplayText } from \"./keybinding-hints.ts\";\n\n// EnabledIds: null = all enabled (no filter), string[] = explicit ordered list\ntype EnabledIds = string[] | null;\n\nfunction isEnabled(enabledIds: EnabledIds, id: string): boolean {\n\treturn enabledIds === null || enabledIds.includes(id);\n}\n\nfunction toggle(enabledIds: EnabledIds, id: string): EnabledIds {\n\tif (enabledIds === null) return [id]; // First toggle: start with only this one\n\tconst index = enabledIds.indexOf(id);\n\tif (index >= 0) return [...enabledIds.slice(0, index), ...enabledIds.slice(index + 1)];\n\treturn [...enabledIds, id];\n}\n\nfunction enableAll(enabledIds: EnabledIds, allIds: string[], targetIds?: string[]): EnabledIds {\n\tif (enabledIds === null) return null; // Already all enabled\n\tconst targets = targetIds ?? allIds;\n\tconst result = [...enabledIds];\n\tfor (const id of targets) {\n\t\tif (!result.includes(id)) result.push(id);\n\t}\n\treturn result.length === allIds.length && result.every((id) => allIds.includes(id)) ? null : result;\n}\n\nfunction clearAll(enabledIds: EnabledIds, allIds: string[], targetIds?: string[]): EnabledIds {\n\tif (enabledIds === null) {\n\t\treturn targetIds ? allIds.filter((id) => !targetIds.includes(id)) : [];\n\t}\n\tconst targets = new Set(targetIds ?? enabledIds);\n\treturn enabledIds.filter((id) => !targets.has(id));\n}\n\nfunction move(enabledIds: EnabledIds, id: string, delta: number): EnabledIds {\n\tif (enabledIds === null) return null;\n\tconst list = [...enabledIds];\n\tconst index = list.indexOf(id);\n\tif (index < 0) return list;\n\tconst newIndex = index + delta;\n\tif (newIndex < 0 || newIndex >= list.length) return list;\n\tconst result = [...list];\n\t[result[index], result[newIndex]] = [result[newIndex], result[index]];\n\treturn result;\n}\n\nfunction getSortedIds(enabledIds: EnabledIds, allIds: string[]): string[] {\n\tif (enabledIds === null) return allIds;\n\tconst enabledSet = new Set(enabledIds);\n\treturn [...enabledIds, ...allIds.filter((id) => !enabledSet.has(id))];\n}\n\ninterface ModelItem {\n\tfullId: string;\n\tmodel: Model<Api> | undefined;\n\tenabled: boolean;\n}\n\nexport interface ModelsConfig {\n\tallModels: Model<Api>[];\n\tenabledModelIds: string[] | null;\n\trefreshStatus?: string;\n}\n\nexport interface ModelsCallbacks {\n\t/** Called whenever the enabled model set or order changes (session-only, no persist) */\n\tonChange: (enabledModelIds: string[] | null) => void | Promise<void>;\n\t/** Called when user wants to persist current selection to settings */\n\tonPersist: (enabledModelIds: string[] | null) => void | Promise<void>;\n\tonCancel: () => void;\n}\n\n/**\n * Component for enabling/disabling models in the /model cycling scope.\n * Changes are session-only until explicitly persisted with Ctrl+S.\n */\nexport class ScopedModelsSelectorComponent extends Container implements Focusable {\n\tprivate modelsById: Map<string, Model<Api>> = new Map();\n\tprivate allIds: string[] = [];\n\tprivate enabledIds: EnabledIds = null;\n\tprivate filteredItems: ModelItem[] = [];\n\tprivate selectedIndex = 0;\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate footerText: Text;\n\tprivate callbacks: ModelsCallbacks;\n\tprivate maxVisible = 8;\n\tprivate isDirty = false;\n\tprivate refreshStatusText?: Text;\n\n\tconstructor(config: ModelsConfig, callbacks: ModelsCallbacks) {\n\t\tsuper();\n\t\tthis.callbacks = callbacks;\n\n\t\tfor (const model of config.allModels) {\n\t\t\tconst fullId = `${model.provider}/${model.id}`;\n\t\t\tthis.modelsById.set(fullId, model);\n\t\t\tthis.allIds.push(fullId);\n\t\t}\n\n\t\tthis.enabledIds = config.enabledModelIds === null ? null : [...config.enabledModelIds];\n\t\tthis.filteredItems = this.buildItems();\n\n\t\t// Header\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"accent\", theme.bold(\"Model Configuration\")), 0, 0));\n\t\tthis.addChild(\n\t\t\tnew Text(theme.fg(\"muted\", `Session-only. ${keyDisplayText(\"app.models.save\")} to save to settings.`), 0, 0),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Search input\n\t\tthis.searchInput = new Input();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// List container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\t// Footer hint\n\t\tthis.addChild(new Spacer(1));\n\t\tif (config.refreshStatus) {\n\t\t\tthis.refreshStatusText = new Text(theme.fg(\"muted\", ` ${config.refreshStatus}`), 0, 0);\n\t\t\tthis.addChild(this.refreshStatusText);\n\t\t}\n\t\tthis.footerText = new Text(this.getFooterText(), 0, 0);\n\t\tthis.addChild(this.footerText);\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.updateList();\n\t}\n\n\tupdateModels(models: readonly Model<Api>[], enabledModelIds?: string[] | null): void {\n\t\tconst selectedId = this.filteredItems[this.selectedIndex]?.fullId;\n\t\tif (enabledModelIds !== undefined) this.enabledIds = enabledModelIds === null ? null : [...enabledModelIds];\n\t\tthis.modelsById.clear();\n\t\tthis.allIds = [];\n\t\tfor (const model of models) {\n\t\t\tconst fullId = `${model.provider}/${model.id}`;\n\t\t\tthis.modelsById.set(fullId, model);\n\t\t\tthis.allIds.push(fullId);\n\t\t}\n\t\tthis.refresh();\n\t\tconst refreshedIndex = selectedId ? this.filteredItems.findIndex((item) => item.fullId === selectedId) : -1;\n\t\tif (refreshedIndex >= 0) {\n\t\t\tthis.selectedIndex = refreshedIndex;\n\t\t\tthis.updateList();\n\t\t}\n\t}\n\n\tsetRefreshStatus(message: string, kind: \"muted\" | \"success\" | \"warning\"): void {\n\t\tthis.refreshStatusText?.setText(theme.fg(kind, ` ${message}`));\n\t}\n\n\tprivate buildItems(): ModelItem[] {\n\t\treturn getSortedIds(this.enabledIds, this.allIds).map((id) => ({\n\t\t\tfullId: id,\n\t\t\tmodel: this.modelsById.get(id),\n\t\t\tenabled: isEnabled(this.enabledIds, id),\n\t\t}));\n\t}\n\n\tprivate getFooterText(): string {\n\t\tconst enabledCount = this.enabledIds?.filter((id) => this.modelsById.has(id)).length ?? this.allIds.length;\n\t\tconst unavailableCount = this.enabledIds?.filter((id) => !this.modelsById.has(id)).length ?? 0;\n\t\tconst allEnabled = this.enabledIds === null;\n\t\tconst countText = allEnabled\n\t\t\t? \"all enabled\"\n\t\t\t: `${enabledCount}/${this.allIds.length} enabled${unavailableCount ? ` · ${unavailableCount} unavailable` : \"\"}`;\n\t\tconst parts = [\n\t\t\t`${keyDisplayText(\"tui.select.confirm\")} toggle`,\n\t\t\t`${keyDisplayText(\"app.models.enableAll\")} all`,\n\t\t\t`${keyDisplayText(\"app.models.clearAll\")} clear`,\n\t\t\t`${keyDisplayText(\"app.models.toggleProvider\")} provider`,\n\t\t\t`${keyDisplayText(\"app.models.reorderUp\")}/${keyDisplayText(\"app.models.reorderDown\")} reorder`,\n\t\t\t`${keyDisplayText(\"app.models.save\")} save`,\n\t\t\tcountText,\n\t\t];\n\t\treturn this.isDirty\n\t\t\t? theme.fg(\"dim\", ` ${parts.join(\" · \")} `) + theme.fg(\"warning\", \"(unsaved)\")\n\t\t\t: theme.fg(\"dim\", ` ${parts.join(\" · \")}`);\n\t}\n\n\tprivate refresh(): void {\n\t\tconst query = this.searchInput.getValue();\n\t\tconst items = this.buildItems();\n\t\tthis.filteredItems = query\n\t\t\t? fuzzyFilter(items, query, (item) =>\n\t\t\t\t\titem.model\n\t\t\t\t\t\t? getModelSearchText({ id: item.model.id, provider: item.model.provider, name: item.model.name })\n\t\t\t\t\t\t: item.fullId,\n\t\t\t\t)\n\t\t\t: items;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredItems.length - 1));\n\t\tthis.updateList();\n\t\tthis.footerText.setText(this.getFooterText());\n\t}\n\n\tprivate notifyChange(): void {\n\t\tthis.callbacks.onChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tif (this.filteredItems.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);\n\t\tconst allEnabled = this.enabledIds === null;\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredItems[i]!;\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst id = item.model?.id ?? item.fullId;\n\t\t\tconst modelText = isSelected ? theme.fg(\"accent\", id) : id;\n\t\t\tconst providerBadge = theme.fg(\"muted\", item.model ? ` [${item.model.provider}]` : \" [unavailable]\");\n\t\t\tconst status = item.model\n\t\t\t\t? allEnabled\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: item.enabled\n\t\t\t\t\t\t? theme.fg(\"success\", \" ✓\")\n\t\t\t\t\t\t: theme.fg(\"dim\", \" ✗\")\n\t\t\t\t: theme.fg(\"dim\", \" ✗\");\n\t\t\tthis.listContainer.addChild(new Text(`${prefix}${modelText}${providerBadge}${status}`, 0, 0));\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredItems.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredItems.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\tif (this.filteredItems.length > 0) {\n\t\t\tconst selected = this.filteredItems[this.selectedIndex];\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\ttheme.fg(\"muted\", ` ${selected.model ? `Model Name: ${selected.model.name}` : \"Model unavailable\"}`),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\n\t\t// Navigation\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tif (this.filteredItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filteredItems.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tif (this.filteredItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filteredItems.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\n\t\t// Reorder enabled models\n\t\tconst reorderUp = kb.matches(data, \"app.models.reorderUp\");\n\t\tconst reorderDown = kb.matches(data, \"app.models.reorderDown\");\n\t\tif (reorderUp || reorderDown) {\n\t\t\tif (this.enabledIds === null) return;\n\t\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\t\tif (item && isEnabled(this.enabledIds, item.fullId)) {\n\t\t\t\tconst delta = reorderUp ? -1 : 1;\n\t\t\t\tconst currentIndex = this.enabledIds.indexOf(item.fullId);\n\t\t\t\tconst newIndex = currentIndex + delta;\n\t\t\t\t// Only move if within bounds\n\t\t\t\tif (newIndex >= 0 && newIndex < this.enabledIds.length) {\n\t\t\t\t\tthis.enabledIds = move(this.enabledIds, item.fullId, delta);\n\t\t\t\t\tthis.isDirty = true;\n\t\t\t\t\tthis.selectedIndex += delta;\n\t\t\t\t\tthis.refresh();\n\t\t\t\t\tthis.notifyChange();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Toggle on Enter\n\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\t\tif (item) {\n\t\t\t\tthis.enabledIds = toggle(this.enabledIds, item.fullId);\n\t\t\t\tthis.isDirty = true;\n\t\t\t\tthis.refresh();\n\t\t\t\tthis.notifyChange();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Enable all (filtered if search active, otherwise all)\n\t\tif (kb.matches(data, \"app.models.enableAll\")) {\n\t\t\tconst targetIds = this.searchInput.getValue() ? this.filteredItems.map((i) => i.fullId) : undefined;\n\t\t\tthis.enabledIds = enableAll(this.enabledIds, this.allIds, targetIds);\n\t\t\tthis.isDirty = true;\n\t\t\tthis.refresh();\n\t\t\tthis.notifyChange();\n\t\t\treturn;\n\t\t}\n\n\t\t// Clear all (filtered if search active, otherwise all)\n\t\tif (kb.matches(data, \"app.models.clearAll\")) {\n\t\t\tconst targetIds = this.searchInput.getValue() ? this.filteredItems.map((i) => i.fullId) : undefined;\n\t\t\tthis.enabledIds = clearAll(this.enabledIds, this.allIds, targetIds);\n\t\t\tthis.isDirty = true;\n\t\t\tthis.refresh();\n\t\t\tthis.notifyChange();\n\t\t\treturn;\n\t\t}\n\n\t\t// Toggle provider of current item\n\t\tif (kb.matches(data, \"app.models.toggleProvider\")) {\n\t\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\t\tif (item?.model) {\n\t\t\t\tconst provider = item.model.provider;\n\t\t\t\tconst providerIds = this.allIds.filter((id) => this.modelsById.get(id)!.provider === provider);\n\t\t\t\tconst allEnabled = providerIds.every((id) => isEnabled(this.enabledIds, id));\n\t\t\t\tthis.enabledIds = allEnabled\n\t\t\t\t\t? clearAll(this.enabledIds, this.allIds, providerIds)\n\t\t\t\t\t: enableAll(this.enabledIds, this.allIds, providerIds);\n\t\t\t\tthis.isDirty = true;\n\t\t\t\tthis.refresh();\n\t\t\t\tthis.notifyChange();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Save/persist to settings\n\t\tif (kb.matches(data, \"app.models.save\")) {\n\t\t\tthis.callbacks.onPersist(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\tthis.isDirty = false;\n\t\t\tthis.footerText.setText(this.getFooterText());\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+C - clear search or cancel if empty\n\t\tif (kb.matches(data, \"app.models.cancel\")) {\n\t\t\tif (this.searchInput.getValue()) {\n\t\t\t\tthis.searchInput.setValue(\"\");\n\t\t\t\tthis.refresh();\n\t\t\t} else {\n\t\t\t\tthis.callbacks.onCancel();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Escape - cancel (via the shared select-cancel binding; ctrl+c is consumed by app.models.cancel above)\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onCancel();\n\t\t\treturn;\n\t\t}\n\n\t\t// Pass everything else to search input\n\t\tthis.searchInput.handleInput(data);\n\t\tthis.refresh();\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scoped-models-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/scoped-models-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAA+B,KAAK,EAAgB,MAAM,kBAAkB,CAAC;AA+D/G,MAAM,WAAW,YAAY;IAC5B,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC/B,wFAAwF;IACxF,QAAQ,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,sEAAsE;IACtE,SAAS,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,QAAQ,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,SAAU,YAAW,SAAS;IAChF,OAAO,CAAC,UAAU,CAAsC;IACxD,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,aAAa,CAAmB;IACxC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,WAAW,CAAQ;IAG3B,OAAO,CAAC,QAAQ,CAAS;IACzB,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IACD,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,UAAU,CAAO;IACzB,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAC,CAAO;IAEjC,YAAY,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAiD3D;IAED,YAAY,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAgBnF;IAED,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAE7E;IAED,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,OAAO;IAef,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAuDlB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAoH9B;IAED,cAAc,IAAI,KAAK,CAEtB;CACD","sourcesContent":["import type { Api, Model } from \"@agent-forge/ai\";\nimport { Container, type Focusable, fuzzyFilter, getKeybindings, Input, Spacer, Text } from \"@agent-forge/tui\";\nimport { t } from \"../../../core/i18n/index.ts\";\nimport { getModelSearchText } from \"../model-search.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\nimport { keyDisplayText } from \"./keybinding-hints.ts\";\n\n// EnabledIds: null = all enabled (no filter), string[] = explicit ordered list\ntype EnabledIds = string[] | null;\n\nfunction isEnabled(enabledIds: EnabledIds, id: string): boolean {\n\treturn enabledIds === null || enabledIds.includes(id);\n}\n\nfunction toggle(enabledIds: EnabledIds, id: string): EnabledIds {\n\tif (enabledIds === null) return [id]; // First toggle: start with only this one\n\tconst index = enabledIds.indexOf(id);\n\tif (index >= 0) return [...enabledIds.slice(0, index), ...enabledIds.slice(index + 1)];\n\treturn [...enabledIds, id];\n}\n\nfunction enableAll(enabledIds: EnabledIds, allIds: string[], targetIds?: string[]): EnabledIds {\n\tif (enabledIds === null) return null; // Already all enabled\n\tconst targets = targetIds ?? allIds;\n\tconst result = [...enabledIds];\n\tfor (const id of targets) {\n\t\tif (!result.includes(id)) result.push(id);\n\t}\n\treturn result.length === allIds.length && result.every((id) => allIds.includes(id)) ? null : result;\n}\n\nfunction clearAll(enabledIds: EnabledIds, allIds: string[], targetIds?: string[]): EnabledIds {\n\tif (enabledIds === null) {\n\t\treturn targetIds ? allIds.filter((id) => !targetIds.includes(id)) : [];\n\t}\n\tconst targets = new Set(targetIds ?? enabledIds);\n\treturn enabledIds.filter((id) => !targets.has(id));\n}\n\nfunction move(enabledIds: EnabledIds, id: string, delta: number): EnabledIds {\n\tif (enabledIds === null) return null;\n\tconst list = [...enabledIds];\n\tconst index = list.indexOf(id);\n\tif (index < 0) return list;\n\tconst newIndex = index + delta;\n\tif (newIndex < 0 || newIndex >= list.length) return list;\n\tconst result = [...list];\n\t[result[index], result[newIndex]] = [result[newIndex], result[index]];\n\treturn result;\n}\n\nfunction getSortedIds(enabledIds: EnabledIds, allIds: string[]): string[] {\n\tif (enabledIds === null) return allIds;\n\tconst enabledSet = new Set(enabledIds);\n\treturn [...enabledIds, ...allIds.filter((id) => !enabledSet.has(id))];\n}\n\ninterface ModelItem {\n\tfullId: string;\n\tmodel: Model<Api> | undefined;\n\tenabled: boolean;\n}\n\nexport interface ModelsConfig {\n\tallModels: Model<Api>[];\n\tenabledModelIds: string[] | null;\n\trefreshStatus?: string;\n}\n\nexport interface ModelsCallbacks {\n\t/** Called whenever the enabled model set or order changes (session-only, no persist) */\n\tonChange: (enabledModelIds: string[] | null) => void | Promise<void>;\n\t/** Called when user wants to persist current selection to settings */\n\tonPersist: (enabledModelIds: string[] | null) => void | Promise<void>;\n\tonCancel: () => void;\n}\n\n/**\n * Component for enabling/disabling models in the /model cycling scope.\n * Changes are session-only until explicitly persisted with Ctrl+S.\n */\nexport class ScopedModelsSelectorComponent extends Container implements Focusable {\n\tprivate modelsById: Map<string, Model<Api>> = new Map();\n\tprivate allIds: string[] = [];\n\tprivate enabledIds: EnabledIds = null;\n\tprivate filteredItems: ModelItem[] = [];\n\tprivate selectedIndex = 0;\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to searchInput for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\tprivate listContainer: Container;\n\tprivate footerText: Text;\n\tprivate callbacks: ModelsCallbacks;\n\tprivate maxVisible = 8;\n\tprivate isDirty = false;\n\tprivate refreshStatusText?: Text;\n\n\tconstructor(config: ModelsConfig, callbacks: ModelsCallbacks) {\n\t\tsuper();\n\t\tthis.callbacks = callbacks;\n\n\t\tfor (const model of config.allModels) {\n\t\t\tconst fullId = `${model.provider}/${model.id}`;\n\t\t\tthis.modelsById.set(fullId, model);\n\t\t\tthis.allIds.push(fullId);\n\t\t}\n\n\t\tthis.enabledIds = config.enabledModelIds === null ? null : [...config.enabledModelIds];\n\t\tthis.filteredItems = this.buildItems();\n\n\t\t// Header\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(theme.fg(\"accent\", theme.bold(t(\"Model Configuration\"))), 0, 0));\n\t\tthis.addChild(\n\t\t\tnew Text(\n\t\t\t\ttheme.fg(\n\t\t\t\t\t\"muted\",\n\t\t\t\t\tt(\"Session-only. {key} to save to settings.\", { key: keyDisplayText(\"app.models.save\") }),\n\t\t\t\t),\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t),\n\t\t);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Search input\n\t\tthis.searchInput = new Input();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// List container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\t// Footer hint\n\t\tthis.addChild(new Spacer(1));\n\t\tif (config.refreshStatus) {\n\t\t\tthis.refreshStatusText = new Text(theme.fg(\"muted\", ` ${config.refreshStatus}`), 0, 0);\n\t\t\tthis.addChild(this.refreshStatusText);\n\t\t}\n\t\tthis.footerText = new Text(this.getFooterText(), 0, 0);\n\t\tthis.addChild(this.footerText);\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.updateList();\n\t}\n\n\tupdateModels(models: readonly Model<Api>[], enabledModelIds?: string[] | null): void {\n\t\tconst selectedId = this.filteredItems[this.selectedIndex]?.fullId;\n\t\tif (enabledModelIds !== undefined) this.enabledIds = enabledModelIds === null ? null : [...enabledModelIds];\n\t\tthis.modelsById.clear();\n\t\tthis.allIds = [];\n\t\tfor (const model of models) {\n\t\t\tconst fullId = `${model.provider}/${model.id}`;\n\t\t\tthis.modelsById.set(fullId, model);\n\t\t\tthis.allIds.push(fullId);\n\t\t}\n\t\tthis.refresh();\n\t\tconst refreshedIndex = selectedId ? this.filteredItems.findIndex((item) => item.fullId === selectedId) : -1;\n\t\tif (refreshedIndex >= 0) {\n\t\t\tthis.selectedIndex = refreshedIndex;\n\t\t\tthis.updateList();\n\t\t}\n\t}\n\n\tsetRefreshStatus(message: string, kind: \"muted\" | \"success\" | \"warning\"): void {\n\t\tthis.refreshStatusText?.setText(theme.fg(kind, ` ${message}`));\n\t}\n\n\tprivate buildItems(): ModelItem[] {\n\t\treturn getSortedIds(this.enabledIds, this.allIds).map((id) => ({\n\t\t\tfullId: id,\n\t\t\tmodel: this.modelsById.get(id),\n\t\t\tenabled: isEnabled(this.enabledIds, id),\n\t\t}));\n\t}\n\n\tprivate getFooterText(): string {\n\t\tconst enabledCount = this.enabledIds?.filter((id) => this.modelsById.has(id)).length ?? this.allIds.length;\n\t\tconst unavailableCount = this.enabledIds?.filter((id) => !this.modelsById.has(id)).length ?? 0;\n\t\tconst allEnabled = this.enabledIds === null;\n\t\tconst countText = allEnabled\n\t\t\t? t(\"all enabled\")\n\t\t\t: t(\"{enabled}/{total} enabled\", { enabled: enabledCount, total: this.allIds.length }) +\n\t\t\t\t(unavailableCount ? ` · ${t(\"{count} unavailable\", { count: unavailableCount })}` : \"\");\n\t\tconst parts = [\n\t\t\t`${keyDisplayText(\"tui.select.confirm\")} ${t(\"toggle\")}`,\n\t\t\t`${keyDisplayText(\"app.models.enableAll\")} ${t(\"all\")}`,\n\t\t\t`${keyDisplayText(\"app.models.clearAll\")} ${t(\"clear\")}`,\n\t\t\t`${keyDisplayText(\"app.models.toggleProvider\")} ${t(\"provider\")}`,\n\t\t\t`${keyDisplayText(\"app.models.reorderUp\")}/${keyDisplayText(\"app.models.reorderDown\")} ${t(\"reorder\")}`,\n\t\t\t`${keyDisplayText(\"app.models.save\")} ${t(\"save\")}`,\n\t\t\tcountText,\n\t\t];\n\t\treturn this.isDirty\n\t\t\t? theme.fg(\"dim\", ` ${parts.join(\" · \")} `) + theme.fg(\"warning\", t(\"(unsaved)\"))\n\t\t\t: theme.fg(\"dim\", ` ${parts.join(\" · \")}`);\n\t}\n\n\tprivate refresh(): void {\n\t\tconst query = this.searchInput.getValue();\n\t\tconst items = this.buildItems();\n\t\tthis.filteredItems = query\n\t\t\t? fuzzyFilter(items, query, (item) =>\n\t\t\t\t\titem.model\n\t\t\t\t\t\t? getModelSearchText({ id: item.model.id, provider: item.model.provider, name: item.model.name })\n\t\t\t\t\t\t: item.fullId,\n\t\t\t\t)\n\t\t\t: items;\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredItems.length - 1));\n\t\tthis.updateList();\n\t\tthis.footerText.setText(this.getFooterText());\n\t}\n\n\tprivate notifyChange(): void {\n\t\tthis.callbacks.onChange(this.enabledIds === null ? null : [...this.enabledIds]);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tif (this.filteredItems.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", ` ${t(\"No matching models\")}`), 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + this.maxVisible, this.filteredItems.length);\n\t\tconst allEnabled = this.enabledIds === null;\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst item = this.filteredItems[i]!;\n\t\t\tconst isSelected = i === this.selectedIndex;\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst id = item.model?.id ?? item.fullId;\n\t\t\tconst modelText = isSelected ? theme.fg(\"accent\", id) : id;\n\t\t\tconst providerBadge = theme.fg(\"muted\", item.model ? ` [${item.model.provider}]` : ` ${t(\"[unavailable]\")}`);\n\t\t\tconst status = item.model\n\t\t\t\t? allEnabled\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: item.enabled\n\t\t\t\t\t\t? theme.fg(\"success\", \" ✓\")\n\t\t\t\t\t\t: theme.fg(\"dim\", \" ✗\")\n\t\t\t\t: theme.fg(\"dim\", \" ✗\");\n\t\t\tthis.listContainer.addChild(new Text(`${prefix}${modelText}${providerBadge}${status}`, 0, 0));\n\t\t}\n\n\t\t// Add scroll indicator if needed\n\t\tif (startIndex > 0 || endIndex < this.filteredItems.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredItems.length})`), 0, 0),\n\t\t\t);\n\t\t}\n\n\t\tif (this.filteredItems.length > 0) {\n\t\t\tconst selected = this.filteredItems[this.selectedIndex];\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\ttheme.fg(\n\t\t\t\t\t\t\"muted\",\n\t\t\t\t\t\t` ${selected.model ? t(\"Model Name: {name}\", { name: selected.model.name }) : t(\"Model unavailable\")}`,\n\t\t\t\t\t),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\thandleInput(data: string): void {\n\t\tconst kb = getKeybindings();\n\n\t\t// Navigation\n\t\tif (kb.matches(data, \"tui.select.up\")) {\n\t\t\tif (this.filteredItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.filteredItems.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\t\tif (kb.matches(data, \"tui.select.down\")) {\n\t\t\tif (this.filteredItems.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.filteredItems.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t\treturn;\n\t\t}\n\n\t\t// Reorder enabled models\n\t\tconst reorderUp = kb.matches(data, \"app.models.reorderUp\");\n\t\tconst reorderDown = kb.matches(data, \"app.models.reorderDown\");\n\t\tif (reorderUp || reorderDown) {\n\t\t\tif (this.enabledIds === null) return;\n\t\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\t\tif (item && isEnabled(this.enabledIds, item.fullId)) {\n\t\t\t\tconst delta = reorderUp ? -1 : 1;\n\t\t\t\tconst currentIndex = this.enabledIds.indexOf(item.fullId);\n\t\t\t\tconst newIndex = currentIndex + delta;\n\t\t\t\t// Only move if within bounds\n\t\t\t\tif (newIndex >= 0 && newIndex < this.enabledIds.length) {\n\t\t\t\t\tthis.enabledIds = move(this.enabledIds, item.fullId, delta);\n\t\t\t\t\tthis.isDirty = true;\n\t\t\t\t\tthis.selectedIndex += delta;\n\t\t\t\t\tthis.refresh();\n\t\t\t\t\tthis.notifyChange();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Toggle on Enter\n\t\tif (kb.matches(data, \"tui.select.confirm\")) {\n\t\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\t\tif (item) {\n\t\t\t\tthis.enabledIds = toggle(this.enabledIds, item.fullId);\n\t\t\t\tthis.isDirty = true;\n\t\t\t\tthis.refresh();\n\t\t\t\tthis.notifyChange();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Enable all (filtered if search active, otherwise all)\n\t\tif (kb.matches(data, \"app.models.enableAll\")) {\n\t\t\tconst targetIds = this.searchInput.getValue() ? this.filteredItems.map((i) => i.fullId) : undefined;\n\t\t\tthis.enabledIds = enableAll(this.enabledIds, this.allIds, targetIds);\n\t\t\tthis.isDirty = true;\n\t\t\tthis.refresh();\n\t\t\tthis.notifyChange();\n\t\t\treturn;\n\t\t}\n\n\t\t// Clear all (filtered if search active, otherwise all)\n\t\tif (kb.matches(data, \"app.models.clearAll\")) {\n\t\t\tconst targetIds = this.searchInput.getValue() ? this.filteredItems.map((i) => i.fullId) : undefined;\n\t\t\tthis.enabledIds = clearAll(this.enabledIds, this.allIds, targetIds);\n\t\t\tthis.isDirty = true;\n\t\t\tthis.refresh();\n\t\t\tthis.notifyChange();\n\t\t\treturn;\n\t\t}\n\n\t\t// Toggle provider of current item\n\t\tif (kb.matches(data, \"app.models.toggleProvider\")) {\n\t\t\tconst item = this.filteredItems[this.selectedIndex];\n\t\t\tif (item?.model) {\n\t\t\t\tconst provider = item.model.provider;\n\t\t\t\tconst providerIds = this.allIds.filter((id) => this.modelsById.get(id)!.provider === provider);\n\t\t\t\tconst allEnabled = providerIds.every((id) => isEnabled(this.enabledIds, id));\n\t\t\t\tthis.enabledIds = allEnabled\n\t\t\t\t\t? clearAll(this.enabledIds, this.allIds, providerIds)\n\t\t\t\t\t: enableAll(this.enabledIds, this.allIds, providerIds);\n\t\t\t\tthis.isDirty = true;\n\t\t\t\tthis.refresh();\n\t\t\t\tthis.notifyChange();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Save/persist to settings\n\t\tif (kb.matches(data, \"app.models.save\")) {\n\t\t\tthis.callbacks.onPersist(this.enabledIds === null ? null : [...this.enabledIds]);\n\t\t\tthis.isDirty = false;\n\t\t\tthis.footerText.setText(this.getFooterText());\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+C - clear search or cancel if empty\n\t\tif (kb.matches(data, \"app.models.cancel\")) {\n\t\t\tif (this.searchInput.getValue()) {\n\t\t\t\tthis.searchInput.setValue(\"\");\n\t\t\t\tthis.refresh();\n\t\t\t} else {\n\t\t\t\tthis.callbacks.onCancel();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Escape - cancel (via the shared select-cancel binding; ctrl+c is consumed by app.models.cancel above)\n\t\tif (kb.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.callbacks.onCancel();\n\t\t\treturn;\n\t\t}\n\n\t\t// Pass everything else to search input\n\t\tthis.searchInput.handleInput(data);\n\t\tthis.refresh();\n\t}\n\n\tgetSearchInput(): Input {\n\t\treturn this.searchInput;\n\t}\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Container, fuzzyFilter, getKeybindings, Input, Spacer, Text } from "@agent-forge/tui";
|
|
2
|
+
import { t } from "../../../core/i18n/index.js";
|
|
2
3
|
import { getModelSearchText } from "../model-search.js";
|
|
3
4
|
import { theme } from "../theme/theme.js";
|
|
4
5
|
import { DynamicBorder } from "./dynamic-border.js";
|
|
@@ -91,8 +92,8 @@ export class ScopedModelsSelectorComponent extends Container {
|
|
|
91
92
|
// Header
|
|
92
93
|
this.addChild(new DynamicBorder());
|
|
93
94
|
this.addChild(new Spacer(1));
|
|
94
|
-
this.addChild(new Text(theme.fg("accent", theme.bold("Model Configuration")), 0, 0));
|
|
95
|
-
this.addChild(new Text(theme.fg("muted",
|
|
95
|
+
this.addChild(new Text(theme.fg("accent", theme.bold(t("Model Configuration"))), 0, 0));
|
|
96
|
+
this.addChild(new Text(theme.fg("muted", t("Session-only. {key} to save to settings.", { key: keyDisplayText("app.models.save") })), 0, 0));
|
|
96
97
|
this.addChild(new Spacer(1));
|
|
97
98
|
// Search input
|
|
98
99
|
this.searchInput = new Input();
|
|
@@ -145,19 +146,20 @@ export class ScopedModelsSelectorComponent extends Container {
|
|
|
145
146
|
const unavailableCount = this.enabledIds?.filter((id) => !this.modelsById.has(id)).length ?? 0;
|
|
146
147
|
const allEnabled = this.enabledIds === null;
|
|
147
148
|
const countText = allEnabled
|
|
148
|
-
? "all enabled"
|
|
149
|
-
:
|
|
149
|
+
? t("all enabled")
|
|
150
|
+
: t("{enabled}/{total} enabled", { enabled: enabledCount, total: this.allIds.length }) +
|
|
151
|
+
(unavailableCount ? ` · ${t("{count} unavailable", { count: unavailableCount })}` : "");
|
|
150
152
|
const parts = [
|
|
151
|
-
`${keyDisplayText("tui.select.confirm")} toggle`,
|
|
152
|
-
`${keyDisplayText("app.models.enableAll")} all`,
|
|
153
|
-
`${keyDisplayText("app.models.clearAll")} clear`,
|
|
154
|
-
`${keyDisplayText("app.models.toggleProvider")} provider`,
|
|
155
|
-
`${keyDisplayText("app.models.reorderUp")}/${keyDisplayText("app.models.reorderDown")} reorder`,
|
|
156
|
-
`${keyDisplayText("app.models.save")} save`,
|
|
153
|
+
`${keyDisplayText("tui.select.confirm")} ${t("toggle")}`,
|
|
154
|
+
`${keyDisplayText("app.models.enableAll")} ${t("all")}`,
|
|
155
|
+
`${keyDisplayText("app.models.clearAll")} ${t("clear")}`,
|
|
156
|
+
`${keyDisplayText("app.models.toggleProvider")} ${t("provider")}`,
|
|
157
|
+
`${keyDisplayText("app.models.reorderUp")}/${keyDisplayText("app.models.reorderDown")} ${t("reorder")}`,
|
|
158
|
+
`${keyDisplayText("app.models.save")} ${t("save")}`,
|
|
157
159
|
countText,
|
|
158
160
|
];
|
|
159
161
|
return this.isDirty
|
|
160
|
-
? theme.fg("dim", ` ${parts.join(" · ")} `) + theme.fg("warning", "(unsaved)")
|
|
162
|
+
? theme.fg("dim", ` ${parts.join(" · ")} `) + theme.fg("warning", t("(unsaved)"))
|
|
161
163
|
: theme.fg("dim", ` ${parts.join(" · ")}`);
|
|
162
164
|
}
|
|
163
165
|
refresh() {
|
|
@@ -178,7 +180,7 @@ export class ScopedModelsSelectorComponent extends Container {
|
|
|
178
180
|
updateList() {
|
|
179
181
|
this.listContainer.clear();
|
|
180
182
|
if (this.filteredItems.length === 0) {
|
|
181
|
-
this.listContainer.addChild(new Text(theme.fg("muted", "
|
|
183
|
+
this.listContainer.addChild(new Text(theme.fg("muted", ` ${t("No matching models")}`), 0, 0));
|
|
182
184
|
return;
|
|
183
185
|
}
|
|
184
186
|
const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.filteredItems.length - this.maxVisible));
|
|
@@ -190,7 +192,7 @@ export class ScopedModelsSelectorComponent extends Container {
|
|
|
190
192
|
const prefix = isSelected ? theme.fg("accent", "→ ") : " ";
|
|
191
193
|
const id = item.model?.id ?? item.fullId;
|
|
192
194
|
const modelText = isSelected ? theme.fg("accent", id) : id;
|
|
193
|
-
const providerBadge = theme.fg("muted", item.model ? ` [${item.model.provider}]` : "
|
|
195
|
+
const providerBadge = theme.fg("muted", item.model ? ` [${item.model.provider}]` : ` ${t("[unavailable]")}`);
|
|
194
196
|
const status = item.model
|
|
195
197
|
? allEnabled
|
|
196
198
|
? ""
|
|
@@ -207,7 +209,7 @@ export class ScopedModelsSelectorComponent extends Container {
|
|
|
207
209
|
if (this.filteredItems.length > 0) {
|
|
208
210
|
const selected = this.filteredItems[this.selectedIndex];
|
|
209
211
|
this.listContainer.addChild(new Spacer(1));
|
|
210
|
-
this.listContainer.addChild(new Text(theme.fg("muted", ` ${selected.model ?
|
|
212
|
+
this.listContainer.addChild(new Text(theme.fg("muted", ` ${selected.model ? t("Model Name: {name}", { name: selected.model.name }) : t("Model unavailable")}`), 0, 0));
|
|
211
213
|
}
|
|
212
214
|
}
|
|
213
215
|
handleInput(data) {
|