@ai-zen/cli 1.0.0-alpha.9 → 1.0.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 +1334 -275
- package/LICENSE +21 -0
- package/README.md +136 -31
- package/README.zh.md +136 -31
- package/dist/agent-creator.d.ts +11 -0
- package/dist/agent-creator.d.ts.map +1 -1
- package/dist/agent-creator.js +50 -20
- package/dist/agent-creator.js.map +1 -1
- package/dist/agent-switch.d.ts +61 -0
- package/dist/agent-switch.d.ts.map +1 -0
- package/dist/agent-switch.js +83 -0
- package/dist/agent-switch.js.map +1 -0
- package/dist/agents-store.d.ts +6 -1
- package/dist/agents-store.d.ts.map +1 -1
- package/dist/agents-store.js +46 -4
- package/dist/agents-store.js.map +1 -1
- package/dist/auto-migrate-confirm.d.ts +43 -0
- package/dist/auto-migrate-confirm.d.ts.map +1 -0
- package/dist/auto-migrate-confirm.js +47 -0
- package/dist/auto-migrate-confirm.js.map +1 -0
- package/dist/clipboard.d.ts +68 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +177 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/config-editor.d.ts +42 -5
- package/dist/config-editor.d.ts.map +1 -1
- package/dist/config-editor.js +80 -27
- package/dist/config-editor.js.map +1 -1
- package/dist/config.d.ts +76 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +143 -39
- package/dist/config.js.map +1 -1
- package/dist/conversation-commands/registry.d.ts +127 -4
- package/dist/conversation-commands/registry.d.ts.map +1 -1
- package/dist/conversation-commands/registry.js +93 -14
- package/dist/conversation-commands/registry.js.map +1 -1
- package/dist/conversation-persist-plugin.d.ts +0 -1
- package/dist/conversation-persist-plugin.d.ts.map +1 -1
- package/dist/conversation-persist-plugin.js +7 -16
- package/dist/conversation-persist-plugin.js.map +1 -1
- package/dist/conversation-repository.d.ts +79 -18
- package/dist/conversation-repository.d.ts.map +1 -1
- package/dist/conversation-repository.js +96 -30
- package/dist/conversation-repository.js.map +1 -1
- package/dist/cwd-tracker-plugin.d.ts.map +1 -1
- package/dist/cwd-tracker-plugin.js +22 -7
- package/dist/cwd-tracker-plugin.js.map +1 -1
- package/dist/format-time.d.ts +17 -6
- package/dist/format-time.d.ts.map +1 -1
- package/dist/format-time.js +32 -14
- package/dist/format-time.js.map +1 -1
- package/dist/handoff-service.d.ts +19 -0
- package/dist/handoff-service.d.ts.map +1 -0
- package/dist/handoff-service.js +85 -0
- package/dist/handoff-service.js.map +1 -0
- package/dist/hook.d.ts.map +1 -1
- package/dist/hook.js +69 -15
- package/dist/hook.js.map +1 -1
- package/dist/i18n/en-wizard.d.ts +8 -0
- package/dist/i18n/en-wizard.d.ts.map +1 -0
- package/dist/i18n/en-wizard.js +303 -0
- package/dist/i18n/en-wizard.js.map +1 -0
- package/dist/i18n/en.d.ts +7 -0
- package/dist/i18n/en.d.ts.map +1 -0
- package/dist/i18n/en.js +245 -0
- package/dist/i18n/en.js.map +1 -0
- package/dist/i18n/index.d.ts +57 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +109 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/preferences.d.ts +37 -0
- package/dist/i18n/preferences.d.ts.map +1 -0
- package/dist/i18n/preferences.js +73 -0
- package/dist/i18n/preferences.js.map +1 -0
- package/dist/i18n/zh-wizard.d.ts +11 -0
- package/dist/i18n/zh-wizard.d.ts.map +1 -0
- package/dist/i18n/zh-wizard.js +306 -0
- package/dist/i18n/zh-wizard.js.map +1 -0
- package/dist/i18n/zh.d.ts +10 -0
- package/dist/i18n/zh.d.ts.map +1 -0
- package/dist/i18n/zh.js +249 -0
- package/dist/i18n/zh.js.map +1 -0
- package/dist/index.js +52 -23
- package/dist/index.js.map +1 -1
- package/dist/mcp-command.d.ts +32 -0
- package/dist/mcp-command.d.ts.map +1 -0
- package/dist/mcp-command.js +37 -0
- package/dist/mcp-command.js.map +1 -0
- package/dist/mode.d.ts +31 -4
- package/dist/mode.d.ts.map +1 -1
- package/dist/mode.js +42 -7
- package/dist/mode.js.map +1 -1
- package/dist/model-switch.d.ts +58 -0
- package/dist/model-switch.d.ts.map +1 -0
- package/dist/model-switch.js +62 -0
- package/dist/model-switch.js.map +1 -0
- package/dist/reasoning-effort.d.ts +96 -0
- package/dist/reasoning-effort.d.ts.map +1 -0
- package/dist/reasoning-effort.js +164 -0
- package/dist/reasoning-effort.js.map +1 -0
- package/dist/reasoning-presets.d.ts +34 -0
- package/dist/reasoning-presets.d.ts.map +1 -0
- package/dist/reasoning-presets.js +85 -0
- package/dist/reasoning-presets.js.map +1 -0
- package/dist/sdk-log.d.ts +84 -0
- package/dist/sdk-log.d.ts.map +1 -0
- package/dist/sdk-log.js +167 -0
- package/dist/sdk-log.js.map +1 -0
- package/dist/session-pointer.d.ts.map +1 -1
- package/dist/session-pointer.js +10 -4
- package/dist/session-pointer.js.map +1 -1
- package/dist/stdio-runner.d.ts.map +1 -1
- package/dist/stdio-runner.js +32 -30
- package/dist/stdio-runner.js.map +1 -1
- package/dist/sub-agent-guard-plugin.d.ts +10 -7
- package/dist/sub-agent-guard-plugin.d.ts.map +1 -1
- package/dist/sub-agent-guard-plugin.js +12 -9
- package/dist/sub-agent-guard-plugin.js.map +1 -1
- package/dist/tui/chat-history.d.ts +29 -0
- package/dist/tui/chat-history.d.ts.map +1 -0
- package/dist/tui/chat-history.js +55 -0
- package/dist/tui/chat-history.js.map +1 -0
- package/dist/tui/chat-session.d.ts +144 -13
- package/dist/tui/chat-session.d.ts.map +1 -1
- package/dist/tui/chat-session.js +312 -73
- package/dist/tui/chat-session.js.map +1 -1
- package/dist/tui/components.d.ts +109 -6
- package/dist/tui/components.d.ts.map +1 -1
- package/dist/tui/components.js +177 -12
- package/dist/tui/components.js.map +1 -1
- package/dist/tui/config-wizard/detail.d.ts +18 -10
- package/dist/tui/config-wizard/detail.d.ts.map +1 -1
- package/dist/tui/config-wizard/detail.js +53 -46
- package/dist/tui/config-wizard/detail.js.map +1 -1
- package/dist/tui/config-wizard/engine.d.ts +2 -2
- package/dist/tui/config-wizard/engine.d.ts.map +1 -1
- package/dist/tui/config-wizard/engine.js +48 -26
- package/dist/tui/config-wizard/engine.js.map +1 -1
- package/dist/tui/config-wizard/fields.d.ts +3 -1
- package/dist/tui/config-wizard/fields.d.ts.map +1 -1
- package/dist/tui/config-wizard/fields.js +202 -167
- package/dist/tui/config-wizard/fields.js.map +1 -1
- package/dist/tui/config-wizard/frame.js +1 -1
- package/dist/tui/config-wizard/kv-editor.d.ts.map +1 -1
- package/dist/tui/config-wizard/kv-editor.js +13 -5
- package/dist/tui/config-wizard/kv-editor.js.map +1 -1
- package/dist/tui/config-wizard/list.d.ts +3 -1
- package/dist/tui/config-wizard/list.d.ts.map +1 -1
- package/dist/tui/config-wizard/list.js +4 -4
- package/dist/tui/config-wizard/list.js.map +1 -1
- package/dist/tui/config-wizard/mcp-helpers.d.ts.map +1 -1
- package/dist/tui/config-wizard/mcp-helpers.js +4 -3
- package/dist/tui/config-wizard/mcp-helpers.js.map +1 -1
- package/dist/tui/config-wizard/menu.d.ts.map +1 -1
- package/dist/tui/config-wizard/menu.js +33 -21
- package/dist/tui/config-wizard/menu.js.map +1 -1
- package/dist/tui/config-wizard/prompt-editor.d.ts +8 -1
- package/dist/tui/config-wizard/prompt-editor.d.ts.map +1 -1
- package/dist/tui/config-wizard/prompt-editor.js +11 -7
- package/dist/tui/config-wizard/prompt-editor.js.map +1 -1
- package/dist/tui/config-wizard/prompt.d.ts.map +1 -1
- package/dist/tui/config-wizard/prompt.js +8 -7
- package/dist/tui/config-wizard/prompt.js.map +1 -1
- package/dist/tui/config-wizard/step-agents.d.ts.map +1 -1
- package/dist/tui/config-wizard/step-agents.js +50 -29
- package/dist/tui/config-wizard/step-agents.js.map +1 -1
- package/dist/tui/config-wizard/step-defaults.d.ts.map +1 -1
- package/dist/tui/config-wizard/step-defaults.js +77 -27
- package/dist/tui/config-wizard/step-defaults.js.map +1 -1
- package/dist/tui/config-wizard/step-endpoints.d.ts.map +1 -1
- package/dist/tui/config-wizard/step-endpoints.js +27 -14
- package/dist/tui/config-wizard/step-endpoints.js.map +1 -1
- package/dist/tui/config-wizard/step-mcp.d.ts.map +1 -1
- package/dist/tui/config-wizard/step-mcp.js +29 -25
- package/dist/tui/config-wizard/step-mcp.js.map +1 -1
- package/dist/tui/config-wizard/step-models.d.ts.map +1 -1
- package/dist/tui/config-wizard/step-models.js +98 -43
- package/dist/tui/config-wizard/step-models.js.map +1 -1
- package/dist/tui/config-wizard/step-new-endpoint.d.ts.map +1 -1
- package/dist/tui/config-wizard/step-new-endpoint.js +16 -12
- package/dist/tui/config-wizard/step-new-endpoint.js.map +1 -1
- package/dist/tui/config-wizard/step-simple.d.ts.map +1 -1
- package/dist/tui/config-wizard/step-simple.js +18 -17
- package/dist/tui/config-wizard/step-simple.js.map +1 -1
- package/dist/tui/config-wizard/types.d.ts +31 -3
- package/dist/tui/config-wizard/types.d.ts.map +1 -1
- package/dist/tui/config-wizard/types.js.map +1 -1
- package/dist/tui/file-index.d.ts +38 -0
- package/dist/tui/file-index.d.ts.map +1 -0
- package/dist/tui/file-index.js +117 -0
- package/dist/tui/file-index.js.map +1 -0
- package/dist/tui/index.d.ts +17 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +105 -49
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/input-editing.d.ts +52 -0
- package/dist/tui/input-editing.d.ts.map +1 -0
- package/dist/tui/input-editing.js +91 -0
- package/dist/tui/input-editing.js.map +1 -0
- package/dist/tui/key-debug.d.ts +62 -0
- package/dist/tui/key-debug.d.ts.map +1 -0
- package/dist/tui/key-debug.js +92 -0
- package/dist/tui/key-debug.js.map +1 -0
- package/dist/tui/mention.d.ts +47 -0
- package/dist/tui/mention.d.ts.map +1 -0
- package/dist/tui/mention.js +152 -0
- package/dist/tui/mention.js.map +1 -0
- package/dist/tui/mouse.d.ts +55 -0
- package/dist/tui/mouse.d.ts.map +1 -0
- package/dist/tui/mouse.js +74 -0
- package/dist/tui/mouse.js.map +1 -0
- package/dist/tui/phase.d.ts +64 -0
- package/dist/tui/phase.d.ts.map +1 -0
- package/dist/tui/phase.js +112 -0
- package/dist/tui/phase.js.map +1 -0
- package/dist/tui/screens/agent-tabs.d.ts +53 -0
- package/dist/tui/screens/agent-tabs.d.ts.map +1 -0
- package/dist/tui/screens/agent-tabs.js +81 -0
- package/dist/tui/screens/agent-tabs.js.map +1 -0
- package/dist/tui/screens/chat-commands.d.ts +78 -1
- package/dist/tui/screens/chat-commands.d.ts.map +1 -1
- package/dist/tui/screens/chat-commands.js +688 -157
- package/dist/tui/screens/chat-commands.js.map +1 -1
- package/dist/tui/screens/chat.d.ts +57 -1
- package/dist/tui/screens/chat.d.ts.map +1 -1
- package/dist/tui/screens/chat.js +708 -261
- package/dist/tui/screens/chat.js.map +1 -1
- package/dist/tui/screens/common-keys.d.ts +36 -0
- package/dist/tui/screens/common-keys.d.ts.map +1 -0
- package/dist/tui/screens/common-keys.js +67 -0
- package/dist/tui/screens/common-keys.js.map +1 -0
- package/dist/tui/screens/frame-buffer.d.ts.map +1 -1
- package/dist/tui/screens/frame-buffer.js.map +1 -1
- package/dist/tui/screens/handoff-choice.d.ts +37 -0
- package/dist/tui/screens/handoff-choice.d.ts.map +1 -0
- package/dist/tui/screens/handoff-choice.js +42 -0
- package/dist/tui/screens/handoff-choice.js.map +1 -0
- package/dist/tui/screens/index.d.ts +7 -5
- package/dist/tui/screens/index.d.ts.map +1 -1
- package/dist/tui/screens/index.js +6 -5
- package/dist/tui/screens/index.js.map +1 -1
- package/dist/tui/screens/input-row.d.ts +64 -0
- package/dist/tui/screens/input-row.d.ts.map +1 -0
- package/dist/tui/screens/input-row.js +67 -0
- package/dist/tui/screens/input-row.js.map +1 -0
- package/dist/tui/screens/input.d.ts +77 -1
- package/dist/tui/screens/input.d.ts.map +1 -1
- package/dist/tui/screens/input.js +125 -8
- package/dist/tui/screens/input.js.map +1 -1
- package/dist/tui/screens/layout.d.ts +49 -0
- package/dist/tui/screens/layout.d.ts.map +1 -1
- package/dist/tui/screens/layout.js +45 -7
- package/dist/tui/screens/layout.js.map +1 -1
- package/dist/tui/screens/lines.d.ts +7 -0
- package/dist/tui/screens/lines.d.ts.map +1 -1
- package/dist/tui/screens/lines.js +6 -6
- package/dist/tui/screens/lines.js.map +1 -1
- package/dist/tui/screens/messages-view.d.ts +20 -1
- package/dist/tui/screens/messages-view.d.ts.map +1 -1
- package/dist/tui/screens/messages-view.js +55 -8
- package/dist/tui/screens/messages-view.js.map +1 -1
- package/dist/tui/screens/notice-bar.d.ts +5 -0
- package/dist/tui/screens/notice-bar.d.ts.map +1 -0
- package/dist/tui/screens/notice-bar.js +21 -0
- package/dist/tui/screens/notice-bar.js.map +1 -0
- package/dist/tui/screens/notice.d.ts +44 -10
- package/dist/tui/screens/notice.d.ts.map +1 -1
- package/dist/tui/screens/notice.js +75 -15
- package/dist/tui/screens/notice.js.map +1 -1
- package/dist/tui/screens/overlays.d.ts.map +1 -1
- package/dist/tui/screens/overlays.js +4 -3
- package/dist/tui/screens/overlays.js.map +1 -1
- package/dist/tui/screens/render.d.ts +1 -1
- package/dist/tui/screens/render.d.ts.map +1 -1
- package/dist/tui/screens/render.js +18 -11
- package/dist/tui/screens/render.js.map +1 -1
- package/dist/tui/screens/use-chat-viewport.d.ts +22 -0
- package/dist/tui/screens/use-chat-viewport.d.ts.map +1 -0
- package/dist/tui/screens/use-chat-viewport.js +50 -0
- package/dist/tui/screens/use-chat-viewport.js.map +1 -0
- package/dist/tui/screens/use-input-editing.d.ts +69 -0
- package/dist/tui/screens/use-input-editing.d.ts.map +1 -0
- package/dist/tui/screens/use-input-editing.js +220 -0
- package/dist/tui/screens/use-input-editing.js.map +1 -0
- package/dist/tui/screens/use-overlays.d.ts +25 -0
- package/dist/tui/screens/use-overlays.d.ts.map +1 -0
- package/dist/tui/screens/use-overlays.js +32 -0
- package/dist/tui/screens/use-overlays.js.map +1 -0
- package/dist/tui/screens/use-wizard-host.d.ts +46 -0
- package/dist/tui/screens/use-wizard-host.d.ts.map +1 -0
- package/dist/tui/screens/use-wizard-host.js +123 -0
- package/dist/tui/screens/use-wizard-host.js.map +1 -0
- package/dist/tui/screens/welcome.d.ts +12 -0
- package/dist/tui/screens/welcome.d.ts.map +1 -0
- package/dist/tui/screens/welcome.js +36 -0
- package/dist/tui/screens/welcome.js.map +1 -0
- package/dist/tui/status-segments.d.ts +37 -0
- package/dist/tui/status-segments.d.ts.map +1 -0
- package/dist/tui/status-segments.js +166 -0
- package/dist/tui/status-segments.js.map +1 -0
- package/dist/tui/text.d.ts +22 -7
- package/dist/tui/text.d.ts.map +1 -1
- package/dist/tui/text.js +110 -39
- package/dist/tui/text.js.map +1 -1
- package/dist/tui/theme.d.ts +2 -0
- package/dist/tui/theme.d.ts.map +1 -1
- package/dist/tui/theme.js +2 -0
- package/dist/tui/theme.js.map +1 -1
- package/dist/tui/token-rate.d.ts +83 -0
- package/dist/tui/token-rate.d.ts.map +1 -0
- package/dist/tui/token-rate.js +195 -0
- package/dist/tui/token-rate.js.map +1 -0
- package/dist/types.d.ts +7 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/user-content.d.ts +41 -0
- package/dist/user-content.d.ts.map +1 -0
- package/dist/user-content.js +37 -0
- package/dist/user-content.js.map +1 -0
- package/dist/version-compare.d.ts +37 -0
- package/dist/version-compare.d.ts.map +1 -0
- package/dist/version-compare.js +105 -0
- package/dist/version-compare.js.map +1 -0
- package/dist/version.js.map +1 -1
- package/package.json +7 -5
- package/dist/auto-migrate-confirm-plugin.d.ts +0 -58
- package/dist/auto-migrate-confirm-plugin.d.ts.map +0 -1
- package/dist/auto-migrate-confirm-plugin.js +0 -61
- package/dist/auto-migrate-confirm-plugin.js.map +0 -1
- package/dist/migration-service.d.ts +0 -15
- package/dist/migration-service.d.ts.map +0 -1
- package/dist/migration-service.js +0 -66
- package/dist/migration-service.js.map +0 -1
- package/dist/tui/screens/splash.d.ts +0 -5
- package/dist/tui/screens/splash.d.ts.map +0 -1
- package/dist/tui/screens/splash.js +0 -51
- package/dist/tui/screens/splash.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-chat-viewport.js","sourceRoot":"","sources":["../../../src/tui/screens/use-chat-viewport.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,EAAE;AACF,yDAAyD;AACzD,kDAAkD;AAClD,yBAAyB;AACzB,EAAE;AACF,gDAAgD;AAChD,8BAA8B;AAC9B,2DAA2D;AAC3D,2BAA2B;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAmB,MAAM,aAAa,CAAC;AAqB5D,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC5D,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAElD,wDAAwD;IACxD,sCAAsC;IACtC,0DAA0D;IAC1D,wCAAwC;IACxC,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,OAAe,EAAE,EAAE;QAC/C,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,GAAW,EAAE,EAAE;QACd,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,gDAAgD;QAChD,0CAA0C;QAC1C,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,GAAW,EAAE,EAAE;QACd,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;IAC5B,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,MAAM,aAAa,GAAG,WAAW,CAC/B,CAAC,GAAW,EAAE,EAAE;QACd,MAAM,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,QAAQ,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,GAAG,UAAU,CAAC,CAAC;IACzC,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAE/D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ClipboardImage } from "../../clipboard.js";
|
|
2
|
+
import type { HistoryEntry } from "../chat-history.js";
|
|
3
|
+
import type { Notice } from "./notice.js";
|
|
4
|
+
export interface InputEditingDeps {
|
|
5
|
+
/** 初始草稿(`/back` 撤回后重挂载用的预填内容),缺省空 */
|
|
6
|
+
initialText?: string;
|
|
7
|
+
/** 通知出口(暂存 / 取回草稿的提示,走通知通道而不是转录) */
|
|
8
|
+
notify: (text: string, tone?: Notice["tone"]) => void;
|
|
9
|
+
/**
|
|
10
|
+
* 历史数据源(`↑` / `↓` 翻的就是它):按发送顺序返回草稿,**最后一条最新**。
|
|
11
|
+
*
|
|
12
|
+
* 由外部注入(`userDrafts(session.messages)`)而不是 hook 自己攒:消息才是真相源,
|
|
13
|
+
* 自带图片;内部再存一份 `string[]` 就只能存文本,`↑` 回到带图消息时图会静默丢失。
|
|
14
|
+
*/
|
|
15
|
+
historySource: () => readonly HistoryEntry[];
|
|
16
|
+
/** 把历史里的附件放回输入区(`↑` 回到带图片的消息时) */
|
|
17
|
+
restoreImages: (images: readonly ClipboardImage[]) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface InputEditing {
|
|
20
|
+
/** 当前草稿 */
|
|
21
|
+
input: string;
|
|
22
|
+
/** 光标位置:以字素簇计的索引(0..字数),可落在末尾之后一格 */
|
|
23
|
+
cursor: number;
|
|
24
|
+
/** 整体替换草稿(光标移到末尾) */
|
|
25
|
+
setInputText: (text: string) => void;
|
|
26
|
+
insertAtCursor: (text: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* 用一段文本替换 `[start, end)` 区间(光标落到插入文本末尾),并记一条撤销。
|
|
29
|
+
*
|
|
30
|
+
* `@` 文件补全专用:它替换的是**整个 token**(可能是 `@src/tu` 这种半截路径,
|
|
31
|
+
* 也可能是光标停在中间、右半边还没删的部分),而不是在光标处插入。
|
|
32
|
+
* 走 `applyEdit` 才有撤销快照 —— 补错一次 `Ctrl+_` 就能退回原样。
|
|
33
|
+
*/
|
|
34
|
+
replaceRange: (start: number, end: number, text: string) => void;
|
|
35
|
+
deleteBeforeCursor: () => void;
|
|
36
|
+
deleteAfterCursor: () => void;
|
|
37
|
+
deleteWordBeforeCursor: () => void;
|
|
38
|
+
deleteWordAfterCursor: () => void;
|
|
39
|
+
deleteToStartOfLine: () => void;
|
|
40
|
+
deleteToEndOfLine: () => void;
|
|
41
|
+
/** Ctrl+W:删到前一空白(标点不切分) */
|
|
42
|
+
deletePrevWhitespace: () => void;
|
|
43
|
+
/** Ctrl+Y / Alt+Y:取回 kill ring 里的一段;`advance` 为真时循环到更早的一段 */
|
|
44
|
+
yank: (advance: boolean) => void;
|
|
45
|
+
/** Ctrl+_:撤销上一次编辑 */
|
|
46
|
+
undoEdit: () => void;
|
|
47
|
+
/** Ctrl+S:暂存草稿 / 取回草稿 */
|
|
48
|
+
toggleStash: () => void;
|
|
49
|
+
moveCursor: (delta: number) => void;
|
|
50
|
+
moveCursorToLineStart: () => void;
|
|
51
|
+
moveCursorToLineEnd: () => void;
|
|
52
|
+
/**
|
|
53
|
+
* ↑ / ↓:光标上 / 下移一行(按折行后的视觉行,需要当前折行宽度)。
|
|
54
|
+
*
|
|
55
|
+
* 返回 `false` 表示已经在首行(↑)/ 末行(↓)——呼叫方据此改成翻历史:
|
|
56
|
+
* 「能在行间走就在行间走,走不动了才动历史」是这两个键的唯一语义。
|
|
57
|
+
*/
|
|
58
|
+
moveCursorUpRow: (width: number) => boolean;
|
|
59
|
+
moveCursorDownRow: (width: number) => boolean;
|
|
60
|
+
/** 按词左右移动:`dir` 为 -1 往前、1 往后 */
|
|
61
|
+
moveCursorByWord: (dir: -1 | 1) => void;
|
|
62
|
+
/** 历史:上一条 / 下一条(没有可翻的时候自动空转;带图片的消息会把附件一并放回) */
|
|
63
|
+
historyPrev: () => void;
|
|
64
|
+
historyNext: () => void;
|
|
65
|
+
/** 提交时调用:清空草稿并退出历史浏览(历史游标复位到底部) */
|
|
66
|
+
clearDraft: () => void;
|
|
67
|
+
}
|
|
68
|
+
export declare function useInputEditing({ initialText, notify, historySource, restoreImages }: InputEditingDeps): InputEditing;
|
|
69
|
+
//# sourceMappingURL=use-input-editing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-input-editing.d.ts","sourceRoot":"","sources":["../../../src/tui/screens/use-input-editing.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACtD;;;;;OAKG;IACH,aAAa,EAAE,MAAM,SAAS,YAAY,EAAE,CAAC;IAC7C,kCAAkC;IAClC,aAAa,EAAE,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,KAAK,IAAI,CAAC;CAC5D;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC;;;;;;OAMG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,sBAAsB,EAAE,MAAM,IAAI,CAAC;IACnC,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,2BAA2B;IAC3B,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC,6DAA6D;IAC7D,IAAI,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,qBAAqB;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,yBAAyB;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC,mBAAmB,EAAE,MAAM,IAAI,CAAC;IAChC;;;;;OAKG;IACH,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC5C,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAC9C,gCAAgC;IAChC,gBAAgB,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACxC,+CAA+C;IAC/C,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,mCAAmC;IACnC,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,EAAE,gBAAgB,GAAG,YAAY,CAkNrH"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// 输入编辑 —— 草稿文本与光标、历史、kill ring、撤销栈、暂存区的唯一实现
|
|
2
|
+
//
|
|
3
|
+
// 从 `chat.tsx` 抽出来的理由:这一整块(`input` / `cursor` / `history` / kill ring /
|
|
4
|
+
// undo / stash + 20 个编辑动作)是**纯编辑器语义**,与「对话屏」毫无关系,却和会话、
|
|
5
|
+
// 向导、渲染挤在同一个组件里 —— 于是既不能单测,也每次都被误认为「对话的一部分」。
|
|
6
|
+
//
|
|
7
|
+
// 两条贯穿全篇的约定:
|
|
8
|
+
//
|
|
9
|
+
// 1. **按字素簇编辑**:所有位置计算都走 `graphemes()`。`❤️` 是 2 个 code point、
|
|
10
|
+
// `👨👩👧` 是 5 个,但它们都是**一个**字符 —— 按 code point 删会切出半个字素簇。
|
|
11
|
+
// 2. **纯函数算、hook 只套用**:具体「删哪个词、删到哪」在 `input.ts` /
|
|
12
|
+
// `input-editing.ts` 里(有独立测试),这里只负责「拿到结果 → 更新状态 + 记撤销」。
|
|
13
|
+
import { useRef, useState } from "react";
|
|
14
|
+
import { deleteToLineEnd, deleteToLineStart, deleteWordLeft, deleteWordRight, moveCursorRow, wordLeft, wordRight, } from "./input.js";
|
|
15
|
+
import { deleteToPrevWhitespace, killedText, killAt, popUndo, pushKill, pushUndo, } from "../input-editing.js";
|
|
16
|
+
import { graphemes } from "../text.js";
|
|
17
|
+
import { t } from "../../i18n/index.js";
|
|
18
|
+
export function useInputEditing({ initialText, notify, historySource, restoreImages }) {
|
|
19
|
+
const [input, setInput] = useState(initialText ?? "");
|
|
20
|
+
const [cursor, setCursor] = useState(graphemes(initialText ?? "").length);
|
|
21
|
+
/** 历史游标:-1 = 不在浏览历史(当前是草稿);具体内容每次现取 `historySource()` */
|
|
22
|
+
const historyIndex = useRef(-1);
|
|
23
|
+
/** kill ring:Ctrl+W/U/K 删掉的文本,Ctrl+Y 取回、Alt+Y 循环 */
|
|
24
|
+
const killRingRef = useRef([]);
|
|
25
|
+
const yankIndexRef = useRef(-1);
|
|
26
|
+
/** 编辑撤销栈(Ctrl+_) */
|
|
27
|
+
const undoStackRef = useRef([]);
|
|
28
|
+
/** 暂存区(Ctrl+S) */
|
|
29
|
+
const stashRef = useRef(null);
|
|
30
|
+
const setInputText = (text) => {
|
|
31
|
+
setInput(text);
|
|
32
|
+
setCursor(graphemes(text).length);
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* 取「当前文本 + 钳制后的光标」,所有编辑动作的统一起点。
|
|
36
|
+
*
|
|
37
|
+
* 钳制防的**不是**「cursor 越界」——`cursor` 的每个写入点都已保证落在 `[0, len]`;
|
|
38
|
+
* 防的是**文本与光标不同步**:`input` 与 `cursor` 是两个 state,任何一处只改其一
|
|
39
|
+
* (或将来新增编辑动作忘了同步)都会让 `cp > chars.length` 成立,那时 `slice`
|
|
40
|
+
* 会静默切少、`cp - 1` 会变负。钳一下把后果限制在「本次编辑落点不对」。
|
|
41
|
+
*/
|
|
42
|
+
const clampCursor = () => {
|
|
43
|
+
const chars = graphemes(input);
|
|
44
|
+
return { chars, cp: Math.max(0, Math.min(cursor, chars.length)) };
|
|
45
|
+
};
|
|
46
|
+
const insertAtCursor = (text) => {
|
|
47
|
+
const { chars, cp } = clampCursor();
|
|
48
|
+
setInput(chars.slice(0, cp).join("") + text + chars.slice(cp).join(""));
|
|
49
|
+
setCursor(cp + graphemes(text).length);
|
|
50
|
+
};
|
|
51
|
+
const deleteBeforeCursor = () => {
|
|
52
|
+
const { chars, cp } = clampCursor();
|
|
53
|
+
if (cp === 0)
|
|
54
|
+
return;
|
|
55
|
+
setInput(chars.slice(0, cp - 1).join("") + chars.slice(cp).join(""));
|
|
56
|
+
setCursor(cp - 1);
|
|
57
|
+
};
|
|
58
|
+
const deleteAfterCursor = () => {
|
|
59
|
+
const { chars, cp } = clampCursor();
|
|
60
|
+
if (cp >= chars.length)
|
|
61
|
+
return;
|
|
62
|
+
setInput(chars.slice(0, cp).join("") + chars.slice(cp + 1).join(""));
|
|
63
|
+
};
|
|
64
|
+
/** 套用纯函数算好的「文本 + 光标」结果(无变化则不触发重渲染,也不进撤销栈) */
|
|
65
|
+
const applyEdit = (r) => {
|
|
66
|
+
if (r.text === input && r.cursor === cursor)
|
|
67
|
+
return;
|
|
68
|
+
undoStackRef.current = pushUndo(undoStackRef.current, { text: input, cursor });
|
|
69
|
+
setInput(r.text);
|
|
70
|
+
setCursor(r.cursor);
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* 用一段文本替换 `[start, end)`,光标落到插入文本末尾。
|
|
74
|
+
*
|
|
75
|
+
* 走 `applyEdit`(而不是 `setInput`)是必须的:`@` 补全会把半截路径整段替换掉,
|
|
76
|
+
* 补错了要能 `Ctrl+_` 退回原样。
|
|
77
|
+
*/
|
|
78
|
+
const replaceRange = (start, end, text) => {
|
|
79
|
+
const { chars } = clampCursor();
|
|
80
|
+
const from = Math.max(0, Math.min(start, chars.length));
|
|
81
|
+
const to = Math.max(from, Math.min(end, chars.length));
|
|
82
|
+
applyEdit({
|
|
83
|
+
text: chars.slice(0, from).join("") + text + chars.slice(to).join(""),
|
|
84
|
+
cursor: from + graphemes(text).length,
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
/** 删除类编辑:额外把删掉的文本放进 kill ring(Ctrl+Y 可取回) */
|
|
88
|
+
const applyKill = (r) => {
|
|
89
|
+
if (r.text === input && r.cursor === cursor)
|
|
90
|
+
return;
|
|
91
|
+
killRingRef.current = pushKill(killRingRef.current, killedText(input, r.text));
|
|
92
|
+
yankIndexRef.current = -1;
|
|
93
|
+
applyEdit(r);
|
|
94
|
+
};
|
|
95
|
+
const yank = (advance) => {
|
|
96
|
+
const ring = killRingRef.current;
|
|
97
|
+
if (ring.length === 0)
|
|
98
|
+
return;
|
|
99
|
+
const next = advance ? yankIndexRef.current + 1 : 0;
|
|
100
|
+
// 只用 `killAt` 的 undefined 做越界守卫(环已到头),不再先判一遍 `next >= ring.length`
|
|
101
|
+
const text = killAt(ring, next);
|
|
102
|
+
if (text === undefined)
|
|
103
|
+
return;
|
|
104
|
+
yankIndexRef.current = next;
|
|
105
|
+
insertAtCursor(text);
|
|
106
|
+
};
|
|
107
|
+
const undoEdit = () => {
|
|
108
|
+
const popped = popUndo(undoStackRef.current);
|
|
109
|
+
if (!popped)
|
|
110
|
+
return;
|
|
111
|
+
undoStackRef.current = popped.rest;
|
|
112
|
+
setInput(popped.state.text);
|
|
113
|
+
setCursor(popped.state.cursor);
|
|
114
|
+
};
|
|
115
|
+
const toggleStash = () => {
|
|
116
|
+
if (input.length > 0) {
|
|
117
|
+
stashRef.current = { text: input, cursor };
|
|
118
|
+
setInputText("");
|
|
119
|
+
notify(t("notice.draftSaved"));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const stashed = stashRef.current;
|
|
123
|
+
if (!stashed)
|
|
124
|
+
return;
|
|
125
|
+
stashRef.current = null;
|
|
126
|
+
setInput(stashed.text);
|
|
127
|
+
setCursor(stashed.cursor);
|
|
128
|
+
notify(t("notice.draftRestored"));
|
|
129
|
+
};
|
|
130
|
+
const moveCursor = (delta) => {
|
|
131
|
+
const len = graphemes(input).length;
|
|
132
|
+
setCursor((c) => Math.max(0, Math.min(len, c + delta)));
|
|
133
|
+
};
|
|
134
|
+
const moveCursorByWord = (dir) => {
|
|
135
|
+
setCursor(dir === -1 ? wordLeft(input, cursor) : wordRight(input, cursor));
|
|
136
|
+
};
|
|
137
|
+
const moveCursorToLineStart = () => {
|
|
138
|
+
const { chars, cp } = clampCursor();
|
|
139
|
+
let i = cp;
|
|
140
|
+
while (i > 0 && chars[i - 1] !== "\n")
|
|
141
|
+
i -= 1;
|
|
142
|
+
setCursor(i);
|
|
143
|
+
};
|
|
144
|
+
const moveCursorToLineEnd = () => {
|
|
145
|
+
const { chars, cp } = clampCursor();
|
|
146
|
+
let i = cp;
|
|
147
|
+
while (i < chars.length && chars[i] !== "\n")
|
|
148
|
+
i += 1;
|
|
149
|
+
setCursor(i);
|
|
150
|
+
};
|
|
151
|
+
/** 上下移一行:移得动就移并返回 true,已在边界则返回 false(交给历史) */
|
|
152
|
+
const moveCursorRowBy = (dir, width) => {
|
|
153
|
+
const next = moveCursorRow(input, cursor, width, dir);
|
|
154
|
+
if (next == null)
|
|
155
|
+
return false;
|
|
156
|
+
setCursor(next);
|
|
157
|
+
return true;
|
|
158
|
+
};
|
|
159
|
+
// 历史浏览:「上一条」从最新开始往回走,「下一条」走到底就回到空草稿。
|
|
160
|
+
// 上下两处按键(Ctrl+P/N 与 ↑/↓)共用这一对,不再各写一遍。
|
|
161
|
+
/** 把一条历史草稿放回输入区:文本 + 附件(`↑` 回到带图消息时图也跟着回来) */
|
|
162
|
+
const recall = (entry) => {
|
|
163
|
+
setInputText(entry.text);
|
|
164
|
+
restoreImages(entry.images);
|
|
165
|
+
};
|
|
166
|
+
const historyPrev = () => {
|
|
167
|
+
const entries = historySource();
|
|
168
|
+
if (entries.length === 0)
|
|
169
|
+
return;
|
|
170
|
+
const idx = historyIndex.current < 0 ? entries.length - 1 : Math.max(0, historyIndex.current - 1);
|
|
171
|
+
historyIndex.current = idx;
|
|
172
|
+
recall(entries[idx]);
|
|
173
|
+
};
|
|
174
|
+
const historyNext = () => {
|
|
175
|
+
if (historyIndex.current < 0)
|
|
176
|
+
return;
|
|
177
|
+
const entries = historySource();
|
|
178
|
+
const idx = historyIndex.current + 1;
|
|
179
|
+
if (idx >= entries.length) {
|
|
180
|
+
historyIndex.current = -1;
|
|
181
|
+
setInputText("");
|
|
182
|
+
restoreImages([]);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
historyIndex.current = idx;
|
|
186
|
+
recall(entries[idx]);
|
|
187
|
+
};
|
|
188
|
+
const clearDraft = () => {
|
|
189
|
+
setInput("");
|
|
190
|
+
setCursor(0);
|
|
191
|
+
historyIndex.current = -1;
|
|
192
|
+
};
|
|
193
|
+
return {
|
|
194
|
+
input,
|
|
195
|
+
cursor,
|
|
196
|
+
setInputText,
|
|
197
|
+
insertAtCursor,
|
|
198
|
+
replaceRange,
|
|
199
|
+
deleteBeforeCursor,
|
|
200
|
+
deleteAfterCursor,
|
|
201
|
+
deleteWordBeforeCursor: () => applyKill(deleteWordLeft(input, cursor)),
|
|
202
|
+
deleteWordAfterCursor: () => applyKill(deleteWordRight(input, cursor)),
|
|
203
|
+
deleteToStartOfLine: () => applyKill(deleteToLineStart(input, cursor)),
|
|
204
|
+
deleteToEndOfLine: () => applyKill(deleteToLineEnd(input, cursor)),
|
|
205
|
+
deletePrevWhitespace: () => applyKill(deleteToPrevWhitespace(input, cursor)),
|
|
206
|
+
yank,
|
|
207
|
+
undoEdit,
|
|
208
|
+
toggleStash,
|
|
209
|
+
moveCursor,
|
|
210
|
+
moveCursorToLineStart,
|
|
211
|
+
moveCursorToLineEnd,
|
|
212
|
+
moveCursorUpRow: (width) => moveCursorRowBy(-1, width),
|
|
213
|
+
moveCursorDownRow: (width) => moveCursorRowBy(1, width),
|
|
214
|
+
moveCursorByWord,
|
|
215
|
+
historyPrev,
|
|
216
|
+
historyNext,
|
|
217
|
+
clearDraft,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=use-input-editing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-input-editing.js","sourceRoot":"","sources":["../../../src/tui/screens/use-input-editing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Dispatch, type SetStateAction } from "react";
|
|
2
|
+
import type { SelectItem } from "../components.js";
|
|
3
|
+
/** 确认框请求:`question` 上屏,用户作答后由 `resolve` 结算 */
|
|
4
|
+
export interface ConfirmState {
|
|
5
|
+
question: string;
|
|
6
|
+
resolve: (value: boolean) => void;
|
|
7
|
+
}
|
|
8
|
+
/** 选择器请求:`items` 上屏,用户选中 / 取消后由 `resolve` 结算(取消为 `null`) */
|
|
9
|
+
export interface PickerState {
|
|
10
|
+
title: string;
|
|
11
|
+
items: SelectItem<string>[];
|
|
12
|
+
resolve: (value: string | null) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface ChatOverlays {
|
|
15
|
+
confirmState: ConfirmState | null;
|
|
16
|
+
pickerState: PickerState | null;
|
|
17
|
+
/** 命令层推送覆盖层用(`runCommand` / `chooseHandoffMode` 的入参类型) */
|
|
18
|
+
setConfirmState: Dispatch<SetStateAction<ConfirmState | null>>;
|
|
19
|
+
setPickerState: Dispatch<SetStateAction<PickerState | null>>;
|
|
20
|
+
/** 作答:结算 Promise 并关掉覆盖层(无覆盖层时为空操作) */
|
|
21
|
+
resolveConfirm: (value: boolean) => void;
|
|
22
|
+
resolvePicker: (value: string | null) => void;
|
|
23
|
+
}
|
|
24
|
+
export declare function useChatOverlays(): ChatOverlays;
|
|
25
|
+
//# sourceMappingURL=use-overlays.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-overlays.d.ts","sourceRoot":"","sources":["../../../src/tui/screens/use-overlays.ts"],"names":[],"mappings":"AAWA,OAAO,EAAyB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAClF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,8CAA8C;AAC9C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC;AAED,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;IAC5B,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,0DAA0D;IAC1D,eAAe,EAAE,QAAQ,CAAC,cAAc,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC;IAC/D,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC;IAC7D,sCAAsC;IACtC,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,eAAe,IAAI,YAAY,CAqB9C"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// 覆盖层(确认框 / 选择器)—— 「弹一个、答一个、再关掉」的唯一实现
|
|
2
|
+
//
|
|
3
|
+
// 两种覆盖层共用同一套契约:调用方给一个 `resolve` 回调,拿到一个 Promise,
|
|
4
|
+
// **用户在覆盖层上作答后 Promise 才结算**。这正是命令处理器能写成
|
|
5
|
+
// `const ok = await confirm(...)` 的原因。
|
|
6
|
+
//
|
|
7
|
+
// 从 `chat.tsx` 抽出来的理由:这套 `resolve` 生命周期被埋在 God Component 里,
|
|
8
|
+
// 既没法单测(要从键盘打到命令层才能碰到),也容易被下一个人的 `setState` 写出
|
|
9
|
+
// 「先清状态、后调 resolve」的竞态。抽出来后:
|
|
10
|
+
// · 关状态与调 resolve 在**同一次**函数式更新里完成,不会读到过期状态;
|
|
11
|
+
// · 已经是 `null` 时重复 resolve 是安全空操作(Esc 连按不会炸)。
|
|
12
|
+
import { useCallback, useState } from "react";
|
|
13
|
+
export function useChatOverlays() {
|
|
14
|
+
const [confirmState, setConfirmState] = useState(null);
|
|
15
|
+
const [pickerState, setPickerState] = useState(null);
|
|
16
|
+
// 用函数式更新而不是闭包里的 `confirmState`:连按两下 Esc / 两个键同一帧到达时,
|
|
17
|
+
// 第二次更新仍能看到「已被第一次清掉」的真实状态,不会重复 resolve。
|
|
18
|
+
const resolveConfirm = useCallback((value) => {
|
|
19
|
+
setConfirmState((cs) => {
|
|
20
|
+
cs?.resolve(value);
|
|
21
|
+
return null;
|
|
22
|
+
});
|
|
23
|
+
}, []);
|
|
24
|
+
const resolvePicker = useCallback((value) => {
|
|
25
|
+
setPickerState((ps) => {
|
|
26
|
+
ps?.resolve(value);
|
|
27
|
+
return null;
|
|
28
|
+
});
|
|
29
|
+
}, []);
|
|
30
|
+
return { confirmState, pickerState, setConfirmState, setPickerState, resolveConfirm, resolvePicker };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=use-overlays.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-overlays.js","sourceRoot":"","sources":["../../../src/tui/screens/use-overlays.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,iDAAiD;AACjD,yCAAyC;AACzC,uCAAuC;AACvC,EAAE;AACF,4DAA4D;AAC5D,+CAA+C;AAC/C,6BAA6B;AAC7B,+CAA+C;AAC/C,gDAAgD;AAChD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAsC,MAAM,OAAO,CAAC;AA2BlF,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAsB,IAAI,CAAC,CAAC;IAC5E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IAEzE,qDAAqD;IACrD,wCAAwC;IACxC,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,KAAc,EAAE,EAAE;QACpD,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE;YACrB,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,aAAa,GAAG,WAAW,CAAC,CAAC,KAAoB,EAAE,EAAE;QACzD,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE;YACpB,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;AACvG,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { AppConfig, ReasoningPresets } from "@ai-zen/agents-sdk";
|
|
2
|
+
import { type McpReadResult, type McpScope } from "../../config.js";
|
|
3
|
+
import { type AgentStore } from "../../agents-store.js";
|
|
4
|
+
import type { McpSnapshot, WizardCloseResult, WizardStep } from "../config-wizard/index.js";
|
|
5
|
+
import type { Notice } from "./notice.js";
|
|
6
|
+
export interface WizardHostDeps {
|
|
7
|
+
/** 当前模型 id:`/key` 直达它所用端点的密钥;也是「当前端点是否被改动」的比较基准 */
|
|
8
|
+
modelId: string;
|
|
9
|
+
/** 通知出口(读写失败、变更摘要都从这里出去,不进食转录) */
|
|
10
|
+
notify: (text: string, tone?: Notice["tone"]) => void;
|
|
11
|
+
/** 会话是否已建好(未建好时改配置只能重启) */
|
|
12
|
+
hasSession: () => boolean;
|
|
13
|
+
/** 会话还没建好就改了配置 → 只能重启进程让新配置生效 */
|
|
14
|
+
restart: () => void;
|
|
15
|
+
/** 改了当前端点 / MCP / Agent 定义 / 中断策略 → 重载会话(消息保留) */
|
|
16
|
+
reloadSession: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* 快照读取器。缺省用真实实现;测试注入假实现即可,**不必** `vi.mock` 整个 config 模块
|
|
19
|
+
* ——模块级替换在进程内共享模块时会泄漏到其他测试文件。
|
|
20
|
+
*/
|
|
21
|
+
readers?: {
|
|
22
|
+
readConfig: () => Promise<AppConfig>;
|
|
23
|
+
readMcpConfig: (scope: McpScope) => Promise<McpReadResult>;
|
|
24
|
+
readReasoningPresets: () => Promise<ReasoningPresets>;
|
|
25
|
+
readAgentStore: () => Promise<AgentStore>;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface WizardHost {
|
|
29
|
+
wizardStep: WizardStep | null;
|
|
30
|
+
wizardConfig: AppConfig | null;
|
|
31
|
+
wizardPresets: ReasoningPresets;
|
|
32
|
+
wizardAgents: {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
}[];
|
|
36
|
+
wizardMcp: McpSnapshot | null;
|
|
37
|
+
wizardAgentStore: AgentStore | null;
|
|
38
|
+
/** 打开向导:先读齐快照再接管整屏(读失败则只报错、不进向导) */
|
|
39
|
+
openWizard: (step: WizardStep) => Promise<void>;
|
|
40
|
+
/** `/key`:直达当前模型所用端点的 API Key 编辑步骤 */
|
|
41
|
+
openKeyEditor: () => Promise<void>;
|
|
42
|
+
/** 向导关闭:渲染变更摘要,并让改动生效 */
|
|
43
|
+
closeWizard: (result: WizardCloseResult) => void;
|
|
44
|
+
}
|
|
45
|
+
export declare function useWizardHost({ modelId, notify, hasSession, restart, reloadSession, readers: injected, }: WizardHostDeps): WizardHost;
|
|
46
|
+
//# sourceMappingURL=use-wizard-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-wizard-host.d.ts","sourceRoot":"","sources":["../../../src/tui/screens/use-wizard-host.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAqE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACvI,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACtD,2BAA2B;IAC3B,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,iCAAiC;IACjC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,kDAAkD;IAClD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE;QACR,UAAU,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;QACrC,aAAa,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;QAC3D,oBAAoB,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACtD,cAAc,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;KAC3C,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,SAAS,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,gBAAgB,CAAC;IAChC,YAAY,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,oCAAoC;IACpC,UAAU,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,sCAAsC;IACtC,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,yBAAyB;IACzB,WAAW,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAClD;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,MAAM,EACN,UAAU,EACV,OAAO,EACP,aAAa,EACb,OAAO,EAAE,QAAQ,GAClB,EAAE,cAAc,GAAG,UAAU,CA6G7B"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// 配置向导宿主 —— 「打开向导 / 读齐快照 / 关闭后让改动生效」的唯一实现
|
|
2
|
+
//
|
|
3
|
+
// 从 `chat.tsx` 抽出来的理由:向导本身(`config-wizard/`)是独立状态机,但**宿主**
|
|
4
|
+
// 的活儿散落在对话屏里 —— 6 个 `useState`、3 个入口函数,还要顺手记「当前模型用的是
|
|
5
|
+
// 哪个端点」以便关闭时判断要不要重建会话。这些既不属于「对话」,也没法单测(要一路
|
|
6
|
+
// 从键盘打到向导关闭才能碰到)。
|
|
7
|
+
//
|
|
8
|
+
// 依赖方向是**注入**而非 import 会话:宿主要做的事(通知、重启、重载会话)都通过
|
|
9
|
+
// `WizardHostDeps` 传进来,于是 hook 可以在测试里用假依赖跑完整生命周期。
|
|
10
|
+
import { useRef, useState } from "react";
|
|
11
|
+
import { mcpConfigOrEmpty, readConfig, readMcpConfig, readReasoningPresets } from "../../config.js";
|
|
12
|
+
import { readAgentStore } from "../../agents-store.js";
|
|
13
|
+
import { resolveCredential } from "../../config-editor.js";
|
|
14
|
+
import { t } from "../../i18n/index.js";
|
|
15
|
+
export function useWizardHost({ modelId, notify, hasSession, restart, reloadSession, readers: injected, }) {
|
|
16
|
+
const readers = {
|
|
17
|
+
readConfig,
|
|
18
|
+
readMcpConfig,
|
|
19
|
+
readReasoningPresets,
|
|
20
|
+
readAgentStore,
|
|
21
|
+
...injected,
|
|
22
|
+
};
|
|
23
|
+
const [wizardStep, setWizardStep] = useState(null);
|
|
24
|
+
const [wizardConfig, setWizardConfig] = useState(null);
|
|
25
|
+
const [wizardPresets, setWizardPresets] = useState({});
|
|
26
|
+
const [wizardAgents, setWizardAgents] = useState([]);
|
|
27
|
+
const [wizardMcp, setWizardMcp] = useState(null);
|
|
28
|
+
const [wizardAgentStore, setWizardAgentStore] = useState(null);
|
|
29
|
+
/**
|
|
30
|
+
* 打开向导时当前模型所用的端点 id —— 关闭时据此判断「当前端点有没有被改」。
|
|
31
|
+
*
|
|
32
|
+
* 用 ref 而不是 state:它只在 `openWizard` / `closeWizard` 之间传递,不上屏,
|
|
33
|
+
* 放 state 会多一次无意义渲染。
|
|
34
|
+
*/
|
|
35
|
+
const currentEndpointRef = useRef(null);
|
|
36
|
+
const openWizard = async (step) => {
|
|
37
|
+
try {
|
|
38
|
+
const config = await readers.readConfig();
|
|
39
|
+
currentEndpointRef.current = resolveCredential(config, modelId)?.endpointId ?? null;
|
|
40
|
+
const agentStore = await readers.readAgentStore();
|
|
41
|
+
setWizardConfig(config);
|
|
42
|
+
setWizardPresets(await readers.readReasoningPresets());
|
|
43
|
+
setWizardAgents(agentStore.agents.map((agent) => ({ id: agent.id, name: agent.name || agent.id })));
|
|
44
|
+
setWizardAgentStore(agentStore);
|
|
45
|
+
// 坏文件照样进屏(屏上写明),只把失败原因随之带过去
|
|
46
|
+
const globalMcp = await readers.readMcpConfig("global");
|
|
47
|
+
const projectMcp = await readers.readMcpConfig("project");
|
|
48
|
+
const errors = {};
|
|
49
|
+
if (!globalMcp.ok)
|
|
50
|
+
errors.global = globalMcp.error;
|
|
51
|
+
if (!projectMcp.ok)
|
|
52
|
+
errors.project = projectMcp.error;
|
|
53
|
+
setWizardMcp({
|
|
54
|
+
global: mcpConfigOrEmpty(globalMcp),
|
|
55
|
+
project: mcpConfigOrEmpty(projectMcp),
|
|
56
|
+
...(Object.keys(errors).length ? { errors } : {}),
|
|
57
|
+
});
|
|
58
|
+
setWizardStep(step);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
notify(t("chat.configReadFailed", { error: error?.message ?? error }), "error");
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const openKeyEditor = async () => {
|
|
65
|
+
try {
|
|
66
|
+
const config = await readers.readConfig();
|
|
67
|
+
const credential = resolveCredential(config, modelId);
|
|
68
|
+
if (!credential) {
|
|
69
|
+
notify(t("chat.modelNoEndpoint", { id: modelId }), "error");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
currentEndpointRef.current = credential.endpointId;
|
|
73
|
+
setWizardConfig(config);
|
|
74
|
+
setWizardStep({ kind: "edit", field: "apiKey", endpointId: credential.endpointId });
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
notify(t("chat.configReadFailed", { error: error?.message ?? error }), "error");
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
/** 向导关闭:渲染变更摘要;若改到当前端点 / MCP / Agent 定义则重建会话(消息保留) */
|
|
81
|
+
const closeWizard = (result) => {
|
|
82
|
+
setWizardStep(null);
|
|
83
|
+
setWizardConfig(null);
|
|
84
|
+
setWizardMcp(null);
|
|
85
|
+
setWizardAgentStore(null);
|
|
86
|
+
// 同一批摘要合成**一条**(多行):既能全部显示,又只占通知队列的一个槽位。
|
|
87
|
+
// 逐条 push 在单槽时代只剩最后一条,在队列时代则会挤掉更早的进度提示。
|
|
88
|
+
const { summary } = result;
|
|
89
|
+
if (summary.length === 1) {
|
|
90
|
+
notify(t("chat.configUpdated", { line: summary[0] }));
|
|
91
|
+
}
|
|
92
|
+
else if (summary.length > 1) {
|
|
93
|
+
// 子项缩进 = 一个汉字宽度(两个半角空格),不加 `·` 之类的项目符号:
|
|
94
|
+
// 通知正文本身就左对齐于行首,子项只需要一点层级差,符号是多余装饰。
|
|
95
|
+
notify(t("chat.configUpdatedMulti", { lines: summary.map((line) => ` ${line}`).join("\n") }));
|
|
96
|
+
}
|
|
97
|
+
if (!result.dirty)
|
|
98
|
+
return;
|
|
99
|
+
// 会话都没建好 → 只能重启让新配置生效。
|
|
100
|
+
if (!hasSession()) {
|
|
101
|
+
restart();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// 只有「当前端点 / MCP / Agent 定义 / 建 Agent 时才读的配置(中断策略)」变了
|
|
105
|
+
// 才需要重建会话;改的是别的模型、别的端点的参数,当前会话不受影响,不该白重连一次。
|
|
106
|
+
const endpointChanged = !!currentEndpointRef.current && result.changedEndpointIds.includes(currentEndpointRef.current);
|
|
107
|
+
if (endpointChanged || result.mcpChanged || result.agentsChanged || result.sessionOptionsChanged) {
|
|
108
|
+
reloadSession();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
wizardStep,
|
|
113
|
+
wizardConfig,
|
|
114
|
+
wizardPresets,
|
|
115
|
+
wizardAgents,
|
|
116
|
+
wizardMcp,
|
|
117
|
+
wizardAgentStore,
|
|
118
|
+
openWizard,
|
|
119
|
+
openKeyEditor,
|
|
120
|
+
closeWizard,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=use-wizard-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-wizard-host.js","sourceRoot":"","sources":["../../../src/tui/screens/use-wizard-host.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,2DAA2D;AAC3D,qDAAqD;AACrD,2CAA2C;AAC3C,kBAAkB;AAClB,EAAE;AACF,gDAAgD;AAChD,kDAAkD;AAClD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,aAAa,EAAE,oBAAoB,EAAqC,MAAM,iBAAiB,CAAC;AACvI,OAAO,EAAE,cAAc,EAAmB,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAC;AAyCxC,MAAM,UAAU,aAAa,CAAC,EAC5B,OAAO,EACP,MAAM,EACN,UAAU,EACV,OAAO,EACP,aAAa,EACb,OAAO,EAAE,QAAQ,GACF;IACf,MAAM,OAAO,GAAG;QACd,UAAU;QACV,aAAa;QACb,oBAAoB;QACpB,cAAc;QACd,GAAG,QAAQ;KACZ,CAAC;IACF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAoB,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAmB,IAAI,CAAC,CAAC;IACzE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAmB,EAAE,CAAC,CAAC;IACzE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAiC,EAAE,CAAC,CAAC;IACrF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IACrE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAoB,IAAI,CAAC,CAAC;IAClF;;;;;OAKG;IACH,MAAM,kBAAkB,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IAEvD,MAAM,UAAU,GAAG,KAAK,EAAE,IAAgB,EAAE,EAAE;QAC5C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;YAC1C,kBAAkB,CAAC,OAAO,GAAG,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,IAAI,IAAI,CAAC;YACpF,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC;YAClD,eAAe,CAAC,MAAM,CAAC,CAAC;YACxB,gBAAgB,CAAC,MAAM,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;YACvD,eAAe,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;YACpG,mBAAmB,CAAC,UAAU,CAAC,CAAC;YAChC,4BAA4B;YAC5B,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACxD,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAsC,EAAE,CAAC;YACrD,IAAI,CAAC,SAAS,CAAC,EAAE;gBAAE,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC;YACnD,IAAI,CAAC,UAAU,CAAC,EAAE;gBAAE,MAAM,CAAC,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC;YACtD,YAAY,CAAC;gBACX,MAAM,EAAE,gBAAgB,CAAC,SAAS,CAAC;gBACnC,OAAO,EAAE,gBAAgB,CAAC,UAAU,CAAC;gBACrC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAClD,CAAC,CAAC;YACH,aAAa,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,CAAC,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;QAC/B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;YAC1C,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACtD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,CAAC,CAAC,CAAC,sBAAsB,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC5D,OAAO;YACT,CAAC;YACD,kBAAkB,CAAC,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC;YACnD,eAAe,CAAC,MAAM,CAAC,CAAC;YACxB,aAAa,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;QACtF,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,CAAC,CAAC,uBAAuB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,CAAC;IACH,CAAC,CAAC;IAEF,sDAAsD;IACtD,MAAM,WAAW,GAAG,CAAC,MAAyB,EAAE,EAAE;QAChD,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,yCAAyC;QACzC,wCAAwC;QACxC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;QAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,CAAC,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;aAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,wCAAwC;YACxC,oCAAoC;YACpC,MAAM,CACJ,CAAC,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CACvF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK;YAAE,OAAO;QAE1B,uBAAuB;QACvB,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,qDAAqD;QACrD,4CAA4C;QAC5C,MAAM,eAAe,GACnB,CAAC,CAAC,kBAAkB,CAAC,OAAO,IAAI,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACjG,IAAI,eAAe,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,qBAAqB,EAAE,CAAC;YACjG,aAAa,EAAE,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,UAAU;QACV,YAAY;QACZ,aAAa;QACb,YAAY;QACZ,SAAS;QACT,gBAAgB;QAChB,UAAU;QACV,aAAa;QACb,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type RLine } from "./lines.js";
|
|
2
|
+
/**
|
|
3
|
+
* 品牌区各行 —— 纯函数,不依赖 Ink(渲染交给 `LineView`)。
|
|
4
|
+
*
|
|
5
|
+
* 宽度取 `pickLogo()` 的判据:能放下宽版 6 行 logo 就用宽版,否则退化成单行
|
|
6
|
+
* `◢ AI · ZEN ◣`。整块按终端宽度居中。所有行都带 `spans`(颜色逐段给),
|
|
7
|
+
* 因此 `kind` 只取中性的 `content`。
|
|
8
|
+
*/
|
|
9
|
+
export declare function welcomeLines({ columns }: {
|
|
10
|
+
columns: number;
|
|
11
|
+
}): RLine[];
|
|
12
|
+
//# sourceMappingURL=welcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../../src/tui/screens/welcome.ts"],"names":[],"mappings":"AASA,OAAO,EAAY,KAAK,KAAK,EAAa,MAAM,YAAY,CAAC;AAE7D;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,KAAK,EAAE,CAmBtE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// 欢迎块 —— 空对话时对话区顶部的品牌区(logo + 标语 + 版本)
|
|
2
|
+
//
|
|
3
|
+
// 这一块曾经是启动时的全屏开屏动画(splash):显现 + 扫光 + 停 1.1s 才进对话,
|
|
4
|
+
// 每次启动强阻塞约 1.8s。现在改为**对话区的普通内容**:不阻塞、随消息自然上滚、
|
|
5
|
+
// 滚回来还能看到。渐变相位固定为 0(静态),不持有任何定时器。
|
|
6
|
+
import { CLI_VERSION, CORE_VERSION, SDK_VERSION } from "../../version.js";
|
|
7
|
+
import { t } from "../../i18n/index.js";
|
|
8
|
+
import { displayWidth } from "../text.js";
|
|
9
|
+
import { logoGradientColors, pickLogo, theme } from "../theme.js";
|
|
10
|
+
import { spanLine } from "./lines.js";
|
|
11
|
+
/**
|
|
12
|
+
* 品牌区各行 —— 纯函数,不依赖 Ink(渲染交给 `LineView`)。
|
|
13
|
+
*
|
|
14
|
+
* 宽度取 `pickLogo()` 的判据:能放下宽版 6 行 logo 就用宽版,否则退化成单行
|
|
15
|
+
* `◢ AI · ZEN ◣`。整块按终端宽度居中。所有行都带 `spans`(颜色逐段给),
|
|
16
|
+
* 因此 `kind` 只取中性的 `content`。
|
|
17
|
+
*/
|
|
18
|
+
export function welcomeLines({ columns }) {
|
|
19
|
+
const logo = pickLogo(columns);
|
|
20
|
+
const colors = logoGradientColors(logo, 0);
|
|
21
|
+
const tagline = t("welcome.tagline");
|
|
22
|
+
const versions = `v${CLI_VERSION} · sdk ${SDK_VERSION} · core ${CORE_VERSION}`;
|
|
23
|
+
/** 逐行居中(不按最宽行对齐 —— 否则 logo 会因版本行更长而看起来偏左) */
|
|
24
|
+
const center = (text) => " ".repeat(Math.max(0, Math.floor((columns - displayWidth(text)) / 2)));
|
|
25
|
+
const lines = logo.map((line, i) => {
|
|
26
|
+
const spans = [{ text: center(line) }];
|
|
27
|
+
for (const [x, ch] of [...line].entries())
|
|
28
|
+
spans.push({ text: ch, color: colors[i]?.[x] });
|
|
29
|
+
return spanLine(`welcome-logo-${i}`, "content", spans);
|
|
30
|
+
});
|
|
31
|
+
lines.push({ key: "welcome-gap", kind: "gap", text: "" });
|
|
32
|
+
lines.push(spanLine("welcome-tagline", "content", [{ text: center(tagline) }, { text: tagline, color: theme.accent }]));
|
|
33
|
+
lines.push(spanLine("welcome-versions", "content", [{ text: center(versions) }, { text: versions, color: theme.dim }]));
|
|
34
|
+
return lines;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=welcome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../../src/tui/screens/welcome.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,EAAE;AACF,kDAAkD;AAClD,8CAA8C;AAC9C,kCAAkC;AAClC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,qBAAqB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAyB,MAAM,YAAY,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,OAAO,EAAuB;IAC3D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,WAAW,UAAU,WAAW,WAAW,YAAY,EAAE,CAAC;IAE/E,6CAA6C;IAC7C,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEzG,MAAM,KAAK,GAAY,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAW,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,KAAK,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3F,OAAO,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1D,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACxH,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACxH,OAAO,KAAK,CAAC;AACf,CAAC"}
|