@ai-zen/cli 1.0.0-alpha.20 → 1.0.0-alpha.22
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 +158 -0
- package/README.md +43 -17
- package/README.zh.md +43 -17
- package/dist/agent-creator.d.ts.map +1 -1
- package/dist/agent-creator.js +32 -10
- 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 +6 -1
- package/dist/agents-store.js.map +1 -1
- package/dist/auto-migrate-confirm.d.ts.map +1 -1
- package/dist/auto-migrate-confirm.js +2 -1
- package/dist/auto-migrate-confirm.js.map +1 -1
- package/dist/config-editor.d.ts +9 -1
- package/dist/config-editor.d.ts.map +1 -1
- package/dist/config-editor.js +30 -19
- package/dist/config-editor.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +29 -13
- package/dist/config.js.map +1 -1
- package/dist/conversation-commands/registry.d.ts +123 -4
- package/dist/conversation-commands/registry.d.ts.map +1 -1
- package/dist/conversation-commands/registry.js +92 -17
- package/dist/conversation-commands/registry.js.map +1 -1
- package/dist/conversation-persist-plugin.d.ts.map +1 -1
- package/dist/conversation-persist-plugin.js +6 -14
- package/dist/conversation-persist-plugin.js.map +1 -1
- package/dist/conversation-repository.d.ts +68 -14
- package/dist/conversation-repository.d.ts.map +1 -1
- package/dist/conversation-repository.js +81 -23
- package/dist/conversation-repository.js.map +1 -1
- package/dist/cwd-tracker-plugin.d.ts.map +1 -1
- package/dist/cwd-tracker-plugin.js +6 -2
- 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.map +1 -1
- package/dist/handoff-service.js +22 -19
- package/dist/handoff-service.js.map +1 -1
- 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 +290 -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 +224 -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 +34 -0
- package/dist/i18n/preferences.d.ts.map +1 -0
- package/dist/i18n/preferences.js +69 -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 +293 -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 +228 -0
- package/dist/i18n/zh.js.map +1 -0
- package/dist/index.js +41 -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.map +1 -1
- package/dist/model-switch.js +5 -4
- package/dist/model-switch.js.map +1 -1
- package/dist/reasoning-effort.d.ts +23 -4
- package/dist/reasoning-effort.d.ts.map +1 -1
- package/dist/reasoning-effort.js +51 -24
- package/dist/reasoning-effort.js.map +1 -1
- package/dist/sdk-log.d.ts +23 -16
- package/dist/sdk-log.d.ts.map +1 -1
- package/dist/sdk-log.js +43 -19
- package/dist/sdk-log.js.map +1 -1
- package/dist/stdio-runner.d.ts.map +1 -1
- package/dist/stdio-runner.js +19 -19
- package/dist/stdio-runner.js.map +1 -1
- package/dist/tui/chat-session.d.ts +27 -0
- package/dist/tui/chat-session.d.ts.map +1 -1
- package/dist/tui/chat-session.js +120 -28
- package/dist/tui/chat-session.js.map +1 -1
- package/dist/tui/components.d.ts +43 -2
- package/dist/tui/components.d.ts.map +1 -1
- package/dist/tui/components.js +97 -4
- package/dist/tui/components.js.map +1 -1
- package/dist/tui/config-wizard/detail.d.ts +12 -6
- package/dist/tui/config-wizard/detail.d.ts.map +1 -1
- package/dist/tui/config-wizard/detail.js +33 -32
- package/dist/tui/config-wizard/detail.js.map +1 -1
- package/dist/tui/config-wizard/engine.d.ts.map +1 -1
- package/dist/tui/config-wizard/engine.js +26 -20
- package/dist/tui/config-wizard/engine.js.map +1 -1
- package/dist/tui/config-wizard/fields.d.ts.map +1 -1
- package/dist/tui/config-wizard/fields.js +176 -164
- package/dist/tui/config-wizard/fields.js.map +1 -1
- package/dist/tui/config-wizard/kv-editor.d.ts.map +1 -1
- package/dist/tui/config-wizard/kv-editor.js +9 -5
- package/dist/tui/config-wizard/kv-editor.js.map +1 -1
- package/dist/tui/config-wizard/list.d.ts.map +1 -1
- package/dist/tui/config-wizard/list.js +2 -1
- 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 +32 -19
- package/dist/tui/config-wizard/menu.js.map +1 -1
- package/dist/tui/config-wizard/prompt-editor.d.ts.map +1 -1
- package/dist/tui/config-wizard/prompt-editor.js +4 -3
- 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 +29 -20
- 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 +21 -17
- 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 +16 -6
- 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 +17 -19
- 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 +41 -26
- 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/index.d.ts +17 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +25 -14
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/input-editing.d.ts +4 -1
- package/dist/tui/input-editing.d.ts.map +1 -1
- package/dist/tui/input-editing.js +7 -3
- package/dist/tui/input-editing.js.map +1 -1
- 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/chat-commands.d.ts +54 -3
- package/dist/tui/screens/chat-commands.d.ts.map +1 -1
- package/dist/tui/screens/chat-commands.js +469 -330
- package/dist/tui/screens/chat-commands.js.map +1 -1
- package/dist/tui/screens/chat.d.ts +8 -0
- package/dist/tui/screens/chat.d.ts.map +1 -1
- package/dist/tui/screens/chat.js +206 -405
- 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/handoff-choice.d.ts.map +1 -1
- package/dist/tui/screens/handoff-choice.js +4 -3
- package/dist/tui/screens/handoff-choice.js.map +1 -1
- package/dist/tui/screens/index.d.ts +1 -1
- package/dist/tui/screens/index.d.ts.map +1 -1
- package/dist/tui/screens/index.js +1 -1
- 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 +11 -1
- package/dist/tui/screens/input.d.ts.map +1 -1
- package/dist/tui/screens/input.js +21 -12
- package/dist/tui/screens/input.js.map +1 -1
- package/dist/tui/screens/layout.d.ts +8 -0
- package/dist/tui/screens/layout.d.ts.map +1 -1
- package/dist/tui/screens/layout.js +6 -2
- package/dist/tui/screens/layout.js.map +1 -1
- 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.map +1 -1
- package/dist/tui/screens/messages-view.js +5 -4
- 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 +15 -0
- package/dist/tui/screens/notice-bar.js.map +1 -0
- package/dist/tui/screens/notice.d.ts +40 -8
- 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 +3 -2
- package/dist/tui/screens/overlays.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 +5 -2
- 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 +44 -0
- package/dist/tui/screens/use-input-editing.d.ts.map +1 -0
- package/dist/tui/screens/use-input-editing.js +192 -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 +35 -0
- package/dist/tui/screens/use-wizard-host.d.ts.map +1 -0
- package/dist/tui/screens/use-wizard-host.js +103 -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 +8 -5
- package/dist/tui/text.d.ts.map +1 -1
- package/dist/tui/text.js +95 -35
- package/dist/tui/text.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 +0 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,12 +13,130 @@ export interface CommandMeta {
|
|
|
13
13
|
/** 主命令名(不含 `/` 前缀),同时是处理函数表的键 */
|
|
14
14
|
name: string;
|
|
15
15
|
/** 等价别名(不含 `/` 前缀) */
|
|
16
|
-
aliases?: string[];
|
|
17
|
-
/**
|
|
18
|
-
|
|
16
|
+
aliases?: readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* 一句话说明的 i18n key。
|
|
19
|
+
*
|
|
20
|
+
* 这里存 **key 而不是文案**:本模块是纯数据,加载时机靠前(甚至早于语言初始化),
|
|
21
|
+
* 存成文案就定死了「加载那一刻的语言」。渲染时由 `getCommandHints()` 用 `t()` 现取。
|
|
22
|
+
*/
|
|
23
|
+
descriptionKey: string;
|
|
24
|
+
/**
|
|
25
|
+
* 执行期间会调用模型(较慢,几十秒)。
|
|
26
|
+
*
|
|
27
|
+
* 宿主据此**拦住输入框**:否则用户以为没反应、继续打字,按键会被静默吞进隐藏的
|
|
28
|
+
* 输入缓冲,等命令结束后才突然冒出来(迁移过程中出现过这个 bug)。
|
|
29
|
+
* 这是命令的属性而不是宿主的白名单 —— 新增命令只改本文件,宿主自动跟上。
|
|
30
|
+
*/
|
|
31
|
+
blocksInput?: boolean;
|
|
19
32
|
}
|
|
20
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* 命令元数据表(数组顺序即展示顺序)。
|
|
35
|
+
*
|
|
36
|
+
* 用 `as const` 声明以保留命令名的字面量类型,从而派生出 `CommandName`:
|
|
37
|
+
* 命令处理器表以 `Record<CommandName, …>` 声明,于是「新增命令但忘了写处理器」是
|
|
38
|
+
* **编译错误**,而不是运行时静默落到「未知命令」。
|
|
39
|
+
*
|
|
40
|
+
* 但 `as const` 的代价是联合类型里**没有别名的条目压根没有 `aliases` 字段**,
|
|
41
|
+
* 遍历时访问会报错。所以这里只把它作为内部字面量,对外导出的
|
|
42
|
+
* {@link COMMAND_REGISTRY} 放宽成 `readonly CommandMeta[]` —— 类型保护一分不少,
|
|
43
|
+
* 而所有遍历点都能直接读 `command.aliases`,不需要额外的取值 helper。
|
|
44
|
+
*/
|
|
45
|
+
declare const REGISTRY_ENTRIES: readonly [{
|
|
46
|
+
readonly name: "save";
|
|
47
|
+
readonly descriptionKey: "cmd.save.desc";
|
|
48
|
+
}, {
|
|
49
|
+
readonly name: "load";
|
|
50
|
+
readonly descriptionKey: "cmd.load.desc";
|
|
51
|
+
}, {
|
|
52
|
+
readonly name: "new";
|
|
53
|
+
readonly descriptionKey: "cmd.new.desc";
|
|
54
|
+
}, {
|
|
55
|
+
readonly name: "back";
|
|
56
|
+
readonly descriptionKey: "cmd.back.desc";
|
|
57
|
+
}, {
|
|
58
|
+
readonly name: "editor";
|
|
59
|
+
readonly descriptionKey: "cmd.editor.desc";
|
|
60
|
+
}, {
|
|
61
|
+
readonly name: "clear";
|
|
62
|
+
readonly descriptionKey: "cmd.clear.desc";
|
|
63
|
+
}, {
|
|
64
|
+
readonly name: "config";
|
|
65
|
+
readonly descriptionKey: "cmd.config.desc";
|
|
66
|
+
}, {
|
|
67
|
+
readonly name: "model";
|
|
68
|
+
readonly descriptionKey: "cmd.model.desc";
|
|
69
|
+
}, {
|
|
70
|
+
readonly name: "agent";
|
|
71
|
+
readonly descriptionKey: "cmd.agent.desc";
|
|
72
|
+
}, {
|
|
73
|
+
readonly name: "reload";
|
|
74
|
+
readonly descriptionKey: "cmd.reload.desc";
|
|
75
|
+
}, {
|
|
76
|
+
readonly name: "mcp";
|
|
77
|
+
readonly descriptionKey: "cmd.mcp.desc";
|
|
78
|
+
}, {
|
|
79
|
+
readonly name: "lang";
|
|
80
|
+
readonly descriptionKey: "cmd.lang.desc";
|
|
81
|
+
}, {
|
|
82
|
+
readonly name: "think";
|
|
83
|
+
readonly aliases: readonly ["effort"];
|
|
84
|
+
readonly descriptionKey: "cmd.think.desc";
|
|
85
|
+
}, {
|
|
86
|
+
readonly name: "key";
|
|
87
|
+
readonly descriptionKey: "cmd.key.desc";
|
|
88
|
+
}, {
|
|
89
|
+
readonly name: "handoff";
|
|
90
|
+
readonly descriptionKey: "cmd.handoff.desc";
|
|
91
|
+
readonly blocksInput: true;
|
|
92
|
+
}, {
|
|
93
|
+
readonly name: "migrate";
|
|
94
|
+
readonly descriptionKey: "cmd.migrate.desc";
|
|
95
|
+
readonly blocksInput: true;
|
|
96
|
+
}, {
|
|
97
|
+
readonly name: "help";
|
|
98
|
+
readonly descriptionKey: "cmd.help.desc";
|
|
99
|
+
}, {
|
|
100
|
+
readonly name: "exit";
|
|
101
|
+
readonly aliases: readonly ["quit"];
|
|
102
|
+
readonly descriptionKey: "cmd.exit.desc";
|
|
103
|
+
}];
|
|
104
|
+
/** 命令主名的字面量联合(别名已归一到主名) */
|
|
105
|
+
export type CommandName = (typeof REGISTRY_ENTRIES)[number]["name"];
|
|
106
|
+
/** 命令元数据表:值来自上面的字面量,类型放宽到 `readonly CommandMeta[]` 便于遍历 */
|
|
21
107
|
export declare const COMMAND_REGISTRY: readonly CommandMeta[];
|
|
108
|
+
/**
|
|
109
|
+
* 把命令名(含别名)归一到主名;未知命令返回 `undefined`。
|
|
110
|
+
*
|
|
111
|
+
* `/think` 与 `/effort` 是同一条命令的两种写法,处理器只按主名注册一份。
|
|
112
|
+
*/
|
|
113
|
+
export declare function canonicalCommandName(name: string): CommandName | undefined;
|
|
114
|
+
/** 命中命令的元数据(别名可查) */
|
|
115
|
+
export declare function findCommand(name: string): CommandMeta | undefined;
|
|
116
|
+
/** 该命令执行期间是否应拦住输入框(见 {@link CommandMeta.blocksInput}) */
|
|
117
|
+
export declare function commandBlocksInput(name: string): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* 从原始输入里取命令参数(首个 token 之后的全部 token)。
|
|
120
|
+
*
|
|
121
|
+
* 与 {@link parseCommandInput} 共用 {@link splitCommandInput},保证「命令名边界」与
|
|
122
|
+
* 「参数边界」用的是同一把尺子。
|
|
123
|
+
*/
|
|
124
|
+
export declare function parseCommandArgs(text: string): string[];
|
|
125
|
+
/**
|
|
126
|
+
* 解析斜杠输入:`/migrate summary` → `{ name: "migrate", args: ["summary"] }`。
|
|
127
|
+
*
|
|
128
|
+
* 命令名的解析**只有这一处**:此前宿主自己也 `slice(1).split(/\s+/)[0]` 了一遍,
|
|
129
|
+
* 于是「命令名怎么算」在命令层与宿主层各有一份实现。
|
|
130
|
+
*
|
|
131
|
+
* 注意「只打了个 `/`」也算命令(`name` 为空串):宿主按斜杠前缀分流,空命令名
|
|
132
|
+
* 落到「未知命令」——与拆出本函数之前的行为一致。
|
|
133
|
+
*
|
|
134
|
+
* @returns 非斜杠输入返回 `null`
|
|
135
|
+
*/
|
|
136
|
+
export declare function parseCommandInput(text: string): {
|
|
137
|
+
name: string;
|
|
138
|
+
args: string[];
|
|
139
|
+
} | null;
|
|
22
140
|
/** 命令展示条目:等价写法(如 `/exit` `/quit`)折叠为一条 */
|
|
23
141
|
export interface CommandHint {
|
|
24
142
|
/** 全部等价写法(不含 `/` 前缀),首个为主命令名 */
|
|
@@ -42,4 +160,5 @@ export declare const COMMAND_LABEL_WIDTH: number;
|
|
|
42
160
|
export declare function matchCommandHints(keyword: string): CommandHint[];
|
|
43
161
|
/** 全部命令名(含别名,升序),供启动横幅等场景展示 */
|
|
44
162
|
export declare function getCommandNames(): string[];
|
|
163
|
+
export {};
|
|
45
164
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/conversation-commands/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/conversation-commands/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,iBAAiB;AACjB,MAAM,WAAW,WAAW;IAC1B,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoBqB,CAAC;AAE5C,2BAA2B;AAC3B,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,2DAA2D;AAC3D,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,EAAqB,CAAC;AAEzE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAO1E;AAED,qBAAqB;AACrB,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGjE;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAcD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAIvF;AAED,0CAA0C;AAC1C,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY;IACZ,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAwB;AACxB,wBAAgB,eAAe,IAAI,WAAW,EAAE,CAS/C;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QACqC,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CAOhE;AAED,+BAA+B;AAC/B,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAM1C"}
|
|
@@ -8,24 +8,99 @@
|
|
|
8
8
|
* 新增、改名或调整说明只需改动本文件。本模块为纯数据与纯函数,
|
|
9
9
|
* 不依赖 chalk / React 等 UI 依赖,可直接单测。
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{ name: "
|
|
11
|
+
import { t } from "../i18n/index.js";
|
|
12
|
+
/**
|
|
13
|
+
* 命令元数据表(数组顺序即展示顺序)。
|
|
14
|
+
*
|
|
15
|
+
* 用 `as const` 声明以保留命令名的字面量类型,从而派生出 `CommandName`:
|
|
16
|
+
* 命令处理器表以 `Record<CommandName, …>` 声明,于是「新增命令但忘了写处理器」是
|
|
17
|
+
* **编译错误**,而不是运行时静默落到「未知命令」。
|
|
18
|
+
*
|
|
19
|
+
* 但 `as const` 的代价是联合类型里**没有别名的条目压根没有 `aliases` 字段**,
|
|
20
|
+
* 遍历时访问会报错。所以这里只把它作为内部字面量,对外导出的
|
|
21
|
+
* {@link COMMAND_REGISTRY} 放宽成 `readonly CommandMeta[]` —— 类型保护一分不少,
|
|
22
|
+
* 而所有遍历点都能直接读 `command.aliases`,不需要额外的取值 helper。
|
|
23
|
+
*/
|
|
24
|
+
const REGISTRY_ENTRIES = [
|
|
25
|
+
{ name: "save", descriptionKey: "cmd.save.desc" },
|
|
26
|
+
{ name: "load", descriptionKey: "cmd.load.desc" },
|
|
27
|
+
{ name: "new", descriptionKey: "cmd.new.desc" },
|
|
28
|
+
{ name: "back", descriptionKey: "cmd.back.desc" },
|
|
29
|
+
{ name: "editor", descriptionKey: "cmd.editor.desc" },
|
|
30
|
+
{ name: "clear", descriptionKey: "cmd.clear.desc" },
|
|
31
|
+
{ name: "config", descriptionKey: "cmd.config.desc" },
|
|
32
|
+
{ name: "model", descriptionKey: "cmd.model.desc" },
|
|
33
|
+
{ name: "agent", descriptionKey: "cmd.agent.desc" },
|
|
34
|
+
{ name: "reload", descriptionKey: "cmd.reload.desc" },
|
|
35
|
+
{ name: "mcp", descriptionKey: "cmd.mcp.desc" },
|
|
36
|
+
{ name: "lang", descriptionKey: "cmd.lang.desc" },
|
|
37
|
+
{ name: "think", aliases: ["effort"], descriptionKey: "cmd.think.desc" },
|
|
38
|
+
{ name: "key", descriptionKey: "cmd.key.desc" },
|
|
39
|
+
{ name: "handoff", descriptionKey: "cmd.handoff.desc", blocksInput: true },
|
|
40
|
+
{ name: "migrate", descriptionKey: "cmd.migrate.desc", blocksInput: true },
|
|
41
|
+
{ name: "help", descriptionKey: "cmd.help.desc" },
|
|
26
42
|
// exit 置于末尾:斜杠菜单回车执行高亮项,避免「只输入 / 就回车」直接退出
|
|
27
|
-
{ name: "exit", aliases: ["quit"],
|
|
43
|
+
{ name: "exit", aliases: ["quit"], descriptionKey: "cmd.exit.desc" },
|
|
28
44
|
];
|
|
45
|
+
/** 命令元数据表:值来自上面的字面量,类型放宽到 `readonly CommandMeta[]` 便于遍历 */
|
|
46
|
+
export const COMMAND_REGISTRY = REGISTRY_ENTRIES;
|
|
47
|
+
/**
|
|
48
|
+
* 把命令名(含别名)归一到主名;未知命令返回 `undefined`。
|
|
49
|
+
*
|
|
50
|
+
* `/think` 与 `/effort` 是同一条命令的两种写法,处理器只按主名注册一份。
|
|
51
|
+
*/
|
|
52
|
+
export function canonicalCommandName(name) {
|
|
53
|
+
const normalized = name.trim().toLowerCase();
|
|
54
|
+
// 在放宽类型的表上匹配(可直接读 `aliases`),再用同一下标取回字面量类型
|
|
55
|
+
const index = COMMAND_REGISTRY.findIndex((command) => command.name === normalized || command.aliases?.includes(normalized));
|
|
56
|
+
return index < 0 ? undefined : REGISTRY_ENTRIES[index].name;
|
|
57
|
+
}
|
|
58
|
+
/** 命中命令的元数据(别名可查) */
|
|
59
|
+
export function findCommand(name) {
|
|
60
|
+
const canonical = canonicalCommandName(name);
|
|
61
|
+
return COMMAND_REGISTRY.find((command) => command.name === canonical);
|
|
62
|
+
}
|
|
63
|
+
/** 该命令执行期间是否应拦住输入框(见 {@link CommandMeta.blocksInput}) */
|
|
64
|
+
export function commandBlocksInput(name) {
|
|
65
|
+
return findCommand(name)?.blocksInput ?? false;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 把原始斜杠输入切成「命令名 + 参数」。
|
|
69
|
+
*
|
|
70
|
+
* 两种返回形状共用同一个切分规则(`/migrate self ` → `migrate` + `["self"]`):
|
|
71
|
+
* 命令名由 {@link parseCommandInput} 取,参数由 {@link parseCommandArgs} 取。
|
|
72
|
+
* 以前命令层自己又 `raw.trim().split(/\s+/).slice(1)` 了一遍 —— 命令名收敛了,
|
|
73
|
+
* 参数没有,于是「参数怎么切」仍然有两份实现。
|
|
74
|
+
*/
|
|
75
|
+
function splitCommandInput(text) {
|
|
76
|
+
return text.trim().replace(/^\//, "").split(/\s+/);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 从原始输入里取命令参数(首个 token 之后的全部 token)。
|
|
80
|
+
*
|
|
81
|
+
* 与 {@link parseCommandInput} 共用 {@link splitCommandInput},保证「命令名边界」与
|
|
82
|
+
* 「参数边界」用的是同一把尺子。
|
|
83
|
+
*/
|
|
84
|
+
export function parseCommandArgs(text) {
|
|
85
|
+
return splitCommandInput(text).slice(1);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 解析斜杠输入:`/migrate summary` → `{ name: "migrate", args: ["summary"] }`。
|
|
89
|
+
*
|
|
90
|
+
* 命令名的解析**只有这一处**:此前宿主自己也 `slice(1).split(/\s+/)[0]` 了一遍,
|
|
91
|
+
* 于是「命令名怎么算」在命令层与宿主层各有一份实现。
|
|
92
|
+
*
|
|
93
|
+
* 注意「只打了个 `/`」也算命令(`name` 为空串):宿主按斜杠前缀分流,空命令名
|
|
94
|
+
* 落到「未知命令」——与拆出本函数之前的行为一致。
|
|
95
|
+
*
|
|
96
|
+
* @returns 非斜杠输入返回 `null`
|
|
97
|
+
*/
|
|
98
|
+
export function parseCommandInput(text) {
|
|
99
|
+
if (!text.trim().startsWith("/"))
|
|
100
|
+
return null;
|
|
101
|
+
const [name, ...args] = splitCommandInput(text);
|
|
102
|
+
return { name: name.toLowerCase(), args };
|
|
103
|
+
}
|
|
29
104
|
/** 展开全部命令为展示条目(别名折叠) */
|
|
30
105
|
export function getCommandHints() {
|
|
31
106
|
return COMMAND_REGISTRY.map((command) => {
|
|
@@ -33,7 +108,7 @@ export function getCommandHints() {
|
|
|
33
108
|
return {
|
|
34
109
|
names,
|
|
35
110
|
label: names.map((name) => `/${name}`).join(" "),
|
|
36
|
-
description: command.
|
|
111
|
+
description: t(command.descriptionKey),
|
|
37
112
|
};
|
|
38
113
|
});
|
|
39
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/conversation-commands/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/conversation-commands/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-persist-plugin.d.ts","sourceRoot":"","sources":["../src/conversation-persist-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKnE,MAAM,WAAW,gCAAgC;IAC/C,+BAA+B;IAC/B,KAAK,EAAE,MAAM,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,qBAAa,yBAA0B,YAAW,WAAW;IAC/C,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,gCAAgC;IAEvD,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"conversation-persist-plugin.d.ts","sourceRoot":"","sources":["../src/conversation-persist-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKnE,MAAM,WAAW,gCAAgC;IAC/C,+BAA+B;IAC/B,KAAK,EAAE,MAAM,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,qBAAa,yBAA0B,YAAW,WAAW;IAC/C,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,gCAAgC;IAEvD,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBtD"}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* 会话 id 通过 `getId()` 动态获取,以便任务迁移切换新会话后依然落盘到正确的文件。
|
|
9
9
|
*/
|
|
10
10
|
import { AgentNS } from "@ai-zen/agents-core";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { persistConversation } from "./conversation-repository.js";
|
|
12
|
+
import { t } from "./i18n/index.js";
|
|
13
13
|
export class ConversationPersistPlugin {
|
|
14
14
|
options;
|
|
15
15
|
constructor(options) {
|
|
@@ -23,20 +23,12 @@ export class ConversationPersistPlugin {
|
|
|
23
23
|
return;
|
|
24
24
|
const id = getId();
|
|
25
25
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
await
|
|
29
|
-
id,
|
|
30
|
-
agentId,
|
|
31
|
-
messages,
|
|
32
|
-
cwd,
|
|
33
|
-
createdAt: existing?.createdAt ?? now,
|
|
34
|
-
updatedAt: now,
|
|
35
|
-
});
|
|
36
|
-
await writeLastSession(cwd ?? process.cwd(), id);
|
|
26
|
+
// 每轮自动落盘也算「本目录的上一轮会话」—— 下次在该目录启动时续接它。
|
|
27
|
+
// `SendContext.cwd` 是 SDK 的可选字段,这里(调用点)是**唯一**需要兜底的地方。
|
|
28
|
+
await persistConversation({ id, agentId, messages, cwd: cwd ?? process.cwd() });
|
|
37
29
|
}
|
|
38
30
|
catch (err) {
|
|
39
|
-
onError?.(
|
|
31
|
+
onError?.(t("chat.persistFailed", { error: err?.message ?? err }));
|
|
40
32
|
}
|
|
41
33
|
}
|
|
42
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-persist-plugin.js","sourceRoot":"","sources":["../src/conversation-persist-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"conversation-persist-plugin.js","sourceRoot":"","sources":["../src/conversation-persist-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAWpC,MAAM,OAAO,yBAAyB;IAChB;IAApB,YAAoB,OAAyC;QAAzC,YAAO,GAAP,OAAO,CAAkC;IAAG,CAAC;IAEjE,KAAK,CAAC,cAAc,CAAC,GAAgB;QACnC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QACtD,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;QAEpC,+BAA+B;QAC/B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO;QAEhE,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,sCAAsC;YACtC,uDAAuD;YACvD,MAAM,mBAAmB,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAClF,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC,CAAC,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;CACF"}
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
* 「上一轮会话 id」指针(session-pointer.ts)随每次落盘更新,供下次启动续接。
|
|
8
8
|
*/
|
|
9
9
|
import { EntityRepository } from "@ai-zen/agents-sdk";
|
|
10
|
-
import
|
|
10
|
+
import { AgentNS } from "@ai-zen/agents-core";
|
|
11
11
|
import type { ConversationContext } from "./types.js";
|
|
12
12
|
export interface Conversation {
|
|
13
13
|
id: string;
|
|
14
14
|
agentId: string;
|
|
15
15
|
/**
|
|
16
|
-
* @deprecated
|
|
17
|
-
*
|
|
16
|
+
* @deprecated 已不再读**也不写**(收敛前 stdio 的 `--save` 曾写入它)。
|
|
17
|
+
* 模型真相源是 `AgentDefinition.modelId`;保留字段仅为兼容旧存档的反序列化。
|
|
18
18
|
*/
|
|
19
19
|
modelId?: string;
|
|
20
20
|
messages: AgentNS.Message[];
|
|
@@ -23,26 +23,80 @@ export interface Conversation {
|
|
|
23
23
|
createdAt: string;
|
|
24
24
|
updatedAt: string;
|
|
25
25
|
}
|
|
26
|
-
/** 会话仓储:每个会话一个 JSON 文件(${conversationsDir}/${id}.json) */
|
|
27
|
-
export declare const conversationRepository: EntityRepository<Conversation>;
|
|
28
26
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
27
|
+
* 会话仓储:每个会话一个 JSON 文件(${conversationsDir}/${id}.json),**写盘是原子的**。
|
|
28
|
+
*
|
|
29
|
+
* 为什么要覆写 `write()`:SDK 的实现是直接 `fs.writeFile`,进程在写一半时被杀
|
|
30
|
+
* (Ctrl+C、OOM、断电)就留下半截 JSON,`read()` 解析失败返回 null —— 整段历史
|
|
31
|
+
* 就此丢失。会话文件可达数 MB,写入窗口并不小。这里改成「写临时文件 → rename」:
|
|
32
|
+
* 同一文件系统内 rename 是原子操作,任何时刻读到的要么是旧文件、要么是完整新文件。
|
|
33
|
+
*
|
|
34
|
+
* 临时文件名为 `<id>.json.tmp`:`list()` 按 `.json` 后缀过滤,不会把它当成会话。
|
|
35
|
+
*/
|
|
36
|
+
declare class AtomicConversationRepository extends EntityRepository<Conversation> {
|
|
37
|
+
write(entity: Conversation): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export declare const conversationRepository: AtomicConversationRepository;
|
|
40
|
+
/**
|
|
41
|
+
* 生成文件名安全的会话 id:英文前缀 + 全下划线时间戳,中英一致。
|
|
42
|
+
* 形如 `chat_2026_10_28_00_56_34`。
|
|
31
43
|
*/
|
|
32
44
|
export declare function generateConversationId(date?: Date): string;
|
|
45
|
+
/** 落盘一份会话所需的全部输入 */
|
|
46
|
+
export interface PersistConversationInput {
|
|
47
|
+
id: string;
|
|
48
|
+
agentId?: string;
|
|
49
|
+
messages: AgentNS.Message[];
|
|
50
|
+
/**
|
|
51
|
+
* 会话所属工作目录。**必填**:调用点都知道自己属于哪个目录,
|
|
52
|
+
* 留成可选只会在入口处多一层 `?? process.cwd()`,与调用点自己的兜底重复。
|
|
53
|
+
*/
|
|
54
|
+
cwd: string;
|
|
55
|
+
/**
|
|
56
|
+
* 是否同时把「本目录上一轮会话」指针指向它(默认 true)。
|
|
57
|
+
*
|
|
58
|
+
* stdio 的 `--save` 传 false:那是一次性管道调用的归档,不该让下次 `ai` 续接到它
|
|
59
|
+
* (否则连着跑几条 `cat … | ai --save` 之后,`ai` 会续接到最后一条管道结果上)。
|
|
60
|
+
*/
|
|
61
|
+
setAsLastSession?: boolean;
|
|
62
|
+
}
|
|
33
63
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
64
|
+
* 落盘一份会话 —— **唯一的写入入口**。
|
|
65
|
+
*
|
|
66
|
+
* 此前「读旧记录拿 createdAt → 写 → 更新指针」这段在 5 个地方各写了一遍,并且已经
|
|
67
|
+
* 漂移:`saveConversation()` 漏写 `cwd`、stdio 的 `--save` 不更新指针、还写了一个已
|
|
68
|
+
* 废弃的 `modelId`。收敛到这里后,各处差异只剩「是否更新指针」一个显式开关。
|
|
36
69
|
*/
|
|
37
|
-
export declare function
|
|
70
|
+
export declare function persistConversation(input: PersistConversationInput): Promise<string>;
|
|
38
71
|
/**
|
|
39
|
-
*
|
|
40
|
-
* 供对话内 `/load` 选择器使用。
|
|
72
|
+
* 保存当前对话(交接前落盘旧会话时用):以 `ctx` 为真相源,走统一的写入入口。
|
|
41
73
|
*/
|
|
42
|
-
export declare function
|
|
74
|
+
export declare function saveConversation(ctx: ConversationContext): Promise<string>;
|
|
75
|
+
/** `/load` 选择器的一行 */
|
|
76
|
+
export interface ConversationSummary {
|
|
43
77
|
id: string;
|
|
78
|
+
/** 文件名(= id),无摘要时的回退显示 */
|
|
44
79
|
name: string;
|
|
80
|
+
/** 首条用户消息的第一行(截断);读不到时为空串 */
|
|
81
|
+
preview: string;
|
|
45
82
|
updatedAt: string;
|
|
46
83
|
size: number;
|
|
47
|
-
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 会话摘要:首条用户消息的第一行。
|
|
87
|
+
*
|
|
88
|
+
* 会话 id 是时间戳(`chat_2026_10_28_00_56_34`),直接当标签列出来完全分不清哪条是哪条。
|
|
89
|
+
* 取首行而不是整段:`CwdTrackerPlugin` 会在消息末尾追加工作目录注记,末尾对辨认无意义。
|
|
90
|
+
*/
|
|
91
|
+
export declare function conversationPreview(conversation: Conversation | null): string;
|
|
92
|
+
/**
|
|
93
|
+
* 列出已保存的会话,按更新时间倒序。供对话内 `/load` 选择器使用。
|
|
94
|
+
*
|
|
95
|
+
* 先只 stat(快),排序后**只为将要显示的那几条**解析内容取摘要 —— 会话攒到上百条时,
|
|
96
|
+
* 逐个 `JSON.parse` 会明显拖慢 `/load`。
|
|
97
|
+
*/
|
|
98
|
+
export declare function listConversations(options: {
|
|
99
|
+
previewLimit: number;
|
|
100
|
+
}): Promise<ConversationSummary[]>;
|
|
101
|
+
export {};
|
|
48
102
|
//# sourceMappingURL=conversation-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-repository.d.ts","sourceRoot":"","sources":["../src/conversation-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"conversation-repository.d.ts","sourceRoot":"","sources":["../src/conversation-repository.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAI9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,cAAM,4BAA6B,SAAQ,gBAAgB,CAAC,YAAY,CAAC;IACxD,KAAK,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAO1D;AAED,eAAO,MAAM,sBAAsB,8BAAsD,CAAC;AAE1F;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,GAAE,IAAiB,GAAG,MAAM,CAEtE;AAED,oBAAoB;AACpB,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5B;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAa1F;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAOhF;AAED,qBAAqB;AACrB,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,CAK7E;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA6BzG"}
|
|
@@ -7,43 +7,93 @@
|
|
|
7
7
|
* 「上一轮会话 id」指针(session-pointer.ts)随每次落盘更新,供下次启动续接。
|
|
8
8
|
*/
|
|
9
9
|
import { promises as fs } from "node:fs";
|
|
10
|
-
import { join } from "node:path";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
11
|
import { EntityRepository } from "@ai-zen/agents-sdk";
|
|
12
|
+
import { AgentNS } from "@ai-zen/agents-core";
|
|
12
13
|
import { CONVERSATIONS_DIR } from "./config.js";
|
|
13
|
-
import {
|
|
14
|
+
import { formatFileStamp } from "./format-time.js";
|
|
14
15
|
import { writeLastSession } from "./session-pointer.js";
|
|
15
|
-
/** 会话仓储:每个会话一个 JSON 文件(${conversationsDir}/${id}.json) */
|
|
16
|
-
export const conversationRepository = new EntityRepository(CONVERSATIONS_DIR);
|
|
17
16
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* 会话仓储:每个会话一个 JSON 文件(${conversationsDir}/${id}.json),**写盘是原子的**。
|
|
18
|
+
*
|
|
19
|
+
* 为什么要覆写 `write()`:SDK 的实现是直接 `fs.writeFile`,进程在写一半时被杀
|
|
20
|
+
* (Ctrl+C、OOM、断电)就留下半截 JSON,`read()` 解析失败返回 null —— 整段历史
|
|
21
|
+
* 就此丢失。会话文件可达数 MB,写入窗口并不小。这里改成「写临时文件 → rename」:
|
|
22
|
+
* 同一文件系统内 rename 是原子操作,任何时刻读到的要么是旧文件、要么是完整新文件。
|
|
23
|
+
*
|
|
24
|
+
* 临时文件名为 `<id>.json.tmp`:`list()` 按 `.json` 后缀过滤,不会把它当成会话。
|
|
25
|
+
*/
|
|
26
|
+
class AtomicConversationRepository extends EntityRepository {
|
|
27
|
+
async write(entity) {
|
|
28
|
+
const target = this.path(entity.id);
|
|
29
|
+
const tmp = `${target}.tmp`;
|
|
30
|
+
await fs.mkdir(dirname(target), { recursive: true });
|
|
31
|
+
await fs.writeFile(tmp, JSON.stringify(entity, null, 2), "utf-8");
|
|
32
|
+
await fs.rename(tmp, target);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export const conversationRepository = new AtomicConversationRepository(CONVERSATIONS_DIR);
|
|
36
|
+
/**
|
|
37
|
+
* 生成文件名安全的会话 id:英文前缀 + 全下划线时间戳,中英一致。
|
|
38
|
+
* 形如 `chat_2026_10_28_00_56_34`。
|
|
20
39
|
*/
|
|
21
40
|
export function generateConversationId(date = new Date()) {
|
|
22
|
-
return
|
|
41
|
+
return `chat_${formatFileStamp(date.toISOString())}`;
|
|
23
42
|
}
|
|
24
43
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
44
|
+
* 落盘一份会话 —— **唯一的写入入口**。
|
|
45
|
+
*
|
|
46
|
+
* 此前「读旧记录拿 createdAt → 写 → 更新指针」这段在 5 个地方各写了一遍,并且已经
|
|
47
|
+
* 漂移:`saveConversation()` 漏写 `cwd`、stdio 的 `--save` 不更新指针、还写了一个已
|
|
48
|
+
* 废弃的 `modelId`。收敛到这里后,各处差异只剩「是否更新指针」一个显式开关。
|
|
27
49
|
*/
|
|
28
|
-
export async function
|
|
29
|
-
const
|
|
30
|
-
const existing = await conversationRepository.read(id);
|
|
50
|
+
export async function persistConversation(input) {
|
|
51
|
+
const existing = await conversationRepository.read(input.id);
|
|
31
52
|
const now = new Date().toISOString();
|
|
32
53
|
await conversationRepository.write({
|
|
33
|
-
id,
|
|
34
|
-
agentId:
|
|
35
|
-
messages:
|
|
54
|
+
id: input.id,
|
|
55
|
+
agentId: input.agentId || "default",
|
|
56
|
+
messages: input.messages,
|
|
57
|
+
cwd: input.cwd,
|
|
36
58
|
createdAt: existing?.createdAt ?? now,
|
|
37
59
|
updatedAt: now,
|
|
38
60
|
});
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
if (input.setAsLastSession !== false)
|
|
62
|
+
await writeLastSession(input.cwd, input.id);
|
|
63
|
+
return input.id;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 保存当前对话(交接前落盘旧会话时用):以 `ctx` 为真相源,走统一的写入入口。
|
|
67
|
+
*/
|
|
68
|
+
export async function saveConversation(ctx) {
|
|
69
|
+
return persistConversation({
|
|
70
|
+
id: ctx.currentId || generateConversationId(),
|
|
71
|
+
agentId: ctx.agentId,
|
|
72
|
+
messages: ctx.agent.messages,
|
|
73
|
+
cwd: process.cwd(),
|
|
74
|
+
});
|
|
41
75
|
}
|
|
76
|
+
/** 摘要最大字符数(渲染侧还会按终端宽度再裁一次) */
|
|
77
|
+
const PREVIEW_MAX = 80;
|
|
42
78
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
79
|
+
* 会话摘要:首条用户消息的第一行。
|
|
80
|
+
*
|
|
81
|
+
* 会话 id 是时间戳(`chat_2026_10_28_00_56_34`),直接当标签列出来完全分不清哪条是哪条。
|
|
82
|
+
* 取首行而不是整段:`CwdTrackerPlugin` 会在消息末尾追加工作目录注记,末尾对辨认无意义。
|
|
83
|
+
*/
|
|
84
|
+
export function conversationPreview(conversation) {
|
|
85
|
+
const first = conversation?.messages?.find((m) => m.role === AgentNS.Role.User);
|
|
86
|
+
const content = typeof first?.content === "string" ? first.content : "";
|
|
87
|
+
const line = content.split("\n").find((part) => part.trim()) ?? "";
|
|
88
|
+
return line.trim().slice(0, PREVIEW_MAX);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* 列出已保存的会话,按更新时间倒序。供对话内 `/load` 选择器使用。
|
|
92
|
+
*
|
|
93
|
+
* 先只 stat(快),排序后**只为将要显示的那几条**解析内容取摘要 —— 会话攒到上百条时,
|
|
94
|
+
* 逐个 `JSON.parse` 会明显拖慢 `/load`。
|
|
45
95
|
*/
|
|
46
|
-
export async function listConversations() {
|
|
96
|
+
export async function listConversations(options) {
|
|
47
97
|
try {
|
|
48
98
|
await fs.access(CONVERSATIONS_DIR);
|
|
49
99
|
}
|
|
@@ -51,19 +101,27 @@ export async function listConversations() {
|
|
|
51
101
|
return [];
|
|
52
102
|
}
|
|
53
103
|
const files = await fs.readdir(CONVERSATIONS_DIR);
|
|
54
|
-
const
|
|
104
|
+
const stats = [];
|
|
55
105
|
for (const file of files) {
|
|
56
106
|
if (!file.endsWith(".json"))
|
|
57
107
|
continue;
|
|
58
108
|
const id = file.replace(/\.json$/, "");
|
|
59
109
|
try {
|
|
60
110
|
const st = await fs.stat(join(CONVERSATIONS_DIR, file));
|
|
61
|
-
|
|
111
|
+
stats.push({ id, name: id, updatedAt: st.mtime.toISOString(), size: st.size });
|
|
62
112
|
}
|
|
63
113
|
catch {
|
|
64
114
|
/* 跳过读取失败的条目 */
|
|
65
115
|
}
|
|
66
116
|
}
|
|
67
|
-
|
|
117
|
+
stats.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
118
|
+
// `previewLimit` 必填:默认 0(=全部无摘要)是个静默陷阱 —— 漏传不会报错,
|
|
119
|
+
// 只会让列表变成一堆谁也分不清的时间戳 id。
|
|
120
|
+
const withPreview = await Promise.all(stats.map(async (item, index) => {
|
|
121
|
+
if (index >= options.previewLimit)
|
|
122
|
+
return { ...item, preview: "" };
|
|
123
|
+
return { ...item, preview: conversationPreview(await conversationRepository.read(item.id)) };
|
|
124
|
+
}));
|
|
125
|
+
return withPreview;
|
|
68
126
|
}
|
|
69
127
|
//# sourceMappingURL=conversation-repository.js.map
|