@ai-zen/cli 1.0.0-alpha.3 → 1.0.0-alpha.31
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 +930 -0
- package/LICENSE +21 -0
- package/README.md +135 -30
- package/README.zh.md +135 -30
- 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 +247 -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 +251 -0
- package/dist/i18n/zh.js.map +1 -0
- package/dist/index.js +72 -25
- 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 +177 -57
- package/dist/tui/chat-session.d.ts.map +1 -1
- package/dist/tui/chat-session.js +364 -126
- package/dist/tui/chat-session.js.map +1 -1
- package/dist/tui/components.d.ts +113 -7
- 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 +18 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +107 -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 +82 -3
- package/dist/tui/screens/chat-commands.d.ts.map +1 -1
- package/dist/tui/screens/chat-commands.js +688 -160
- package/dist/tui/screens/chat-commands.js.map +1 -1
- package/dist/tui/screens/chat.d.ts +57 -5
- package/dist/tui/screens/chat.d.ts.map +1 -1
- package/dist/tui/screens/chat.js +799 -304
- 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 +47 -0
- package/dist/tui/screens/frame-buffer.d.ts.map +1 -0
- package/dist/tui/screens/frame-buffer.js +78 -0
- package/dist/tui/screens/frame-buffer.js.map +1 -0
- 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 +11 -9
- package/dist/tui/screens/index.d.ts.map +1 -1
- package/dist/tui/screens/index.js +9 -8
- 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 +42 -3
- package/dist/tui/screens/layout.d.ts.map +1 -1
- package/dist/tui/screens/layout.js +43 -13
- package/dist/tui/screens/layout.js.map +1 -1
- package/dist/tui/screens/lines.d.ts +6 -36
- package/dist/tui/screens/lines.d.ts.map +1 -1
- package/dist/tui/screens/lines.js +8 -71
- package/dist/tui/screens/lines.js.map +1 -1
- package/dist/tui/screens/messages-view.d.ts +29 -0
- package/dist/tui/screens/messages-view.d.ts.map +1 -0
- package/dist/tui/screens/messages-view.js +162 -0
- package/dist/tui/screens/messages-view.js.map +1 -0
- 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 +66 -0
- package/dist/tui/screens/notice.d.ts.map +1 -0
- package/dist/tui/screens/notice.js +106 -0
- package/dist/tui/screens/notice.js.map +1 -0
- 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 +2 -4
- package/dist/tui/screens/render.d.ts.map +1 -1
- package/dist/tui/screens/render.js +19 -50
- package/dist/tui/screens/render.js.map +1 -1
- package/dist/tui/screens/splash.d.ts +1 -1
- package/dist/tui/screens/splash.d.ts.map +1 -1
- package/dist/tui/screens/splash.js +12 -3
- package/dist/tui/screens/splash.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/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 +27 -7
- package/dist/tui/text.d.ts.map +1 -1
- package/dist/tui/text.js +116 -38
- 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 +5 -4
- 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 -59
- package/dist/migration-service.js.map +0 -1
- package/dist/tui/screens/state.d.ts +0 -30
- package/dist/tui/screens/state.d.ts.map +0 -1
- package/dist/tui/screens/state.js +0 -100
- package/dist/tui/screens/state.js.map +0 -1
|
@@ -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":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 状态栏的折行 —— 输入是「按优先级排好的信息块」,输出是「确定的若干行」
|
|
3
|
+
*
|
|
4
|
+
* 为什么不用 Ink 自己的 wrap:状态栏高度必须是**确定值**,`computeChatLayout` 要靠它
|
|
5
|
+
* 算出对话区还能占几行(整帧高度恒等于终端行数,输入框才吸得住底)。让 Ink 在渲染时
|
|
6
|
+
* 折行,行数只有渲染完才知道,布局预算就会算错——轻则顶部留白多一行,重则把输入框
|
|
7
|
+
* 顶出屏幕。所以这里先在纯逻辑里折好,渲染层只负责按行铺颜色。
|
|
8
|
+
*
|
|
9
|
+
* 折行以「块」为单位(见 `packSegments`):身份、用量、快捷键各是一块,窄屏时整块
|
|
10
|
+
* 顺延到下一行,而不是把一块劈成两半——也不再用 `justify-content: space-between` 把
|
|
11
|
+
* 两侧各切一半(左边「思考 高」被吃掉、右边提示只剩半截)。
|
|
12
|
+
*/
|
|
13
|
+
/** 一段带样式的文本(颜色由调用方给,这里只管切分) */
|
|
14
|
+
export interface StatusSegment {
|
|
15
|
+
text: string;
|
|
16
|
+
color?: string;
|
|
17
|
+
bold?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 把片段流按显示宽度折成若干行。
|
|
21
|
+
*
|
|
22
|
+
* 断行策略与 `wrapText` 一致:优先在**空格**处断(英文单词不被劈开),没有空格可断
|
|
23
|
+
* 时按字符硬断(CJK 本来就能任意断行)。折行后的行首空格会被吃掉,避免出现
|
|
24
|
+
* 「第二行无故缩进两格」。
|
|
25
|
+
*/
|
|
26
|
+
export declare function wrapSegments(segments: StatusSegment[], width: number): StatusSegment[][];
|
|
27
|
+
/** 片段流的总显示宽度(宽字符算 2 列) */
|
|
28
|
+
export declare function segmentsWidth(segments: StatusSegment[]): number;
|
|
29
|
+
/**
|
|
30
|
+
* 以**块**为单位装行:能塞进当前行剩余宽度就并排(用 `separator` 连起来),
|
|
31
|
+
* 塞不下就整块挪到下一行;只有单块本身就比一整行还宽时,才退化成块内折行
|
|
32
|
+
* (`wrapSegments`),此时优先在空格 / CJK 边界断,尽量不劈开英文单词。
|
|
33
|
+
*
|
|
34
|
+
* 这样「换行时一块占一行」是默认行为:块是原子的排版单位,行的边界只会落在块边界上。
|
|
35
|
+
*/
|
|
36
|
+
export declare function packSegments(blocks: StatusSegment[][], width: number, separator?: StatusSegment[]): StatusSegment[][];
|
|
37
|
+
//# sourceMappingURL=status-segments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-segments.d.ts","sourceRoot":"","sources":["../../src/tui/status-segments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,+BAA+B;AAC/B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAwCD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,EAAE,CAyDxF;AAED,0BAA0B;AAC1B,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,MAAM,CAM/D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,aAAa,EAAE,EAAE,EACzB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,aAAa,EAAsB,GAC7C,aAAa,EAAE,EAAE,CAwCnB"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 状态栏的折行 —— 输入是「按优先级排好的信息块」,输出是「确定的若干行」
|
|
3
|
+
*
|
|
4
|
+
* 为什么不用 Ink 自己的 wrap:状态栏高度必须是**确定值**,`computeChatLayout` 要靠它
|
|
5
|
+
* 算出对话区还能占几行(整帧高度恒等于终端行数,输入框才吸得住底)。让 Ink 在渲染时
|
|
6
|
+
* 折行,行数只有渲染完才知道,布局预算就会算错——轻则顶部留白多一行,重则把输入框
|
|
7
|
+
* 顶出屏幕。所以这里先在纯逻辑里折好,渲染层只负责按行铺颜色。
|
|
8
|
+
*
|
|
9
|
+
* 折行以「块」为单位(见 `packSegments`):身份、用量、快捷键各是一块,窄屏时整块
|
|
10
|
+
* 顺延到下一行,而不是把一块劈成两半——也不再用 `justify-content: space-between` 把
|
|
11
|
+
* 两侧各切一半(左边「思考 高」被吃掉、右边提示只剩半截)。
|
|
12
|
+
*/
|
|
13
|
+
import { clusterWidth, graphemes } from "./text.js";
|
|
14
|
+
function toChars(segments) {
|
|
15
|
+
const chars = [];
|
|
16
|
+
for (const segment of segments) {
|
|
17
|
+
// 按**字素簇**切,不按 code point:`✌️`(VS16)是两个 code point 但占 2 列,
|
|
18
|
+
// 逐 code point 累加会算成 1 列 → 状态栏行超宽 → Ink 二次折行 → 帧高多一行。
|
|
19
|
+
for (const ch of graphemes(segment.text)) {
|
|
20
|
+
chars.push({ ch, color: segment.color, bold: segment.bold, width: clusterWidth(ch) });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return chars;
|
|
24
|
+
}
|
|
25
|
+
/** 连续同色同粗细的字符合并回一个片段 */
|
|
26
|
+
function toSegments(chars) {
|
|
27
|
+
const segments = [];
|
|
28
|
+
for (const char of chars) {
|
|
29
|
+
const last = segments[segments.length - 1];
|
|
30
|
+
if (last && last.color === char.color && last.bold === char.bold) {
|
|
31
|
+
last.text += char.ch;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
segments.push({ text: char.ch, color: char.color, bold: char.bold });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return segments;
|
|
38
|
+
}
|
|
39
|
+
/** 行尾空格没有意义(会视觉上「多出一截」),折行前后都裁掉 */
|
|
40
|
+
function trimTail(line) {
|
|
41
|
+
while (line.length > 0 && line[line.length - 1].ch === " ")
|
|
42
|
+
line.pop();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 把片段流按显示宽度折成若干行。
|
|
46
|
+
*
|
|
47
|
+
* 断行策略与 `wrapText` 一致:优先在**空格**处断(英文单词不被劈开),没有空格可断
|
|
48
|
+
* 时按字符硬断(CJK 本来就能任意断行)。折行后的行首空格会被吃掉,避免出现
|
|
49
|
+
* 「第二行无故缩进两格」。
|
|
50
|
+
*/
|
|
51
|
+
export function wrapSegments(segments, width) {
|
|
52
|
+
const limit = Math.max(1, width);
|
|
53
|
+
const chars = toChars(segments);
|
|
54
|
+
const lines = [];
|
|
55
|
+
let line = [];
|
|
56
|
+
let lineWidth = 0;
|
|
57
|
+
for (let index = 0; index < chars.length; index += 1) {
|
|
58
|
+
const char = chars[index];
|
|
59
|
+
// 行已满且下一个正好是空格:直接断行并把这个空格丢掉,而不是往回找上一处空格
|
|
60
|
+
// (否则会把已经排好的「aaaa bbbb」硬拆成「aaaa」+「bbbb」,白白浪费半行)
|
|
61
|
+
if (char.ch === " " && lineWidth + char.width > limit && line.length > 0) {
|
|
62
|
+
trimTail(line);
|
|
63
|
+
lines.push(line);
|
|
64
|
+
line = [];
|
|
65
|
+
lineWidth = 0;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (lineWidth + char.width > limit && line.length > 0) {
|
|
69
|
+
// 当前行最后一个空格的位置:能在此断就在此断,把尾巴挪到下一行
|
|
70
|
+
let spaceAt = -1;
|
|
71
|
+
for (let i = line.length - 1; i > 0; i -= 1) {
|
|
72
|
+
if (line[i].ch === " ") {
|
|
73
|
+
spaceAt = i;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (spaceAt > 0) {
|
|
78
|
+
const carry = line.slice(spaceAt + 1);
|
|
79
|
+
line = line.slice(0, spaceAt);
|
|
80
|
+
trimTail(line);
|
|
81
|
+
lines.push(line);
|
|
82
|
+
line = carry;
|
|
83
|
+
lineWidth = carry.reduce((sum, item) => sum + item.width, 0);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
trimTail(line);
|
|
87
|
+
lines.push(line);
|
|
88
|
+
line = [];
|
|
89
|
+
lineWidth = 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (line.length === 0) {
|
|
93
|
+
if (char.ch === " ")
|
|
94
|
+
continue; // 行首不吃空格
|
|
95
|
+
// 行首的孤儿分隔符(`·`)是折行切出来的,留在开头只会变成「· ⚡ 47 tok/s」,
|
|
96
|
+
// 难看且无意义(换行本身已表达分隔),连同其后的空格一并丢掉。
|
|
97
|
+
if (char.ch === "·" && index > 0) {
|
|
98
|
+
while (index + 1 < chars.length && chars[index + 1].ch === " ")
|
|
99
|
+
index += 1;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
line.push(char);
|
|
104
|
+
lineWidth += char.width;
|
|
105
|
+
}
|
|
106
|
+
trimTail(line);
|
|
107
|
+
lines.push(line);
|
|
108
|
+
return lines.map(toSegments);
|
|
109
|
+
}
|
|
110
|
+
/** 片段流的总显示宽度(宽字符算 2 列) */
|
|
111
|
+
export function segmentsWidth(segments) {
|
|
112
|
+
let width = 0;
|
|
113
|
+
for (const segment of segments) {
|
|
114
|
+
for (const ch of graphemes(segment.text))
|
|
115
|
+
width += clusterWidth(ch);
|
|
116
|
+
}
|
|
117
|
+
return width;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 以**块**为单位装行:能塞进当前行剩余宽度就并排(用 `separator` 连起来),
|
|
121
|
+
* 塞不下就整块挪到下一行;只有单块本身就比一整行还宽时,才退化成块内折行
|
|
122
|
+
* (`wrapSegments`),此时优先在空格 / CJK 边界断,尽量不劈开英文单词。
|
|
123
|
+
*
|
|
124
|
+
* 这样「换行时一块占一行」是默认行为:块是原子的排版单位,行的边界只会落在块边界上。
|
|
125
|
+
*/
|
|
126
|
+
export function packSegments(blocks, width, separator = [{ text: " · " }]) {
|
|
127
|
+
const limit = Math.max(1, width);
|
|
128
|
+
const separatorWidth = segmentsWidth(separator);
|
|
129
|
+
const lines = [];
|
|
130
|
+
let line = [];
|
|
131
|
+
let lineWidth = 0;
|
|
132
|
+
const flush = () => {
|
|
133
|
+
if (line.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
lines.push(line);
|
|
136
|
+
line = [];
|
|
137
|
+
lineWidth = 0;
|
|
138
|
+
};
|
|
139
|
+
for (const block of blocks) {
|
|
140
|
+
const blockWidth = segmentsWidth(block);
|
|
141
|
+
if (blockWidth === 0)
|
|
142
|
+
continue; // 空块(如本轮没有速率)不占位,也不留分隔符
|
|
143
|
+
if (line.length > 0) {
|
|
144
|
+
if (lineWidth + separatorWidth + blockWidth <= limit) {
|
|
145
|
+
line = [...line, ...separator, ...block];
|
|
146
|
+
lineWidth += separatorWidth + blockWidth;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
flush();
|
|
150
|
+
}
|
|
151
|
+
if (blockWidth <= limit) {
|
|
152
|
+
line = [...block];
|
|
153
|
+
lineWidth = blockWidth;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
// 单块超一整行:块内折行兜底,尾巴留在 `line` 上等着接下一块
|
|
157
|
+
const chunks = wrapSegments(block, limit);
|
|
158
|
+
const tail = chunks.pop();
|
|
159
|
+
lines.push(...chunks);
|
|
160
|
+
line = tail;
|
|
161
|
+
lineWidth = segmentsWidth(tail);
|
|
162
|
+
}
|
|
163
|
+
flush();
|
|
164
|
+
return lines.length > 0 ? lines : [[]];
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=status-segments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-segments.js","sourceRoot":"","sources":["../../src/tui/status-segments.ts"],"names":[],"mappings":"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"}
|
package/dist/tui/text.d.ts
CHANGED
|
@@ -4,41 +4,56 @@
|
|
|
4
4
|
* 从 `screens.tsx` 中抽出,供对话屏、凭据设置屏、配置中心共用,
|
|
5
5
|
* 避免 `screens.tsx ↔ config-wizard.tsx` 相互 import 形成循环依赖。
|
|
6
6
|
*/
|
|
7
|
-
/**
|
|
7
|
+
/** 终端显示宽度(按字素簇,与 Ink 的排版完全一致) */
|
|
8
8
|
export declare function displayWidth(text: string): number;
|
|
9
|
+
/** 单个字素簇的显示宽度(结果带缓存) */
|
|
10
|
+
export declare function clusterWidth(cluster: string): number;
|
|
11
|
+
export declare function graphemes(text: string): string[];
|
|
9
12
|
/**
|
|
10
13
|
* 按显示宽度把文本折成多行(保留显式换行)。
|
|
11
|
-
* 拉丁文优先在空格处断行,CJK /
|
|
14
|
+
* 拉丁文优先在空格处断行,CJK / 超长词按**字素簇**硬断;保证每行显示宽度 ≤ limit。
|
|
12
15
|
*/
|
|
13
16
|
export declare function wrapText(text: string, limit: number): string[];
|
|
14
17
|
/** 带光标位置的输入区折行结果 */
|
|
15
18
|
export interface InputLayout {
|
|
16
19
|
/** 折行后的各行文本(不含提示符) */
|
|
17
20
|
lines: string[];
|
|
21
|
+
/**
|
|
22
|
+
* 每行首字符的**字素簇下标**(与 `lines` 同长)。
|
|
23
|
+
*
|
|
24
|
+
* 上下移动光标要靠它把「第几行 + 行内第几列」换算回文本下标;不能把 `lines` 长度
|
|
25
|
+
* 相加得出 —— 软折行不占字符,硬换行(`\n`)才占一个。
|
|
26
|
+
*/
|
|
27
|
+
rowStarts: number[];
|
|
18
28
|
/** 光标所在行(0 起始) */
|
|
19
29
|
cursorRow: number;
|
|
20
|
-
/**
|
|
30
|
+
/** 光标在该行内的字符偏移(**字素簇**计,不是 code point) */
|
|
21
31
|
cursorCol: number;
|
|
22
32
|
}
|
|
23
33
|
/**
|
|
24
|
-
* 把输入文本按显示宽度折行,并定位光标(`cursor`
|
|
25
|
-
*
|
|
34
|
+
* 把输入文本按显示宽度折行,并定位光标(`cursor` 为**字素簇**索引)。
|
|
35
|
+
* 折行采用逐簇硬断(不做空格优先),以保证光标映射精确、支持跨行编辑。
|
|
26
36
|
*/
|
|
27
37
|
export declare function layoutInput(text: string, cursor: number, width: number): InputLayout;
|
|
28
38
|
/** 单行输入左侧留白:Box paddingX(1) + 提示符 `❯ `(宽 2) */
|
|
29
39
|
export declare const INPUT_PREFIX_WIDTH = 3;
|
|
30
40
|
/**
|
|
31
|
-
*
|
|
41
|
+
* 判断一段输入是否为「终端上报序列」而非用户输入。
|
|
32
42
|
*
|
|
33
43
|
* 典型来源:
|
|
34
44
|
* - Kitty 键盘协议查询的应答:`CSI ? <flags> u`(Ink 开启 `kittyKeyboard` 时会发 `CSI ? u`);
|
|
35
45
|
* - 光标位置报告(CPR):`CSI <row>;<col> R`;
|
|
36
|
-
* - 设备状态报告:`CSI ? <n> n
|
|
46
|
+
* - 设备状态报告:`CSI ? <n> n`;
|
|
47
|
+
* - 鼠标上报(SGR):`CSI < b ; x ; y M`——滚轮 / 点击 / 拖拽,见 `mouse.ts`。
|
|
37
48
|
*
|
|
38
49
|
* 这类序列本应由 Ink 的解析器整体吞掉。但当它被**拆包**时(前导 ESC 被 Ink 的
|
|
39
50
|
* 「待定转义刷新定时器」当作一次独立的 Escape 键消费),残留在后一个 chunk 里的
|
|
40
51
|
* `[?0u` 会退化成普通文本并被当作输入插入输入框(实测重现)。此处做一层护栏;
|
|
41
52
|
* 根因(不再向终端发查询)已在渲染选项里关闭。
|
|
53
|
+
*
|
|
54
|
+
* 鼠标上报是**主动开启**的(`src/tui/mouse.ts`),且 Ink 会把整条序列当作 `char`
|
|
55
|
+
* 交给 `useInput`,所以这里必须兜住——否则滚一下就往输入框里插一段 `[<64;10;5M`。
|
|
56
|
+
* 注意:需要读滚轮的屏(对话屏)必须**在处理完滚轮之后**再调用本函数。
|
|
42
57
|
*/
|
|
43
58
|
export declare function isTerminalReply(sequence: string): boolean;
|
|
44
59
|
/**
|
|
@@ -68,4 +83,9 @@ export declare function usableFrameRows(terminalRows: number): number;
|
|
|
68
83
|
* 传入行数超过一帧时返回 0(由调用方负责限制内容行数)。
|
|
69
84
|
*/
|
|
70
85
|
export declare function bottomPadding(terminalRows: number, contentLines: number): number;
|
|
86
|
+
/**
|
|
87
|
+
* 去掉 CwdTrackerPlugin 追加在用户消息末尾的工作目录提示。
|
|
88
|
+
* 该提示是喂给模型的上下文,不该显示给用户。
|
|
89
|
+
*/
|
|
90
|
+
export declare function stripCwdNote(text: string): string;
|
|
71
91
|
//# sourceMappingURL=text.d.ts.map
|
package/dist/tui/text.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/tui/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/tui/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0BH,iCAAiC;AACjC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,wBAAwB;AACxB,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQpD;AAuCD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAOhD;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA8B9D;AAID,oBAAoB;AACpB,MAAM,WAAW,WAAW;IAC1B,sBAAsB;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAoDpF;AAED,+CAA+C;AAC/C,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAY3D;AAID;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD"}
|