@armadra/agent 0.5.1 → 0.6.1
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 +203 -304
- package/CHANGELOG.zh-CN.md +462 -0
- package/README.md +408 -364
- package/README.zh-CN.md +705 -0
- package/dist/agent/session-plan.js +2 -2
- package/dist/agent/session-state.d.ts +3 -0
- package/dist/agent/session-state.js +20 -0
- package/dist/agent/session-subagent.d.ts +15 -1
- package/dist/agent/session-subagent.js +26 -3
- package/dist/agent/session-telemetry.d.ts +16 -2
- package/dist/agent/session-telemetry.js +29 -7
- package/dist/agent/session-tools.js +5 -2
- package/dist/agent/session-trace-writer.d.ts +27 -0
- package/dist/agent/session-trace-writer.js +253 -0
- package/dist/agent/session.d.ts +2 -0
- package/dist/agent/session.js +12 -0
- package/dist/agent/subagent-direct.d.ts +20 -0
- package/dist/agent/subagent-direct.js +76 -0
- package/dist/agent/subagent-registry.d.ts +8 -1
- package/dist/agent/subagent-registry.js +28 -1
- package/dist/agent/system-prompt.d.ts +3 -1
- package/dist/agent/system-prompt.js +3 -0
- package/dist/agent/tool-runner.d.ts +2 -1
- package/dist/agent/tool-runner.js +5 -4
- package/dist/agent/types-w6.d.ts +39 -0
- package/dist/agent/types-w6.js +4 -0
- package/dist/agent/types.d.ts +5 -2
- package/dist/agents/external.js +1 -1
- package/dist/agents/task-record.d.ts +74 -1
- package/dist/agents/task-record.js +100 -0
- package/dist/ai/apis/cache-params.js +2 -1
- package/dist/ai/apis/chatgpt-backend.d.ts +52 -0
- package/dist/ai/apis/chatgpt-backend.js +224 -0
- package/dist/ai/apis/chatgpt-rate-limits.d.ts +26 -0
- package/dist/ai/apis/chatgpt-rate-limits.js +91 -0
- package/dist/ai/apis/openai-responses-request.d.ts +2 -1
- package/dist/ai/apis/openai-responses-request.js +8 -2
- package/dist/ai/apis/openai-responses.d.ts +2 -0
- package/dist/ai/apis/openai-responses.js +51 -16
- package/dist/ai/overflow.d.ts +1 -1
- package/dist/ai/overflow.js +10 -7
- package/dist/ai/providers/auth.d.ts +15 -2
- package/dist/ai/providers/auth.js +69 -2
- package/dist/ai/providers/builtin.js +27 -0
- package/dist/ai/providers/catalog-data.js +1 -0
- package/dist/ai/providers/discovered-cache.d.ts +48 -0
- package/dist/ai/providers/discovered-cache.js +102 -0
- package/dist/ai/providers/enrich.js +2 -7
- package/dist/ai/providers/model-visibility.d.ts +33 -0
- package/dist/ai/providers/model-visibility.js +70 -0
- package/dist/ai/providers/models-dev-cache.js +15 -19
- package/dist/ai/providers/models-dev-snapshot.js +8 -7
- package/dist/ai/providers/models-dev.js +5 -15
- package/dist/ai/providers/registry.d.ts +2 -0
- package/dist/ai/providers/registry.js +6 -1
- package/dist/ai/providers/suggest.js +2 -16
- package/dist/ai/types.d.ts +27 -1
- package/dist/auth/chatgpt/backend-client.d.ts +26 -0
- package/dist/auth/chatgpt/backend-client.js +74 -0
- package/dist/auth/chatgpt/claims.d.ts +17 -0
- package/dist/auth/chatgpt/claims.js +46 -0
- package/dist/auth/chatgpt/cli.d.ts +35 -0
- package/dist/auth/chatgpt/cli.js +279 -0
- package/dist/auth/chatgpt/doctor.d.ts +17 -0
- package/dist/auth/chatgpt/doctor.js +36 -0
- package/dist/auth/chatgpt/host-id.d.ts +7 -0
- package/dist/auth/chatgpt/host-id.js +26 -0
- package/dist/auth/chatgpt/login.d.ts +30 -0
- package/dist/auth/chatgpt/login.js +130 -0
- package/dist/auth/chatgpt/presets.d.ts +66 -0
- package/dist/auth/chatgpt/presets.js +120 -0
- package/dist/auth/chatgpt/quota-text.d.ts +13 -0
- package/dist/auth/chatgpt/quota-text.js +36 -0
- package/dist/auth/oauth/browser.d.ts +12 -0
- package/dist/auth/oauth/browser.js +27 -0
- package/dist/auth/oauth/callback-server.d.ts +47 -0
- package/dist/auth/oauth/callback-server.js +147 -0
- package/dist/auth/oauth/flows.d.ts +62 -0
- package/dist/auth/oauth/flows.js +113 -0
- package/dist/auth/oauth/jwt.d.ts +24 -0
- package/dist/auth/oauth/jwt.js +81 -0
- package/dist/auth/oauth/live.d.ts +21 -0
- package/dist/auth/oauth/live.js +25 -0
- package/dist/auth/oauth/oidc.d.ts +26 -0
- package/dist/auth/oauth/oidc.js +72 -0
- package/dist/auth/oauth/pkce.d.ts +15 -0
- package/dist/auth/oauth/pkce.js +20 -0
- package/dist/auth/oauth/refresh.d.ts +35 -0
- package/dist/auth/oauth/refresh.js +129 -0
- package/dist/auth/oauth/token-client.d.ts +33 -0
- package/dist/auth/oauth/token-client.js +121 -0
- package/dist/auth/oauth/token-store.d.ts +23 -0
- package/dist/auth/oauth/token-store.js +125 -0
- package/dist/auth/testing/fake-oauth.d.ts +73 -0
- package/dist/auth/testing/fake-oauth.js +271 -0
- package/dist/auth/testing/refresh-child.d.ts +5 -0
- package/dist/auth/testing/refresh-child.js +16 -0
- package/dist/bundle/ama.cjs +26532 -11045
- package/dist/checkpoints/backend.js +6 -5
- package/dist/checkpoints/restore.js +3 -2
- package/dist/checkpoints/settings.js +2 -1
- package/dist/checkpoints/shadow-git.js +7 -6
- package/dist/checkpoints/shadow-restore.js +3 -2
- package/dist/checkpoints/tracker.js +4 -3
- package/dist/cli/args.d.ts +9 -2
- package/dist/cli/args.js +74 -27
- package/dist/cli/bootstrap.js +53 -31
- package/dist/cli/choice-prompt.js +8 -6
- package/dist/cli/codemode-notice.js +2 -2
- package/dist/cli/compose-agents.js +2 -1
- package/dist/cli/compose-extensions.js +2 -0
- package/dist/cli/compose-memory.d.ts +53 -0
- package/dist/cli/compose-memory.js +127 -0
- package/dist/cli/compose-providers.d.ts +6 -0
- package/dist/cli/compose-providers.js +38 -2
- package/dist/cli/compose-session.d.ts +5 -0
- package/dist/cli/compose-session.js +27 -13
- package/dist/cli/compose-store.d.ts +2 -0
- package/dist/cli/compose-store.js +9 -5
- package/dist/cli/compose.d.ts +2 -0
- package/dist/cli/compose.js +13 -5
- package/dist/cli/default-model.d.ts +0 -2
- package/dist/cli/default-model.js +5 -8
- package/dist/cli/deps.d.ts +5 -1
- package/dist/cli/exit-codes.d.ts +1 -1
- package/dist/cli/exit-codes.js +7 -16
- package/dist/cli/from-prompt.js +3 -2
- package/dist/cli/help-text.d.ts +2 -1
- package/dist/cli/help-text.js +5 -99
- package/dist/cli/main.d.ts +5 -0
- package/dist/cli/main.js +21 -2
- package/dist/cli/proxy.js +14 -9
- package/dist/cli/runtime.d.ts +5 -0
- package/dist/cli/startup-screen.js +20 -27
- package/dist/cli/startup-steps.js +6 -8
- package/dist/cli/subcommands/auth.d.ts +6 -3
- package/dist/cli/subcommands/auth.js +52 -22
- package/dist/cli/subcommands/config-set.d.ts +21 -0
- package/dist/cli/subcommands/config-set.js +145 -0
- package/dist/cli/subcommands/config.d.ts +2 -1
- package/dist/cli/subcommands/config.js +51 -37
- package/dist/cli/subcommands/doctor.d.ts +2 -1
- package/dist/cli/subcommands/doctor.js +97 -58
- package/dist/cli/subcommands/init.d.ts +1 -1
- package/dist/cli/subcommands/init.js +8 -7
- package/dist/cli/subcommands/memory.d.ts +18 -0
- package/dist/cli/subcommands/memory.js +189 -0
- package/dist/cli/subcommands/model-meta.js +11 -9
- package/dist/cli/subcommands/models-cache-probe.js +23 -20
- package/dist/cli/subcommands/models-discover.d.ts +4 -0
- package/dist/cli/subcommands/models-discover.js +60 -21
- package/dist/cli/subcommands/models-enable.d.ts +13 -0
- package/dist/cli/subcommands/models-enable.js +145 -0
- package/dist/cli/subcommands/models.d.ts +3 -1
- package/dist/cli/subcommands/models.js +39 -24
- package/dist/cli/subcommands/probe-runner.js +8 -7
- package/dist/cli/subcommands/providers-list.js +32 -21
- package/dist/cli/subcommands/providers-plan.js +24 -25
- package/dist/cli/subcommands/providers-probe.js +5 -6
- package/dist/cli/subcommands/providers.d.ts +1 -1
- package/dist/cli/subcommands/providers.js +45 -50
- package/dist/cli/subcommands/sessions-export.d.ts +1 -1
- package/dist/cli/subcommands/sessions-export.js +10 -9
- package/dist/cli/subcommands/sessions-search.d.ts +1 -1
- package/dist/cli/subcommands/sessions-search.js +11 -10
- package/dist/cli/subcommands/sessions-trace.d.ts +30 -0
- package/dist/cli/subcommands/sessions-trace.js +156 -0
- package/dist/cli/subcommands/sessions.d.ts +4 -3
- package/dist/cli/subcommands/sessions.js +40 -37
- package/dist/cli/subcommands/stats.d.ts +1 -1
- package/dist/cli/subcommands/stats.js +49 -30
- package/dist/cli/system-prompt-arg.js +3 -2
- package/dist/codemode/capability.js +3 -2
- package/dist/compaction/post-compact.d.ts +1 -0
- package/dist/compaction/post-compact.js +15 -1
- package/dist/compaction/prune-tier.d.ts +1 -1
- package/dist/compaction/prune-tier.js +3 -3
- package/dist/compaction/serialize.js +2 -1
- package/dist/config/auth-file.d.ts +12 -2
- package/dist/config/auth-file.js +32 -10
- package/dist/config/checker.js +12 -11
- package/dist/config/context-files.js +3 -2
- package/dist/config/edit.d.ts +106 -0
- package/dist/config/edit.js +350 -0
- package/dist/config/init.d.ts +4 -3
- package/dist/config/init.js +10 -18
- package/dist/config/json-schema.d.ts +2 -1
- package/dist/config/json-schema.js +102 -69
- package/dist/config/key-docs.d.ts +18 -7
- package/dist/config/key-docs.js +43 -128
- package/dist/config/load.js +7 -6
- package/dist/config/merge.d.ts +4 -1
- package/dist/config/merge.js +42 -22
- package/dist/config/paths.js +6 -5
- package/dist/config/profile.d.ts +5 -1
- package/dist/config/profile.js +7 -2
- package/dist/config/schema-w5.js +12 -4
- package/dist/config/schema-w6.d.ts +19 -0
- package/dist/config/schema-w6.js +115 -0
- package/dist/config/schema.js +34 -20
- package/dist/config/settings-registry.d.ts +81 -0
- package/dist/config/settings-registry.js +185 -0
- package/dist/config/types-w5.d.ts +7 -0
- package/dist/config/types-w5.js +2 -0
- package/dist/config/types-w6.d.ts +109 -0
- package/dist/config/types-w6.js +19 -0
- package/dist/config/types.d.ts +11 -8
- package/dist/config/types.js +1 -0
- package/dist/drivers/acp/client.js +1 -1
- package/dist/drivers/acp/driver.js +13 -8
- package/dist/drivers/agents.js +4 -3
- package/dist/drivers/base.js +3 -2
- package/dist/drivers/host-runners.js +2 -1
- package/dist/drivers/native/claude-stream.js +12 -11
- package/dist/drivers/native/codex-app-server.js +17 -12
- package/dist/drivers/native/oneshot.js +8 -7
- package/dist/drivers/pool.js +1 -1
- package/dist/drivers/runner.d.ts +3 -1
- package/dist/drivers/runner.js +68 -20
- package/dist/drivers/turn.js +1 -1
- package/dist/hooks/config.js +3 -2
- package/dist/hooks/protocol.js +18 -12
- package/dist/host/api-impl.js +11 -10
- package/dist/host/loader.js +9 -8
- package/dist/host/types.d.ts +3 -0
- package/dist/i18n/catalog.d.ts +2209 -0
- package/dist/i18n/catalog.js +72 -0
- package/dist/i18n/format.d.ts +21 -0
- package/dist/i18n/format.js +58 -0
- package/dist/i18n/index.d.ts +58 -0
- package/dist/i18n/index.js +72 -0
- package/dist/i18n/messages/agents.d.ts +84 -0
- package/dist/i18n/messages/agents.js +85 -0
- package/dist/i18n/messages/approval.d.ts +99 -0
- package/dist/i18n/messages/approval.js +100 -0
- package/dist/i18n/messages/auth.d.ts +189 -0
- package/dist/i18n/messages/auth.js +201 -0
- package/dist/i18n/messages/cli-args.d.ts +46 -0
- package/dist/i18n/messages/cli-args.js +46 -0
- package/dist/i18n/messages/cli-help.d.ts +12 -0
- package/dist/i18n/messages/cli-help.js +248 -0
- package/dist/i18n/messages/cli.d.ts +336 -0
- package/dist/i18n/messages/cli.js +311 -0
- package/dist/i18n/messages/config-keys.d.ts +293 -0
- package/dist/i18n/messages/config-keys.js +296 -0
- package/dist/i18n/messages/config.d.ts +508 -0
- package/dist/i18n/messages/config.js +241 -0
- package/dist/i18n/messages/drivers.d.ts +123 -0
- package/dist/i18n/messages/drivers.js +124 -0
- package/dist/i18n/messages/errors.d.ts +83 -0
- package/dist/i18n/messages/errors.js +171 -0
- package/dist/i18n/messages/interactive-line.d.ts +61 -0
- package/dist/i18n/messages/interactive-line.js +69 -0
- package/dist/i18n/messages/interactive-startup.d.ts +99 -0
- package/dist/i18n/messages/interactive-startup.js +100 -0
- package/dist/i18n/messages/interactive-view.d.ts +140 -0
- package/dist/i18n/messages/interactive-view.js +141 -0
- package/dist/i18n/messages/interactive.d.ts +489 -0
- package/dist/i18n/messages/interactive.js +248 -0
- package/dist/i18n/messages/memory.d.ts +123 -0
- package/dist/i18n/messages/memory.js +128 -0
- package/dist/i18n/messages/panels.d.ts +233 -0
- package/dist/i18n/messages/panels.js +232 -0
- package/dist/i18n/messages/permissions.d.ts +126 -0
- package/dist/i18n/messages/permissions.js +151 -0
- package/dist/i18n/messages/plan.d.ts +123 -0
- package/dist/i18n/messages/plan.js +124 -0
- package/dist/i18n/messages/print.d.ts +86 -0
- package/dist/i18n/messages/print.js +91 -0
- package/dist/i18n/messages/report.d.ts +391 -0
- package/dist/i18n/messages/report.js +490 -0
- package/dist/i18n/messages/rewind.d.ts +198 -0
- package/dist/i18n/messages/rewind.js +217 -0
- package/dist/i18n/messages/session.d.ts +230 -0
- package/dist/i18n/messages/session.js +258 -0
- package/dist/i18n/messages/settings.d.ts +355 -0
- package/dist/i18n/messages/settings.js +343 -0
- package/dist/i18n/messages/subcommands-config.d.ts +113 -0
- package/dist/i18n/messages/subcommands-config.js +129 -0
- package/dist/i18n/messages/subcommands-models.d.ts +34 -0
- package/dist/i18n/messages/subcommands-models.js +34 -0
- package/dist/i18n/messages/subcommands.d.ts +576 -0
- package/dist/i18n/messages/subcommands.js +477 -0
- package/dist/i18n/messages/trace.d.ts +243 -0
- package/dist/i18n/messages/trace.js +238 -0
- package/dist/i18n/types.d.ts +15 -0
- package/dist/i18n/types.js +7 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2 -0
- package/dist/memory/edit.d.ts +24 -0
- package/dist/memory/edit.js +63 -0
- package/dist/memory/frontmatter.d.ts +37 -0
- package/dist/memory/frontmatter.js +79 -0
- package/dist/memory/index.d.ts +28 -0
- package/dist/memory/index.js +126 -0
- package/dist/memory/lock.d.ts +17 -0
- package/dist/memory/lock.js +62 -0
- package/dist/memory/paths.d.ts +57 -0
- package/dist/memory/paths.js +175 -0
- package/dist/memory/report.d.ts +36 -0
- package/dist/memory/report.js +86 -0
- package/dist/memory/runtime.d.ts +42 -0
- package/dist/memory/runtime.js +36 -0
- package/dist/memory/secrets.d.ts +8 -0
- package/dist/memory/secrets.js +27 -0
- package/dist/memory/section.d.ts +28 -0
- package/dist/memory/section.js +59 -0
- package/dist/memory/store.d.ts +70 -0
- package/dist/memory/store.js +284 -0
- package/dist/memory/tool.d.ts +31 -0
- package/dist/memory/tool.js +94 -0
- package/dist/modes/acp/acp-events.js +2 -1
- package/dist/modes/acp/acp-server.js +13 -12
- package/dist/modes/commands-core.d.ts +11 -0
- package/dist/modes/commands-core.js +93 -62
- package/dist/modes/image-input.js +20 -6
- package/dist/modes/interactive/agent-bar.d.ts +95 -0
- package/dist/modes/interactive/agent-bar.js +248 -0
- package/dist/modes/interactive/agent-panels.js +27 -26
- package/dist/modes/interactive/agent-transcript.d.ts +47 -0
- package/dist/modes/interactive/agent-transcript.js +191 -0
- package/dist/modes/interactive/agent-ui.d.ts +36 -1
- package/dist/modes/interactive/agent-ui.js +180 -14
- package/dist/modes/interactive/agent-view.d.ts +72 -0
- package/dist/modes/interactive/agent-view.js +281 -0
- package/dist/modes/interactive/approval-dialog.js +46 -34
- package/dist/modes/interactive/clipboard-paste.d.ts +2 -2
- package/dist/modes/interactive/clipboard-paste.js +9 -4
- package/dist/modes/interactive/commands.d.ts +22 -1
- package/dist/modes/interactive/commands.js +100 -49
- package/dist/modes/interactive/completion.js +2 -1
- package/dist/modes/interactive/config-panel.d.ts +70 -0
- package/dist/modes/interactive/config-panel.js +319 -0
- package/dist/modes/interactive/config-ui.d.ts +96 -0
- package/dist/modes/interactive/config-ui.js +397 -0
- package/dist/modes/interactive/confirm-dialog.js +6 -7
- package/dist/modes/interactive/event-notices.js +11 -9
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.js +21 -22
- package/dist/modes/interactive/key-dispatch.d.ts +12 -0
- package/dist/modes/interactive/key-dispatch.js +24 -9
- package/dist/modes/interactive/line/line-editor.js +2 -1
- package/dist/modes/interactive/line/line-mode.js +18 -7
- package/dist/modes/interactive/line/line-render.js +25 -24
- package/dist/modes/interactive/memory-panel.d.ts +64 -0
- package/dist/modes/interactive/memory-panel.js +221 -0
- package/dist/modes/interactive/message-view.d.ts +4 -2
- package/dist/modes/interactive/message-view.js +42 -33
- package/dist/modes/interactive/model-items.d.ts +45 -0
- package/dist/modes/interactive/model-items.js +134 -0
- package/dist/modes/interactive/model-picker.d.ts +57 -0
- package/dist/modes/interactive/model-picker.js +191 -0
- package/dist/modes/interactive/panels.js +39 -31
- package/dist/modes/interactive/pickers.d.ts +2 -1
- package/dist/modes/interactive/pickers.js +10 -6
- package/dist/modes/interactive/plan-command.d.ts +1 -1
- package/dist/modes/interactive/plan-command.js +24 -27
- package/dist/modes/interactive/plan-dialog.js +18 -17
- package/dist/modes/interactive/plan-flow.js +6 -5
- package/dist/modes/interactive/rewind-command.d.ts +1 -1
- package/dist/modes/interactive/rewind-command.js +18 -16
- package/dist/modes/interactive/rewind-flow.d.ts +0 -1
- package/dist/modes/interactive/rewind-flow.js +13 -14
- package/dist/modes/interactive/rewind-list.js +7 -6
- package/dist/modes/interactive/rewind-panel.js +40 -40
- package/dist/modes/interactive/rewind-text.d.ts +5 -3
- package/dist/modes/interactive/rewind-text.js +48 -38
- package/dist/modes/interactive/run-indicator.js +15 -12
- package/dist/modes/interactive/session-events.js +3 -2
- package/dist/modes/interactive/startup-header.js +22 -23
- package/dist/modes/interactive/startup-ui.d.ts +3 -9
- package/dist/modes/interactive/startup-ui.js +44 -88
- package/dist/modes/interactive/status-area.d.ts +2 -0
- package/dist/modes/interactive/status-area.js +8 -2
- package/dist/modes/interactive/status-bar.js +4 -3
- package/dist/modes/interactive/subagent-view.js +9 -7
- package/dist/modes/interactive/tasks-report.d.ts +6 -0
- package/dist/modes/interactive/tasks-report.js +28 -31
- package/dist/modes/interactive/terminal-setup.d.ts +9 -0
- package/dist/modes/interactive/terminal-setup.js +23 -0
- package/dist/modes/interactive/tool-summary.js +19 -17
- package/dist/modes/interactive/tool-view.js +7 -4
- package/dist/modes/interactive/trace-view.d.ts +89 -0
- package/dist/modes/interactive/trace-view.js +332 -0
- package/dist/modes/print/print-mode.js +14 -15
- package/dist/modes/rpc/commands.js +7 -3
- package/dist/modes/rpc/rpc-mode.js +9 -3
- package/dist/modes/session-report.d.ts +2 -0
- package/dist/modes/session-report.js +101 -105
- package/dist/modes/startup-ui-text.js +11 -6
- package/dist/permissions/bypass.d.ts +8 -10
- package/dist/permissions/bypass.js +19 -10
- package/dist/permissions/memory-class.d.ts +23 -0
- package/dist/permissions/memory-class.js +54 -0
- package/dist/permissions/modes.d.ts +3 -3
- package/dist/permissions/modes.js +21 -16
- package/dist/permissions/pipeline.d.ts +1 -1
- package/dist/permissions/pipeline.js +9 -2
- package/dist/permissions/preview.js +49 -42
- package/dist/permissions/rules.js +5 -2
- package/dist/permissions/types.d.ts +4 -0
- package/dist/plan/store.js +2 -1
- package/dist/rpc.d.ts +39 -1
- package/dist/rpc.js +3 -0
- package/dist/sandbox/bash.js +11 -8
- package/dist/sandbox/detect.js +14 -11
- package/dist/sdk.d.ts +17 -1
- package/dist/sdk.js +29 -7
- package/dist/session/export.js +31 -30
- package/dist/session/manager.d.ts +1 -1
- package/dist/session/manager.js +5 -3
- package/dist/session/reuse.js +5 -4
- package/dist/session/scan.js +3 -2
- package/dist/session/stats-aggregate.d.ts +3 -1
- package/dist/session/stats-aggregate.js +5 -1
- package/dist/session/stats-index.js +2 -1
- package/dist/session/stats-scan.d.ts +4 -1
- package/dist/session/stats-scan.js +6 -2
- package/dist/session/store.d.ts +11 -0
- package/dist/session/store.js +48 -1
- package/dist/session/types.d.ts +2 -0
- package/dist/skills/builtin.js +2 -1
- package/dist/tools/image-file.d.ts +26 -1
- package/dist/tools/image-file.js +55 -13
- package/dist/tools/presets.d.ts +14 -1
- package/dist/tools/presets.js +3 -3
- package/dist/tools/registry.js +1 -1
- package/dist/tools/truncate.d.ts +1 -1
- package/dist/tools/truncate.js +2 -2
- package/dist/tools/types.d.ts +17 -1
- package/dist/trace/build-index.d.ts +91 -0
- package/dist/trace/build-index.js +127 -0
- package/dist/trace/build-nodes.d.ts +24 -0
- package/dist/trace/build-nodes.js +279 -0
- package/dist/trace/build-util.d.ts +43 -0
- package/dist/trace/build-util.js +120 -0
- package/dist/trace/build.d.ts +82 -0
- package/dist/trace/build.js +382 -0
- package/dist/trace/detail.d.ts +35 -0
- package/dist/trace/detail.js +205 -0
- package/dist/trace/flatten.d.ts +69 -0
- package/dist/trace/flatten.js +173 -0
- package/dist/trace/format.d.ts +47 -0
- package/dist/trace/format.js +329 -0
- package/dist/trace/html-template.d.ts +19 -0
- package/dist/trace/html-template.js +150 -0
- package/dist/trace/html.d.ts +104 -0
- package/dist/trace/html.js +292 -0
- package/dist/trace/preview.d.ts +29 -0
- package/dist/trace/preview.js +59 -0
- package/dist/trace/query-session.d.ts +14 -0
- package/dist/trace/query-session.js +38 -0
- package/dist/trace/query.d.ts +55 -0
- package/dist/trace/query.js +188 -0
- package/dist/trace/session.d.ts +40 -0
- package/dist/trace/session.js +168 -0
- package/dist/trace/types.d.ts +243 -0
- package/dist/trace/types.js +13 -0
- package/dist/tui/components/editor-paste.d.ts +2 -0
- package/dist/tui/components/editor-paste.js +6 -3
- package/dist/tui/components/editor.js +2 -2
- package/dist/tui/components/loader.d.ts +3 -0
- package/dist/tui/components/loader.js +14 -0
- package/dist/tui/components/select-list.d.ts +2 -0
- package/dist/tui/components/select-list.js +7 -0
- package/dist/tui/components/settings-list.d.ts +61 -0
- package/dist/tui/components/settings-list.js +135 -0
- package/dist/tui/keybindings.d.ts +5 -0
- package/dist/tui/keybindings.js +17 -5
- package/dist/tui.d.ts +1 -0
- package/dist/tui.js +2 -0
- package/docs/en/host-api.md +167 -0
- package/docs/en/permissions.md +214 -0
- package/docs/en/providers.md +627 -0
- package/docs/en/rpc.md +361 -0
- package/docs/en/sessions.md +219 -0
- package/docs/en/tui.md +534 -0
- package/docs/host-api.md +18 -17
- package/docs/memory.md +172 -0
- package/docs/permissions.md +2 -2
- package/docs/providers.md +73 -1
- package/docs/rpc.md +31 -3
- package/docs/session-format.md +8 -2
- package/docs/sessions.md +29 -1
- package/docs/tui.md +140 -4
- package/package.json +8 -3
|
@@ -14,27 +14,28 @@
|
|
|
14
14
|
*
|
|
15
15
|
* 滚动交给终端回滚:消息区只追加,切换会话时整体清空重画。
|
|
16
16
|
*/
|
|
17
|
+
import { msg } from "../../i18n/index.js";
|
|
17
18
|
import { Card, Container, Markdown, Spacer, Text, visibleWidth, wrapTextWithAnsi, } from "../../tui.js";
|
|
18
19
|
import { formatCost, formatTokens } from "./status-bar.js";
|
|
19
20
|
import { notificationSummary } from "./subagent-view.js";
|
|
20
21
|
import { PLAN_APPROVED_PROMPT } from "../../plan/prompts.js";
|
|
21
22
|
/** 退出摘要的时长:不足 1 分钟按秒,否则按分钟。 */
|
|
22
23
|
function sessionDuration(ms) {
|
|
23
|
-
|
|
24
|
-
return seconds < 60 ? `${seconds} 秒` : `${Math.round(seconds / 60)} 分钟`;
|
|
24
|
+
return msg().interactive.view.message.duration(Math.max(0, Math.round(ms / 1000)));
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* 退出摘要(§3.14):`─ 会话 <id> · 时长 · N 回合 · ↑in ↓out · cache x% · $y(重计费 $z)` 与
|
|
28
28
|
* ` 恢复:ama --resume <id>`。整体 dim,会话 id 与恢复命令正文色;0 回合只到「回合」;会话没落盘不给恢复行。
|
|
29
29
|
*/
|
|
30
30
|
export function exitSummaryLines(stats, elapsedMs, theme) {
|
|
31
|
+
const m = msg().interactive.view.message;
|
|
31
32
|
const g = theme.glyphs;
|
|
32
33
|
const dim = (s) => theme.fg("dim", s);
|
|
33
34
|
const id = stats.sessionId.slice(0, 8);
|
|
34
35
|
const parts = [
|
|
35
|
-
dim(
|
|
36
|
+
dim(m.sessionPrefix(g.rule)) + theme.fg("text", id),
|
|
36
37
|
dim(sessionDuration(elapsedMs)),
|
|
37
|
-
dim(
|
|
38
|
+
dim(m.turns(stats.userMessages)),
|
|
38
39
|
];
|
|
39
40
|
const t = stats.tokens;
|
|
40
41
|
const prompt = t.input + t.cacheRead + t.cacheWrite;
|
|
@@ -45,28 +46,23 @@ export function exitSummaryLines(stats, elapsedMs, theme) {
|
|
|
45
46
|
parts.push(dim(`cache ${Math.round(rate * 100)}%`));
|
|
46
47
|
if (stats.cost !== undefined && stats.cost > 0) {
|
|
47
48
|
const rebill = stats.cache?.reBilledUsd;
|
|
48
|
-
const extra = rebill !== undefined && rebill > 0 ?
|
|
49
|
+
const extra = rebill !== undefined && rebill > 0 ? m.rebill(formatCost(rebill)) : "";
|
|
49
50
|
parts.push(dim(formatCost(stats.cost) + extra));
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
const lines = [parts.join(dim(" · "))];
|
|
53
54
|
if (stats.userMessages > 0 && stats.sessionFile !== undefined) {
|
|
54
|
-
lines.push(dim(
|
|
55
|
+
lines.push(dim(m.resume) + theme.fg("text", `ama --resume ${id}`));
|
|
55
56
|
}
|
|
56
57
|
return lines;
|
|
57
58
|
}
|
|
58
59
|
/** 思考块展开时的正文行数上限(`full` 不限)。 */
|
|
59
60
|
export const THINKING_EXPANDED_LINES = 60;
|
|
60
|
-
/** origin →
|
|
61
|
-
export
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
task: "子 Agent 通知",
|
|
66
|
-
plan: "计划",
|
|
67
|
-
};
|
|
68
|
-
/** [W5-U] origin 为 plan 的交接消息(给模型的英文开场)在消息区的说法。 */
|
|
69
|
-
const PLAN_HANDOFF_TEXT = "按批准的计划开始执行";
|
|
61
|
+
/** origin → 界面语言的标签(未知 origin 原样显示)。 */
|
|
62
|
+
export function originLabel(origin) {
|
|
63
|
+
const labels = msg().interactive.view.message.origin;
|
|
64
|
+
return labels[origin] ?? origin;
|
|
65
|
+
}
|
|
70
66
|
/** 首行带前缀、续行按 `indent` 缩进的文本(用户消息、排队消息)。 */
|
|
71
67
|
export class PrefixedText {
|
|
72
68
|
prefix;
|
|
@@ -135,9 +131,10 @@ class ThinkingView {
|
|
|
135
131
|
const t = this.theme;
|
|
136
132
|
const g = t.glyphs;
|
|
137
133
|
const style = (s) => t.fg("dim", t.italic(s));
|
|
134
|
+
const m = msg().interactive.view.message;
|
|
138
135
|
const title = this.streaming
|
|
139
|
-
?
|
|
140
|
-
:
|
|
136
|
+
? m.thinkingStreaming(g.thinking, g.ellipsis)
|
|
137
|
+
: m.thinking(g.thinking, formatTokens(this.tokens));
|
|
141
138
|
const lines = [
|
|
142
139
|
style(title) + (this.open && !this.streaming ? " " + t.fg("dim", g.collapse) : ""),
|
|
143
140
|
];
|
|
@@ -150,7 +147,7 @@ class ThinkingView {
|
|
|
150
147
|
for (const line of all.slice(0, limit))
|
|
151
148
|
lines.push(" " + t.fg("muted", t.italic(line)));
|
|
152
149
|
if (all.length > limit) {
|
|
153
|
-
lines.push(" " + t.fg("dim",
|
|
150
|
+
lines.push(" " + t.fg("dim", m.moreLines(g.ellipsis, all.length - limit)));
|
|
154
151
|
}
|
|
155
152
|
}
|
|
156
153
|
this.cache = { width, lines };
|
|
@@ -173,7 +170,11 @@ export function contentText(content) {
|
|
|
173
170
|
if (typeof content === "string")
|
|
174
171
|
return content;
|
|
175
172
|
return content
|
|
176
|
-
.map((block) =>
|
|
173
|
+
.map((block) => block.type === "text"
|
|
174
|
+
? block.text
|
|
175
|
+
: block.type === "image"
|
|
176
|
+
? msg().interactive.view.message.image
|
|
177
|
+
: "")
|
|
177
178
|
.join("");
|
|
178
179
|
}
|
|
179
180
|
/** 一条助手消息:按内容块(思考 / 文本)同步子组件;工具调用块由 tool-view 单独显示。 */
|
|
@@ -247,14 +248,15 @@ export class AssistantView extends Container {
|
|
|
247
248
|
finish(message) {
|
|
248
249
|
this.streaming = false;
|
|
249
250
|
const { theme } = this.options;
|
|
251
|
+
const m = msg().interactive.view.message;
|
|
250
252
|
if (message.stopReason === "error") {
|
|
251
|
-
this.status.setText(theme.fg("error", `${theme.glyphs.fail} ${message.errorMessage ??
|
|
253
|
+
this.status.setText(theme.fg("error", `${theme.glyphs.fail} ${message.errorMessage ?? m.modelError}`));
|
|
252
254
|
}
|
|
253
255
|
else if (message.stopReason === "aborted") {
|
|
254
|
-
this.status.setText(theme.fg("dim",
|
|
256
|
+
this.status.setText(theme.fg("dim", m.interrupted));
|
|
255
257
|
}
|
|
256
258
|
else if (message.stopReason === "length") {
|
|
257
|
-
this.status.setText(theme.fg("warning",
|
|
259
|
+
this.status.setText(theme.fg("warning", m.lengthLimit));
|
|
258
260
|
}
|
|
259
261
|
this.update(message);
|
|
260
262
|
}
|
|
@@ -285,6 +287,10 @@ export class MessageView extends Container {
|
|
|
285
287
|
get theme() {
|
|
286
288
|
return this.options.theme;
|
|
287
289
|
}
|
|
290
|
+
/** [W6-S] `/config` 热应用:之后渲染的块按新选项(共享同一个 options 对象)。 */
|
|
291
|
+
setOptions(options) {
|
|
292
|
+
Object.assign(this.options, options);
|
|
293
|
+
}
|
|
288
294
|
/** 追加一块(与上一块之间空一行;`compact` 不空行)。 */
|
|
289
295
|
add(component) {
|
|
290
296
|
this.push(component, this.options.compact !== true);
|
|
@@ -350,12 +356,12 @@ export class MessageView extends Container {
|
|
|
350
356
|
this.add(new PrefixedText(t.fg("user", t.bold(t.glyphs.prompt)) + " ", text));
|
|
351
357
|
return;
|
|
352
358
|
}
|
|
353
|
-
const label =
|
|
359
|
+
const label = originLabel(origin);
|
|
354
360
|
// [W5-U] 后台子 Agent 的 <task-notification> 是给模型的全文,消息区只留一行
|
|
355
361
|
const summary = origin === "task"
|
|
356
362
|
? notificationSummary(text)
|
|
357
363
|
: origin === "plan" && text === PLAN_APPROVED_PROMPT
|
|
358
|
-
?
|
|
364
|
+
? msg().interactive.view.message.planHandoff
|
|
359
365
|
: undefined;
|
|
360
366
|
if (summary !== undefined) {
|
|
361
367
|
this.add(new PrefixedText(t.fg("dim", t.glyphs.queued) + " " + t.fg("muted", `${label} `), t.fg("muted", summary)));
|
|
@@ -398,23 +404,24 @@ export class MessageView extends Container {
|
|
|
398
404
|
}
|
|
399
405
|
addHookBlocked(reason) {
|
|
400
406
|
const glyph = this.theme.glyphs.blocked;
|
|
401
|
-
this.add(new Text(this.theme.fg("warning",
|
|
407
|
+
this.add(new Text(this.theme.fg("warning", msg().interactive.view.message.hookBlocked(glyph, reason))));
|
|
402
408
|
}
|
|
403
409
|
addRetry(attempt, maxAttempts, delayMs, error) {
|
|
404
410
|
const seconds = Math.max(1, Math.round(delayMs / 1000));
|
|
405
411
|
const glyph = this.theme.glyphs.retry;
|
|
406
|
-
this.add(new Text(this.theme.fg("warning",
|
|
412
|
+
this.add(new Text(this.theme.fg("warning", msg().interactive.view.message.retry(glyph, attempt, maxAttempts, seconds, error))));
|
|
407
413
|
}
|
|
408
414
|
/** 退出前追加的会话摘要(留在终端回滚里)。 */
|
|
409
415
|
addExitSummary(lines) {
|
|
410
416
|
this.add(new Text(lines.join("\n")));
|
|
411
417
|
}
|
|
412
418
|
addRetryFailed(error) {
|
|
413
|
-
this.addNotice("error",
|
|
419
|
+
this.addNotice("error", msg().interactive.view.message.retryFailed(error));
|
|
414
420
|
}
|
|
415
421
|
/** 压缩 / 分支摘要卡(左竖条):标题 + token 变化(有则显示)+ 摘要前 3 行。 */
|
|
416
422
|
addSummaryCard(summary, options = {}) {
|
|
417
423
|
const t = this.theme;
|
|
424
|
+
const m = msg().interactive.view.message;
|
|
418
425
|
const lines = summary
|
|
419
426
|
.trim()
|
|
420
427
|
.split("\n")
|
|
@@ -422,16 +429,16 @@ export class MessageView extends Container {
|
|
|
422
429
|
const head = lines.slice(0, 3);
|
|
423
430
|
const body = head.map((l) => t.fg("muted", l));
|
|
424
431
|
if (lines.length > head.length) {
|
|
425
|
-
body.push(t.fg("dim",
|
|
432
|
+
body.push(t.fg("dim", m.moreLines(t.glyphs.ellipsis, lines.length - head.length)));
|
|
426
433
|
}
|
|
427
434
|
let subtitle;
|
|
428
435
|
if (options.tokensBefore !== undefined) {
|
|
429
|
-
const after = options.tokensAfter !== undefined ?
|
|
430
|
-
subtitle =
|
|
436
|
+
const after = options.tokensAfter !== undefined ? formatTokens(options.tokensAfter) : undefined;
|
|
437
|
+
subtitle = m.summaryTokens(formatTokens(options.tokensBefore), after);
|
|
431
438
|
}
|
|
432
439
|
this.add(new Card(new Text(body.join("\n")), {
|
|
433
440
|
theme: t,
|
|
434
|
-
title: options.title ??
|
|
441
|
+
title: options.title ?? m.compacted,
|
|
435
442
|
...(subtitle !== undefined ? { subtitle } : {}),
|
|
436
443
|
}));
|
|
437
444
|
}
|
|
@@ -471,7 +478,9 @@ export class MessageView extends Container {
|
|
|
471
478
|
this.addSummaryCard(message.summary, { tokensBefore: message.tokensBefore });
|
|
472
479
|
break;
|
|
473
480
|
case "branchSummary":
|
|
474
|
-
this.addSummaryCard(message.summary, {
|
|
481
|
+
this.addSummaryCard(message.summary, {
|
|
482
|
+
title: msg().interactive.view.message.branchSummary,
|
|
483
|
+
});
|
|
475
484
|
break;
|
|
476
485
|
case "custom":
|
|
477
486
|
if (message.display)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模型选择器的列表项(`/model`、启动选择器、`/config` 的模型项共用)。
|
|
3
|
+
*
|
|
4
|
+
* - 缺省视图「已配置」:只列有 key、OAuth 已登录或本地的供应商;设置了 `models.enabled` 时只列清单内的
|
|
5
|
+
* (`provider/*` 整个供应商)。「全部」视图(`/model` 里 Tab)另列没配置的供应商,组标题标「未配置 key」。
|
|
6
|
+
* - 当前会话的模型不在视图里时置顶一行,组标题「当前」。
|
|
7
|
+
* - 多渠道供应商每个模型一行(首选渠道),说明里列出其它渠道;`channels`(筛选文本含 `@`)时再列出
|
|
8
|
+
* `model@渠道` 行。清单里逐字写了 `provider/model@渠道` 的渠道行总是列出。
|
|
9
|
+
* - 模型表为空的供应商(ChatGPT 订阅,未缓存发现结果)给一行提示(value 以 `HINT_PREFIX` 开头,不是模型)。
|
|
10
|
+
*
|
|
11
|
+
* 先 `loadModelCatalog`(解析 key,异步)再 `catalogItems`(同步):选择器切视图、改清单时不必重查 key。
|
|
12
|
+
*/
|
|
13
|
+
import type { Model, ProviderData, ProviderRegistryApi } from "../../ai/types.js";
|
|
14
|
+
import { type ProviderAccess } from "../../ai/providers/model-visibility.js";
|
|
15
|
+
import type { SelectItem } from "../../tui.js";
|
|
16
|
+
/** 提示行的 value 前缀(`ama:hint:<供应商>`);选中时不是模型。 */
|
|
17
|
+
export declare const HINT_PREFIX = "ama:hint:";
|
|
18
|
+
export declare function isHintValue(value: string): boolean;
|
|
19
|
+
export interface CatalogProvider {
|
|
20
|
+
provider: ProviderData;
|
|
21
|
+
access: ProviderAccess;
|
|
22
|
+
}
|
|
23
|
+
export interface ModelCatalog {
|
|
24
|
+
providers: readonly CatalogProvider[];
|
|
25
|
+
}
|
|
26
|
+
export interface ModelItemOptions {
|
|
27
|
+
/** `configured`(缺省)或 `all`。 */
|
|
28
|
+
view?: "configured" | "all";
|
|
29
|
+
/** `models.enabled`;undefined / 空表示不限。 */
|
|
30
|
+
enabled?: readonly string[] | undefined;
|
|
31
|
+
/** 当前模型 `provider/model[@channel]`。 */
|
|
32
|
+
current?: string | undefined;
|
|
33
|
+
/** 列出 `model@渠道` 行。 */
|
|
34
|
+
channels?: boolean;
|
|
35
|
+
/** 列提示行(缺省 true;启动选择器与 `/config` 关掉)。 */
|
|
36
|
+
hints?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** 选择器里模型的说明:名称(与 id 不同时)、上下文、`img`(收图片)。 */
|
|
39
|
+
export declare function modelDescription(model: Model): string | undefined;
|
|
40
|
+
export declare function loadModelCatalog(registry: ProviderRegistryApi): Promise<ModelCatalog>;
|
|
41
|
+
export declare function accessLabel(access: ProviderAccess): string;
|
|
42
|
+
/** 目录 → 列表项(规则见文件头)。 */
|
|
43
|
+
export declare function catalogItems(catalog: ModelCatalog, options?: ModelItemOptions): SelectItem[];
|
|
44
|
+
/** 一步到位:解析 key 再生成列表项。 */
|
|
45
|
+
export declare function modelItems(registry: ProviderRegistryApi, options?: ModelItemOptions): Promise<SelectItem[]>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模型选择器的列表项(`/model`、启动选择器、`/config` 的模型项共用)。
|
|
3
|
+
*
|
|
4
|
+
* - 缺省视图「已配置」:只列有 key、OAuth 已登录或本地的供应商;设置了 `models.enabled` 时只列清单内的
|
|
5
|
+
* (`provider/*` 整个供应商)。「全部」视图(`/model` 里 Tab)另列没配置的供应商,组标题标「未配置 key」。
|
|
6
|
+
* - 当前会话的模型不在视图里时置顶一行,组标题「当前」。
|
|
7
|
+
* - 多渠道供应商每个模型一行(首选渠道),说明里列出其它渠道;`channels`(筛选文本含 `@`)时再列出
|
|
8
|
+
* `model@渠道` 行。清单里逐字写了 `provider/model@渠道` 的渠道行总是列出。
|
|
9
|
+
* - 模型表为空的供应商(ChatGPT 订阅,未缓存发现结果)给一行提示(value 以 `HINT_PREFIX` 开头,不是模型)。
|
|
10
|
+
*
|
|
11
|
+
* 先 `loadModelCatalog`(解析 key,异步)再 `catalogItems`(同步):选择器切视图、改清单时不必重查 key。
|
|
12
|
+
*/
|
|
13
|
+
import { accessReady, enabledMatch, providerAccess, } from "../../ai/providers/model-visibility.js";
|
|
14
|
+
import { CHATGPT_PROVIDER_ID } from "../../auth/chatgpt/presets.js";
|
|
15
|
+
import { msg } from "../../i18n/index.js";
|
|
16
|
+
/** 提示行的 value 前缀(`ama:hint:<供应商>`);选中时不是模型。 */
|
|
17
|
+
export const HINT_PREFIX = "ama:hint:";
|
|
18
|
+
export function isHintValue(value) {
|
|
19
|
+
return value.startsWith(HINT_PREFIX);
|
|
20
|
+
}
|
|
21
|
+
/** 选择器里模型的说明:名称(与 id 不同时)、上下文、`img`(收图片)。 */
|
|
22
|
+
export function modelDescription(model) {
|
|
23
|
+
const ctx = model.contextWindow;
|
|
24
|
+
const parts = [
|
|
25
|
+
model.name !== "" && model.name !== model.id ? model.name : undefined,
|
|
26
|
+
ctx === undefined
|
|
27
|
+
? undefined
|
|
28
|
+
: ctx >= 1_000_000
|
|
29
|
+
? `${Math.round(ctx / 100_000) / 10}M`
|
|
30
|
+
: `${Math.round(ctx / 1000)}k`,
|
|
31
|
+
model.input.includes("image") ? "img" : undefined,
|
|
32
|
+
].filter((x) => x !== undefined);
|
|
33
|
+
return parts.length > 0 ? parts.join(" · ") : undefined;
|
|
34
|
+
}
|
|
35
|
+
export async function loadModelCatalog(registry) {
|
|
36
|
+
const providers = [];
|
|
37
|
+
for (const provider of registry.list())
|
|
38
|
+
providers.push({ provider, access: await providerAccess(registry, provider) });
|
|
39
|
+
return { providers };
|
|
40
|
+
}
|
|
41
|
+
export function accessLabel(access) {
|
|
42
|
+
const m = msg().panels.model;
|
|
43
|
+
return access === "none" ? m.noKey : m[access];
|
|
44
|
+
}
|
|
45
|
+
/** 模型的其它渠道(首选渠道之外)。 */
|
|
46
|
+
function otherChannels(model) {
|
|
47
|
+
return (model.channels ?? []).filter((c) => c !== "" && c !== model.channel);
|
|
48
|
+
}
|
|
49
|
+
function row(model, group, channel) {
|
|
50
|
+
const suffix = channel === undefined ? "" : `@${channel}`;
|
|
51
|
+
const item = {
|
|
52
|
+
value: `${model.provider}/${model.id}${suffix}`,
|
|
53
|
+
label: `${model.id}${suffix}`,
|
|
54
|
+
group,
|
|
55
|
+
};
|
|
56
|
+
const others = channel === undefined ? otherChannels(model) : [];
|
|
57
|
+
const parts = [
|
|
58
|
+
modelDescription(model),
|
|
59
|
+
others.length > 0
|
|
60
|
+
? msg().panels.model.otherChannels(others.map((c) => `@${c}`).join(" "))
|
|
61
|
+
: undefined,
|
|
62
|
+
].filter((x) => x !== undefined);
|
|
63
|
+
if (parts.length > 0)
|
|
64
|
+
item.description = parts.join(" · ");
|
|
65
|
+
return item;
|
|
66
|
+
}
|
|
67
|
+
function hintRow(entry, group) {
|
|
68
|
+
const { provider, access } = entry;
|
|
69
|
+
if (provider.models.length > 0 || !provider.requiresApiKey)
|
|
70
|
+
return undefined;
|
|
71
|
+
const m = msg().panels.model;
|
|
72
|
+
if (access === "key" || access === "oauth")
|
|
73
|
+
return { value: `${HINT_PREFIX}${provider.id}`, label: m.discoverHint(provider.id), group };
|
|
74
|
+
if (provider.id === CHATGPT_PROVIDER_ID)
|
|
75
|
+
return { value: `${HINT_PREFIX}${provider.id}`, label: m.loginHint(provider.id), group };
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
/** 目录 → 列表项(规则见文件头)。 */
|
|
79
|
+
export function catalogItems(catalog, options = {}) {
|
|
80
|
+
const all = options.view === "all";
|
|
81
|
+
const list = options.enabled !== undefined && options.enabled.length > 0 ? options.enabled : undefined;
|
|
82
|
+
const ready = [];
|
|
83
|
+
const rest = [];
|
|
84
|
+
for (const entry of catalog.providers) {
|
|
85
|
+
const { provider, access } = entry;
|
|
86
|
+
const isReady = accessReady(access);
|
|
87
|
+
const group = `${provider.id} · ${accessLabel(access)}`;
|
|
88
|
+
const items = [];
|
|
89
|
+
const listedProvider = list?.includes(`${provider.id}/*`) === true;
|
|
90
|
+
for (const model of provider.models) {
|
|
91
|
+
const main = row(model, group);
|
|
92
|
+
const listed = list !== undefined && enabledMatch(list, main.value) !== undefined;
|
|
93
|
+
const shown = all || (list !== undefined ? listed : isReady);
|
|
94
|
+
if (shown) {
|
|
95
|
+
if (all && listed)
|
|
96
|
+
main.badge = msg().panels.model.listed;
|
|
97
|
+
if (all && listed)
|
|
98
|
+
main.badgeColor = "dim";
|
|
99
|
+
items.push(main);
|
|
100
|
+
}
|
|
101
|
+
for (const channel of otherChannels(model)) {
|
|
102
|
+
const extra = row(model, group, channel);
|
|
103
|
+
const exact = list?.includes(extra.value) === true;
|
|
104
|
+
if (exact || (shown && options.channels === true))
|
|
105
|
+
items.push(extra);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const hint = options.hints === false ? undefined : hintRow(entry, group);
|
|
109
|
+
if (hint !== undefined && (all || (list !== undefined ? listedProvider : isReady)))
|
|
110
|
+
items.push(hint);
|
|
111
|
+
(isReady ? ready : rest).push(...items);
|
|
112
|
+
}
|
|
113
|
+
return pinCurrent(catalog, [...ready, ...rest], options.current);
|
|
114
|
+
}
|
|
115
|
+
/** 当前模型不在列表里时置顶一行。 */
|
|
116
|
+
function pinCurrent(catalog, items, current) {
|
|
117
|
+
if (current === undefined || current === "" || items.some((i) => i.value === current))
|
|
118
|
+
return items;
|
|
119
|
+
const slash = current.indexOf("/");
|
|
120
|
+
const at = current.lastIndexOf("@");
|
|
121
|
+
const base = at > slash ? current.slice(0, at) : current;
|
|
122
|
+
const model = catalog.providers
|
|
123
|
+
.find((p) => p.provider.id === current.slice(0, slash))
|
|
124
|
+
?.provider.models.find((m) => `${m.provider}/${m.id}` === base);
|
|
125
|
+
const item = { value: current, label: current, group: msg().panels.model.current };
|
|
126
|
+
const description = model === undefined ? undefined : modelDescription(model);
|
|
127
|
+
if (description !== undefined)
|
|
128
|
+
item.description = description;
|
|
129
|
+
return [item, ...items];
|
|
130
|
+
}
|
|
131
|
+
/** 一步到位:解析 key 再生成列表项。 */
|
|
132
|
+
export async function modelItems(registry, options = {}) {
|
|
133
|
+
return catalogItems(await loadModelCatalog(registry), options);
|
|
134
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互模式的 `/model` 选择器:居中覆盖层,列表项见 model-items.ts。
|
|
3
|
+
*
|
|
4
|
+
* - `Tab` 在「已配置 / 全部」两个视图间切换(过滤文本保留);全部视图里没配置的供应商标「未配置 key」,
|
|
5
|
+
* 选中它的模型不切换,选择器底部提示 `ama auth set` / `ama providers add`;
|
|
6
|
+
* - `Space` 把高亮的模型加入 / 移出用户级 `models.enabled`(经 config/edit.ts 写回);只经 `provider/*`
|
|
7
|
+
* 列入的不能单独移出,提示改用 `ama models disable`;
|
|
8
|
+
* - 筛选文本含 `@` 时列出各模型的 `@渠道` 行;
|
|
9
|
+
* - 已在用清单时,从全部视图选中清单外的模型会先把它加入清单再切换;
|
|
10
|
+
* - 提示行(模型表为空的供应商)选中时只在底部显示命令。
|
|
11
|
+
*/
|
|
12
|
+
import type { ProviderRegistryApi } from "../../ai/types.js";
|
|
13
|
+
import type { ModeContext } from "../../cli/deps.js";
|
|
14
|
+
import type { Runtime } from "../../cli/runtime.js";
|
|
15
|
+
import { SelectList, type Component, type Focusable } from "../../tui.js";
|
|
16
|
+
import { type ModelCatalog } from "./model-items.js";
|
|
17
|
+
import type { PickerHost } from "./pickers.js";
|
|
18
|
+
export interface ModelPickerOptions {
|
|
19
|
+
title: string;
|
|
20
|
+
providers: ProviderRegistryApi;
|
|
21
|
+
/** 当前模型 `provider/model[@channel]`。 */
|
|
22
|
+
current?: string | undefined;
|
|
23
|
+
/** 打开时的 `models.enabled`。 */
|
|
24
|
+
enabled?: readonly string[] | undefined;
|
|
25
|
+
/** 写回用户级 `models.enabled`(undefined 删除该键);抛错时错误显示在选择器底部。 */
|
|
26
|
+
saveEnabled(next: string[] | undefined): void;
|
|
27
|
+
}
|
|
28
|
+
type View = "configured" | "all";
|
|
29
|
+
/** 选择器本体(可单独测试):`done` 收到选中的模型引用或 undefined(取消)。 */
|
|
30
|
+
export declare class ModelPickerView implements Component, Focusable {
|
|
31
|
+
private readonly host;
|
|
32
|
+
private readonly catalog;
|
|
33
|
+
private readonly options;
|
|
34
|
+
private readonly done;
|
|
35
|
+
private view;
|
|
36
|
+
private enabled;
|
|
37
|
+
private notice;
|
|
38
|
+
private channels;
|
|
39
|
+
readonly list: SelectList;
|
|
40
|
+
constructor(host: PickerHost, catalog: ModelCatalog, options: ModelPickerOptions, done: (ref: string | undefined) => void);
|
|
41
|
+
get focused(): boolean;
|
|
42
|
+
set focused(value: boolean);
|
|
43
|
+
get currentView(): View;
|
|
44
|
+
private rebuild;
|
|
45
|
+
handleInput(data: string): void;
|
|
46
|
+
private providerOf;
|
|
47
|
+
private save;
|
|
48
|
+
private toggle;
|
|
49
|
+
private select;
|
|
50
|
+
render(width: number): string[];
|
|
51
|
+
invalidate(): void;
|
|
52
|
+
}
|
|
53
|
+
/** 打开 `/model` 选择器;返回选中的模型引用,取消返回 undefined。 */
|
|
54
|
+
export declare function openModelPicker(host: PickerHost, options: ModelPickerOptions): Promise<string | undefined>;
|
|
55
|
+
/** 交互模式装配:清单读 `runtime.config`,写用户级 config.json 并换上新配置。 */
|
|
56
|
+
export declare function modelPickerFor(host: PickerHost, runtime: Runtime, context: ModeContext): (providers: ProviderRegistryApi, current: string | undefined) => Promise<string | undefined>;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互模式的 `/model` 选择器:居中覆盖层,列表项见 model-items.ts。
|
|
3
|
+
*
|
|
4
|
+
* - `Tab` 在「已配置 / 全部」两个视图间切换(过滤文本保留);全部视图里没配置的供应商标「未配置 key」,
|
|
5
|
+
* 选中它的模型不切换,选择器底部提示 `ama auth set` / `ama providers add`;
|
|
6
|
+
* - `Space` 把高亮的模型加入 / 移出用户级 `models.enabled`(经 config/edit.ts 写回);只经 `provider/*`
|
|
7
|
+
* 列入的不能单独移出,提示改用 `ama models disable`;
|
|
8
|
+
* - 筛选文本含 `@` 时列出各模型的 `@渠道` 行;
|
|
9
|
+
* - 已在用清单时,从全部视图选中清单外的模型会先把它加入清单再切换;
|
|
10
|
+
* - 提示行(模型表为空的供应商)选中时只在底部显示命令。
|
|
11
|
+
*/
|
|
12
|
+
import { accessReady, addEnabled, enabledList, enabledMatch, removeEnabled, } from "../../ai/providers/model-visibility.js";
|
|
13
|
+
import { setConfigValue } from "../../config/edit.js";
|
|
14
|
+
import { msg } from "../../i18n/index.js";
|
|
15
|
+
import { Box, SelectList, matchesKey, wrapTextWithAnsi, } from "../../tui.js";
|
|
16
|
+
import { layerInputFor } from "./config-ui.js";
|
|
17
|
+
import { catalogItems, isHintValue, loadModelCatalog } from "./model-items.js";
|
|
18
|
+
/** 选择器本体(可单独测试):`done` 收到选中的模型引用或 undefined(取消)。 */
|
|
19
|
+
export class ModelPickerView {
|
|
20
|
+
host;
|
|
21
|
+
catalog;
|
|
22
|
+
options;
|
|
23
|
+
done;
|
|
24
|
+
view = "configured";
|
|
25
|
+
enabled;
|
|
26
|
+
notice;
|
|
27
|
+
channels = false;
|
|
28
|
+
list;
|
|
29
|
+
constructor(host, catalog, options, done) {
|
|
30
|
+
this.host = host;
|
|
31
|
+
this.catalog = catalog;
|
|
32
|
+
this.options = options;
|
|
33
|
+
this.done = done;
|
|
34
|
+
this.enabled = enabledList(options.enabled);
|
|
35
|
+
this.list = new SelectList([], {
|
|
36
|
+
theme: host.theme,
|
|
37
|
+
maxVisible: 12,
|
|
38
|
+
filterable: true,
|
|
39
|
+
showCount: true,
|
|
40
|
+
...(host.keybindings !== undefined ? { keybindings: host.keybindings } : {}),
|
|
41
|
+
...(options.current !== undefined ? { currentValue: options.current } : {}),
|
|
42
|
+
emptyText: msg().panels.model.emptyConfigured,
|
|
43
|
+
onSelect: (item) => this.select(item),
|
|
44
|
+
onCancel: () => this.done(undefined),
|
|
45
|
+
});
|
|
46
|
+
this.rebuild();
|
|
47
|
+
if (options.current !== undefined)
|
|
48
|
+
this.list.selectValue(options.current);
|
|
49
|
+
}
|
|
50
|
+
get focused() {
|
|
51
|
+
return this.list.focused;
|
|
52
|
+
}
|
|
53
|
+
set focused(value) {
|
|
54
|
+
this.list.focused = value;
|
|
55
|
+
}
|
|
56
|
+
get currentView() {
|
|
57
|
+
return this.view;
|
|
58
|
+
}
|
|
59
|
+
rebuild() {
|
|
60
|
+
const m = msg().panels.model;
|
|
61
|
+
this.list.setFooter(this.view === "all" ? m.footerAll : m.footerConfigured);
|
|
62
|
+
this.list.setItems(catalogItems(this.catalog, {
|
|
63
|
+
view: this.view,
|
|
64
|
+
enabled: this.enabled,
|
|
65
|
+
current: this.options.current,
|
|
66
|
+
channels: this.channels,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
handleInput(data) {
|
|
70
|
+
if (matchesKey(data, "tab")) {
|
|
71
|
+
this.view = this.view === "all" ? "configured" : "all";
|
|
72
|
+
this.notice = undefined;
|
|
73
|
+
this.rebuild();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (data === " ") {
|
|
77
|
+
this.toggle();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.list.handleInput(data);
|
|
81
|
+
const channels = this.list.getFilter().includes("@");
|
|
82
|
+
if (channels !== this.channels) {
|
|
83
|
+
this.channels = channels;
|
|
84
|
+
this.rebuild();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
providerOf(value) {
|
|
88
|
+
const id = value.slice(0, value.indexOf("/"));
|
|
89
|
+
return this.catalog.providers.find((p) => p.provider.id === id);
|
|
90
|
+
}
|
|
91
|
+
save(next) {
|
|
92
|
+
try {
|
|
93
|
+
this.options.saveEnabled(next);
|
|
94
|
+
this.enabled = next;
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
this.notice = {
|
|
99
|
+
text: error instanceof Error ? error.message : String(error),
|
|
100
|
+
level: "error",
|
|
101
|
+
};
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
toggle() {
|
|
106
|
+
const item = this.list.getSelected();
|
|
107
|
+
if (item === undefined || isHintValue(item.value))
|
|
108
|
+
return;
|
|
109
|
+
const m = msg().panels.model;
|
|
110
|
+
const ref = item.value;
|
|
111
|
+
const match = this.enabled === undefined ? undefined : enabledMatch(this.enabled, ref);
|
|
112
|
+
if (match?.kind === "wildcard") {
|
|
113
|
+
this.notice = { text: m.wildcard(ref, match.pattern), level: "warning" };
|
|
114
|
+
}
|
|
115
|
+
else if (match !== undefined) {
|
|
116
|
+
if (this.save(removeEnabled(this.enabled, [ref])))
|
|
117
|
+
this.notice = { text: m.removed(ref), level: "info" };
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const first = this.enabled === undefined;
|
|
121
|
+
if (this.save(addEnabled(this.enabled, [ref])))
|
|
122
|
+
this.notice = { text: first ? m.addedFirst(ref) : m.added(ref), level: "info" };
|
|
123
|
+
}
|
|
124
|
+
this.rebuild();
|
|
125
|
+
}
|
|
126
|
+
select(item) {
|
|
127
|
+
const m = msg().panels.model;
|
|
128
|
+
const id = item.value.slice(0, item.value.indexOf("/"));
|
|
129
|
+
if (isHintValue(item.value)) {
|
|
130
|
+
this.notice = { text: item.label, level: "info" };
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const entry = this.providerOf(item.value);
|
|
134
|
+
if (item.value !== this.options.current && entry !== undefined && !accessReady(entry.access)) {
|
|
135
|
+
const text = entry.access === "needsLogin" ? m.needsLoginHint(id) : m.noKeyHint(id);
|
|
136
|
+
this.notice = { text, level: "warning" };
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (this.enabled !== undefined &&
|
|
140
|
+
item.value !== this.options.current &&
|
|
141
|
+
enabledMatch(this.enabled, item.value) === undefined &&
|
|
142
|
+
!this.save(addEnabled(this.enabled, [item.value])))
|
|
143
|
+
return;
|
|
144
|
+
this.done(item.value);
|
|
145
|
+
}
|
|
146
|
+
render(width) {
|
|
147
|
+
const lines = this.list.render(width);
|
|
148
|
+
if (this.notice === undefined)
|
|
149
|
+
return lines;
|
|
150
|
+
const theme = this.host.theme;
|
|
151
|
+
const color = this.notice.level === "info" ? "dim" : this.notice.level;
|
|
152
|
+
return [...lines, ...wrapTextWithAnsi(theme.fg(color, this.notice.text), width)];
|
|
153
|
+
}
|
|
154
|
+
invalidate() {
|
|
155
|
+
this.list.invalidate();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** 打开 `/model` 选择器;返回选中的模型引用,取消返回 undefined。 */
|
|
159
|
+
export async function openModelPicker(host, options) {
|
|
160
|
+
const catalog = await loadModelCatalog(options.providers);
|
|
161
|
+
return new Promise((resolve) => {
|
|
162
|
+
let handle;
|
|
163
|
+
const view = new ModelPickerView(host, catalog, options, (ref) => {
|
|
164
|
+
handle?.hide();
|
|
165
|
+
resolve(ref);
|
|
166
|
+
});
|
|
167
|
+
const width = Math.max(20, Math.min(host.columns() - 2, 72));
|
|
168
|
+
handle = host.showOverlay(new Box(view, { title: options.title, theme: host.theme }), {
|
|
169
|
+
anchor: "center",
|
|
170
|
+
width,
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/** 交互模式装配:清单读 `runtime.config`,写用户级 config.json 并换上新配置。 */
|
|
175
|
+
export function modelPickerFor(host, runtime, context) {
|
|
176
|
+
return (providers, current) => openModelPicker(host, {
|
|
177
|
+
title: msg().interactive.commands.modelTitle,
|
|
178
|
+
providers,
|
|
179
|
+
current,
|
|
180
|
+
enabled: runtime.config.models?.enabled,
|
|
181
|
+
saveEnabled: (next) => {
|
|
182
|
+
const result = setConfigValue({
|
|
183
|
+
...layerInputFor(runtime, context),
|
|
184
|
+
scope: "user",
|
|
185
|
+
key: "models.enabled",
|
|
186
|
+
value: next,
|
|
187
|
+
});
|
|
188
|
+
runtime.replaceConfig?.(result.snapshot.config);
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
}
|