thatgfsj-code 2.2.9 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/CHANGELOG.md +15 -67
  2. package/dist/app/index.d.ts +28 -5
  3. package/dist/app/index.d.ts.map +1 -1
  4. package/dist/app/index.js +76 -10
  5. package/dist/app/index.js.map +1 -1
  6. package/dist/cache/fingerprint.d.ts +49 -0
  7. package/dist/cache/fingerprint.d.ts.map +1 -0
  8. package/dist/cache/fingerprint.js +100 -0
  9. package/dist/cache/fingerprint.js.map +1 -0
  10. package/dist/cache/index.d.ts +15 -0
  11. package/dist/cache/index.d.ts.map +1 -0
  12. package/dist/cache/index.js +15 -0
  13. package/dist/cache/index.js.map +1 -0
  14. package/dist/cache/smartModel.d.ts +40 -0
  15. package/dist/cache/smartModel.d.ts.map +1 -0
  16. package/dist/cache/smartModel.js +43 -0
  17. package/dist/cache/smartModel.js.map +1 -0
  18. package/dist/cache/stats.d.ts +93 -0
  19. package/dist/cache/stats.d.ts.map +1 -0
  20. package/dist/cache/stats.js +155 -0
  21. package/dist/cache/stats.js.map +1 -0
  22. package/dist/cache/volatile.d.ts +32 -0
  23. package/dist/cache/volatile.d.ts.map +1 -0
  24. package/dist/cache/volatile.js +44 -0
  25. package/dist/cache/volatile.js.map +1 -0
  26. package/dist/cmd/index.js +49 -57
  27. package/dist/cmd/index.js.map +1 -1
  28. package/dist/config/index.d.ts.map +1 -1
  29. package/dist/config/index.js +8 -0
  30. package/dist/config/index.js.map +1 -1
  31. package/dist/config/types.d.ts +14 -0
  32. package/dist/config/types.d.ts.map +1 -1
  33. package/dist/llm/anthropic.d.ts +55 -5
  34. package/dist/llm/anthropic.d.ts.map +1 -1
  35. package/dist/llm/anthropic.js +172 -26
  36. package/dist/llm/anthropic.js.map +1 -1
  37. package/dist/llm/index.d.ts +26 -8
  38. package/dist/llm/index.d.ts.map +1 -1
  39. package/dist/llm/index.js +83 -15
  40. package/dist/llm/index.js.map +1 -1
  41. package/dist/llm/openai.d.ts +28 -8
  42. package/dist/llm/openai.d.ts.map +1 -1
  43. package/dist/llm/openai.js +58 -8
  44. package/dist/llm/openai.js.map +1 -1
  45. package/dist/llm/provider.d.ts +40 -8
  46. package/dist/llm/provider.d.ts.map +1 -1
  47. package/dist/llm/provider.js +8 -1
  48. package/dist/llm/provider.js.map +1 -1
  49. package/dist/prompts/index.d.ts +32 -0
  50. package/dist/prompts/index.d.ts.map +1 -1
  51. package/dist/prompts/index.js +33 -11
  52. package/dist/prompts/index.js.map +1 -1
  53. package/dist/session/index.d.ts +32 -3
  54. package/dist/session/index.d.ts.map +1 -1
  55. package/dist/session/index.js +51 -36
  56. package/dist/session/index.js.map +1 -1
  57. package/dist/skills/brainstorming.js +33 -33
  58. package/dist/skills/code-review.js +35 -35
  59. package/dist/skills/executing-plans.js +18 -18
  60. package/dist/skills/frontend-design.js +25 -25
  61. package/dist/skills/git-workflow.js +26 -26
  62. package/dist/skills/improve-architecture.js +28 -28
  63. package/dist/skills/neuroweave.js +37 -37
  64. package/dist/skills/playwright.js +62 -62
  65. package/dist/skills/prototype.js +20 -20
  66. package/dist/skills/subagent.js +19 -19
  67. package/dist/skills/supabase.js +34 -34
  68. package/dist/skills/systematic-debugging.js +34 -34
  69. package/dist/skills/tdd.js +29 -29
  70. package/dist/skills/triage.js +25 -25
  71. package/dist/skills/verification.js +22 -22
  72. package/dist/skills/writing-plans.js +32 -32
  73. package/dist/tools/nwt.js +16 -16
  74. package/dist/tui/app.d.ts.map +1 -1
  75. package/dist/tui/app.js +9 -2
  76. package/dist/tui/app.js.map +1 -1
  77. package/dist/tui/components/Header.d.ts +8 -0
  78. package/dist/tui/components/Header.d.ts.map +1 -1
  79. package/dist/tui/components/Header.js +17 -4
  80. package/dist/tui/components/Header.js.map +1 -1
  81. package/dist/tui/components/InitWizard.d.ts +12 -1
  82. package/dist/tui/components/InitWizard.d.ts.map +1 -1
  83. package/dist/tui/components/InitWizard.js +58 -3
  84. package/dist/tui/components/InitWizard.js.map +1 -1
  85. package/dist/tui/components/ModelSelector.d.ts +3 -1
  86. package/dist/tui/components/ModelSelector.d.ts.map +1 -1
  87. package/dist/tui/components/ModelSelector.js +24 -7
  88. package/dist/tui/components/ModelSelector.js.map +1 -1
  89. package/dist/tui/components/ToolCall.d.ts.map +1 -1
  90. package/dist/tui/components/ToolCall.js +1 -6
  91. package/dist/tui/components/ToolCall.js.map +1 -1
  92. package/dist/tui/components/UserInput.d.ts.map +1 -1
  93. package/dist/tui/components/UserInput.js +20 -0
  94. package/dist/tui/components/UserInput.js.map +1 -1
  95. package/dist/tui/hooks/useChat.d.ts +22 -0
  96. package/dist/tui/hooks/useChat.d.ts.map +1 -1
  97. package/dist/tui/hooks/useChat.js +82 -46
  98. package/dist/tui/hooks/useChat.js.map +1 -1
  99. package/dist/tui/hooks/useCommands.d.ts.map +1 -1
  100. package/dist/tui/hooks/useCommands.js +57 -0
  101. package/dist/tui/hooks/useCommands.js.map +1 -1
  102. package/dist/tui/welcome.d.ts.map +1 -1
  103. package/dist/tui/welcome.js +2 -3
  104. package/dist/tui/welcome.js.map +1 -1
  105. package/dist/types.d.ts +79 -6
  106. package/dist/types.d.ts.map +1 -1
  107. package/dist/types.js +7 -0
  108. package/dist/types.js.map +1 -1
  109. package/dist/utils/stableStringify.d.ts +21 -0
  110. package/dist/utils/stableStringify.d.ts.map +1 -0
  111. package/dist/utils/stableStringify.js +53 -0
  112. package/dist/utils/stableStringify.js.map +1 -0
  113. package/dist/utils/thinking.d.ts.map +1 -1
  114. package/dist/utils/thinking.js +0 -3
  115. package/dist/utils/thinking.js.map +1 -1
  116. package/package.json +7 -6
  117. package/src/app/index.ts +189 -124
  118. package/src/cache/fingerprint.ts +101 -0
  119. package/src/cache/index.ts +15 -0
  120. package/src/cache/smartModel.ts +52 -0
  121. package/src/cache/stats.ts +199 -0
  122. package/src/cache/volatile.ts +47 -0
  123. package/src/cmd/index.tsx +288 -292
  124. package/src/config/index.ts +156 -148
  125. package/src/config/providers.ts +234 -234
  126. package/src/config/types.ts +67 -53
  127. package/src/hooks/index.ts +111 -111
  128. package/src/llm/anthropic.ts +388 -243
  129. package/src/llm/gemini.ts +169 -169
  130. package/src/llm/index.ts +265 -200
  131. package/src/llm/openai.ts +243 -196
  132. package/src/llm/provider.ts +66 -34
  133. package/src/prompts/index.ts +260 -220
  134. package/src/session/compactor.ts +103 -103
  135. package/src/session/index.ts +181 -168
  136. package/src/session/message.ts +42 -42
  137. package/src/skills/brainstorming.ts +43 -43
  138. package/src/skills/code-review.ts +45 -45
  139. package/src/skills/executing-plans.ts +27 -27
  140. package/src/skills/frontend-design.ts +35 -35
  141. package/src/skills/git-workflow.ts +36 -36
  142. package/src/skills/improve-architecture.ts +38 -38
  143. package/src/skills/index.ts +136 -136
  144. package/src/skills/neuroweave.ts +47 -47
  145. package/src/skills/playwright.ts +72 -72
  146. package/src/skills/prototype.ts +30 -30
  147. package/src/skills/subagent.ts +28 -28
  148. package/src/skills/supabase.ts +44 -44
  149. package/src/skills/systematic-debugging.ts +44 -44
  150. package/src/skills/tdd.ts +39 -39
  151. package/src/skills/triage.ts +35 -35
  152. package/src/skills/verification.ts +31 -31
  153. package/src/skills/writing-plans.ts +42 -42
  154. package/src/tools/nwt.ts +598 -598
  155. package/src/tools/types.ts +122 -122
  156. package/src/tui/app.tsx +200 -186
  157. package/src/tui/components/ChatList.tsx +41 -41
  158. package/src/tui/components/ChatMessage.tsx +54 -54
  159. package/src/tui/components/Header.tsx +56 -29
  160. package/src/tui/components/InitWizard.tsx +217 -132
  161. package/src/tui/components/Markdown.tsx +35 -35
  162. package/src/tui/components/ModelSelector.tsx +107 -87
  163. package/src/tui/components/StatusBar.tsx +30 -30
  164. package/src/tui/components/Thinking.tsx +17 -17
  165. package/src/tui/components/ToolCall.tsx +102 -107
  166. package/src/tui/components/UserInput.tsx +151 -131
  167. package/src/tui/hooks/useChat.ts +287 -238
  168. package/src/tui/hooks/useCommands.ts +234 -176
  169. package/src/tui/index.ts +6 -6
  170. package/src/tui/welcome.ts +177 -178
  171. package/src/types.ts +104 -42
  172. package/src/utils/diff.ts +71 -71
  173. package/src/utils/project.ts +99 -99
  174. package/src/utils/stableStringify.ts +47 -0
  175. package/src/utils/thinking.ts +118 -121
  176. package/tests/cache/fingerprint.test.ts +75 -0
  177. package/tests/cache/providerCatalog.test.ts +31 -0
  178. package/tests/cache/stableStringify.test.ts +43 -0
  179. package/tests/cache/stats.test.ts +146 -0
  180. package/tests/cache/volatile.test.ts +75 -0
  181. package/tests/smoke-pollution.mjs +78 -0
  182. package/tests/smoke-thinking.mjs +110 -0
  183. package/tests/smoke-tool-stream.mjs +69 -0
  184. package/tests/smoke-tool.mjs +117 -0
  185. package/.nwt/meta.json +0 -5
  186. package/dist/version.d.ts +0 -16
  187. package/dist/version.d.ts.map +0 -1
  188. package/dist/version.js +0 -16
  189. package/dist/version.js.map +0 -1
  190. package/src/version.ts +0 -16
@@ -1,176 +1,234 @@
1
- import { useCallback } from 'react';
2
- import type { App } from '../../app/index.js';
3
-
4
- interface CommandResult {
5
- handled: boolean;
6
- output?: string;
7
- action?: 'clear' | 'reinit';
8
- }
9
-
10
- // 中文命令别名映射
11
- const CMD_ALIASES: Record<string, string> = {
12
- '/模型': '/model',
13
- '/新建': '/new',
14
- '/清空': '/new',
15
- '/压缩': '/compact',
16
- '/技能': '/skills',
17
- '/技能管理': '/skills',
18
- '/mcp': '/mcp',
19
- '/帮助': '/help',
20
- '/服务商': '/provider',
21
- '/思考': '/thinking',
22
- };
23
-
24
- export const COMMAND_LIST = [
25
- { name: '/模型', desc: '切换模型' },
26
- { name: '/服务商', desc: '更换服务商' },
27
- { name: '/新建', desc: '新建会话' },
28
- { name: '/压缩', desc: '压缩上下文' },
29
- { name: '/技能', desc: '管理技能' },
30
- { name: '/mcp', desc: 'MCP 设置' },
31
- { name: '/帮助', desc: '查看帮助' },
32
- ];
33
-
34
- export function useCommands(app: App) {
35
-
36
- const handleCommand = useCallback((input: string): CommandResult => {
37
- const cmd = input.trim();
38
- const parts = cmd.split(/\s+/);
39
- let name = parts[0].toLowerCase();
40
- const arg = parts.slice(1).join(' ');
41
-
42
- // 中文别名映射
43
- if (CMD_ALIASES[name]) {
44
- name = CMD_ALIASES[name];
45
- }
46
-
47
- // ── /model [name] ───────────────────────────────────
48
- if (name === '/model') {
49
- if (!arg) {
50
- const c = app.config.get();
51
- return {
52
- handled: true,
53
- output: [
54
- `当前: ${c.provider} / ${c.model}`,
55
- '',
56
- '用法: /模型 <名称>',
57
- ' /模型 deepseek-chat',
58
- ' /模型 gpt-4o',
59
- ' /模型 claude-sonnet-4-20250514',
60
- '',
61
- '或: /服务商 更换服务商',
62
- ].join('\n'),
63
- };
64
- }
65
- app.config.save({ model: arg });
66
- return { handled: true, output: `模型 → ${arg}` };
67
- }
68
-
69
- // ── /provider ───────────────────────────────────────
70
- if (name === '/provider') {
71
- return { handled: true, action: 'reinit' };
72
- }
73
-
74
- // ── /new, /clear ────────────────────────────────────
75
- if (name === '/new') {
76
- app.session.clear();
77
- return { handled: true, output: '新会话已创建。', action: 'clear' };
78
- }
79
-
80
- // ── /compact ────────────────────────────────────────
81
- if (name === '/compact') {
82
- const before = app.session.getMessageCount();
83
- app.session.truncate();
84
- const after = app.session.getMessageCount();
85
- return { handled: true, output: `上下文已压缩: ${before} → ${after} 条消息` };
86
- }
87
-
88
- // ── /skills [id] ────────────────────────────────────
89
- if (name === '/skills') {
90
- if (arg) {
91
- if (app.skills.isActive(arg)) {
92
- app.skills.deactivate(arg);
93
- return { handled: true, output: `✗ 已关闭: ${arg}` };
94
- } else if (app.skills.activate(arg)) {
95
- return { handled: true, output: `✓ 已开启: ${arg}` };
96
- }
97
- return { handled: true, output: `未知技能: ${arg}` };
98
- }
99
-
100
- const all = app.skills.list();
101
- const lines = [
102
- '技能列表:',
103
- ...all.map(s => {
104
- const mark = app.skills.isActive(s.id) ? '✓' : '·';
105
- return ` ${mark} ${s.id} ${s.description}`;
106
- }),
107
- '',
108
- '用法: /技能 <id> 切换',
109
- ];
110
- return { handled: true, output: lines.join('\n') };
111
- }
112
-
113
- // ── /mcp ────────────────────────────────────────────
114
- if (name === '/mcp') {
115
- return {
116
- handled: true,
117
- output: [
118
- 'MCP 配置: ~/.thatgfsj/mcp.json',
119
- '',
120
- ' {',
121
- ' "servers": {',
122
- ' "名称": { "command": "npx", "args": ["-y", "server"] }',
123
- ' }',
124
- ' }',
125
- ].join('\n'),
126
- };
127
- }
128
-
129
- // ── /thinking on|off ─────────────────────────────────
130
- if (name === '/thinking' || name === '/思考') {
131
- if (!arg) {
132
- return {
133
- handled: true,
134
- output: `思考块显示: ${app.showThinking ? '开启 (显示完整 <think>...</think>)' : '关闭 (压缩为单行提示)'}`,
135
- };
136
- }
137
- const want = arg.toLowerCase();
138
- if (want === 'on' || want === '开启' || want === 'true' || want === '1') {
139
- app.showThinking = true;
140
- return { handled: true, output: '✓ 已开启完整思考块显示' };
141
- }
142
- if (want === 'off' || want === '关闭' || want === 'false' || want === '0') {
143
- app.showThinking = false;
144
- return { handled: true, output: '✓ 已关闭思考块显示 (压缩为单行提示)' };
145
- }
146
- return { handled: true, output: `用法: /thinking on|off (当前: ${app.showThinking ? 'on' : 'off'})` };
147
- }
148
-
149
- // ── /help ───────────────────────────────────────────
150
- if (name === '/help') {
151
- return {
152
- handled: true,
153
- output: [
154
- '命令列表:',
155
- ' /模型 <名称> 切换模型',
156
- ' /服务商 更换服务商',
157
- ' /新建 新建会话',
158
- ' /压缩 压缩上下文',
159
- ' /思考 [on|off] 切换思考块显示',
160
- ' /技能 [id] 管理技能',
161
- ' /mcp MCP 设置',
162
- ' /帮助 查看帮助',
163
- ' exit 退出',
164
- '',
165
- '快捷键:',
166
- ' ↑/↓ 历史记录',
167
- ' Ctrl+C 退出',
168
- ].join('\n'),
169
- };
170
- }
171
-
172
- return { handled: false };
173
- }, [app]);
174
-
175
- return { handleCommand };
176
- }
1
+ import { useCallback } from 'react';
2
+ import type { App } from '../../app/index.js';
3
+
4
+ interface CommandResult {
5
+ handled: boolean;
6
+ output?: string;
7
+ action?: 'clear' | 'reinit';
8
+ }
9
+
10
+ // 中文命令别名映射
11
+ const CMD_ALIASES: Record<string, string> = {
12
+ '/模型': '/model',
13
+ '/新建': '/new',
14
+ '/清空': '/new',
15
+ '/压缩': '/compact',
16
+ '/技能': '/skills',
17
+ '/技能管理': '/skills',
18
+ '/mcp': '/mcp',
19
+ '/帮助': '/help',
20
+ '/服务商': '/provider',
21
+ '/思考': '/thinking',
22
+ '/缓存': '/cache',
23
+ };
24
+
25
+ export const COMMAND_LIST = [
26
+ { name: '/模型', desc: '切换模型' },
27
+ { name: '/服务商', desc: '更换服务商' },
28
+ { name: '/新建', desc: '新建会话' },
29
+ { name: '/压缩', desc: '压缩上下文' },
30
+ { name: '/缓存', desc: '缓存命中率' },
31
+ { name: '/技能', desc: '管理技能' },
32
+ { name: '/mcp', desc: 'MCP 设置' },
33
+ { name: '/帮助', desc: '查看帮助' },
34
+ ];
35
+
36
+ export function useCommands(app: App) {
37
+
38
+ const handleCommand = useCallback((input: string): CommandResult => {
39
+ const cmd = input.trim();
40
+ const parts = cmd.split(/\s+/);
41
+ let name = parts[0].toLowerCase();
42
+ const arg = parts.slice(1).join(' ');
43
+
44
+ // 中文别名映射
45
+ if (CMD_ALIASES[name]) {
46
+ name = CMD_ALIASES[name];
47
+ }
48
+
49
+ // ── /model [name] ───────────────────────────────────
50
+ if (name === '/model') {
51
+ if (!arg) {
52
+ const c = app.config.get();
53
+ return {
54
+ handled: true,
55
+ output: [
56
+ `当前: ${c.provider} / ${c.model}`,
57
+ '',
58
+ '用法: /模型 <名称>',
59
+ ' /模型 deepseek-chat',
60
+ ' /模型 gpt-4o',
61
+ ' /模型 claude-sonnet-4-20250514',
62
+ '',
63
+ '或: /服务商 更换服务商',
64
+ ].join('\n'),
65
+ };
66
+ }
67
+ app.config.save({ model: arg });
68
+ return { handled: true, output: `模型 → ${arg}` };
69
+ }
70
+
71
+ // ── /provider ───────────────────────────────────────
72
+ if (name === '/provider') {
73
+ return { handled: true, action: 'reinit' };
74
+ }
75
+
76
+ // ── /new, /clear ────────────────────────────────────
77
+ if (name === '/new') {
78
+ app.session.clear();
79
+ return { handled: true, output: '新会话已创建。', action: 'clear' };
80
+ }
81
+
82
+ // ── /compact ────────────────────────────────────────
83
+ if (name === '/compact') {
84
+ const before = app.session.getMessageCount();
85
+ app.session.truncate();
86
+ const after = app.session.getMessageCount();
87
+ return { handled: true, output: `上下文已压缩: ${before} → ${after} 条消息` };
88
+ }
89
+
90
+ // ── /cache — prompt cache hit-rate + cost savings ───
91
+ // v3.0.0: surfaces CacheStatsStore snapshots. Sub-commands:
92
+ // /cache show full breakdown
93
+ // /cache reset zero the persistent stats
94
+ if (name === '/cache') {
95
+ if (arg === 'reset' || arg === '重置') {
96
+ app.cacheStats.reset();
97
+ return { handled: true, output: '✓ 缓存统计已重置' };
98
+ }
99
+ if (arg === 'off' || arg === '关') {
100
+ // Toggle disable: writes through to provider config (currently a
101
+ // no-op until M4.5 wires Config.cache). Print a hint.
102
+ return {
103
+ handled: true,
104
+ output: [
105
+ '✗ 关闭缓存功能:在 ~/.thatgfsj/config.json 添加 "cache": { "enabled": false } 后重启。',
106
+ ' (提示:完全关闭会大幅增加 token 成本;推荐保留开启)',
107
+ ].join('\n'),
108
+ };
109
+ }
110
+ const s = app.cacheStats.snapshot();
111
+ if (s.totalRequests === 0) {
112
+ return {
113
+ handled: true,
114
+ output: [
115
+ '⚡ 缓存统计',
116
+ '─────────────────────────',
117
+ ' 暂无请求。开启一段对话后再来查看。',
118
+ '',
119
+ '/cache reset · 重置统计',
120
+ ].join('\n'),
121
+ };
122
+ }
123
+ const hitRateStr = (s.hitRate * 100).toFixed(1) + '%';
124
+ const recent = s.history.slice(-10);
125
+ const lines = [
126
+ '⚡ 缓存统计 (累计 ' + s.totalRequests + ' 轮)',
127
+ '─────────────────────────',
128
+ ` 命中率: ${hitRateStr} (${s.totalReadTokens.toLocaleString()} / ${s.totalInputTokens.toLocaleString()} tokens)`,
129
+ ` 累计创建: ${s.totalCreationTokens.toLocaleString()} tokens`,
130
+ ` 累计节省: ¥${s.estimatedSavingsCNY.toFixed(4)}`,
131
+ '',
132
+ '最近 10 轮:',
133
+ ];
134
+ for (let i = 0; i < recent.length; i++) {
135
+ const r = recent[i];
136
+ const tag = r.read > 0 ? '⚡' : '💸';
137
+ const pct = (r.hitRate * 100).toFixed(0) + '%';
138
+ lines.push(` #${s.history.length - recent.length + i + 1} [${tag}] ${String(r.read).padStart(5)} / ${String(r.input).padStart(5)} ${pct.padStart(4)}`);
139
+ }
140
+ lines.push('');
141
+ lines.push('/cache reset · 重置统计');
142
+ return { handled: true, output: lines.join('\n') };
143
+ }
144
+
145
+ // ── /skills [id] ────────────────────────────────────
146
+ if (name === '/skills') {
147
+ if (arg) {
148
+ if (app.skills.isActive(arg)) {
149
+ app.skills.deactivate(arg);
150
+ return { handled: true, output: `✗ 已关闭: ${arg}` };
151
+ } else if (app.skills.activate(arg)) {
152
+ return { handled: true, output: `✓ 已开启: ${arg}` };
153
+ }
154
+ return { handled: true, output: `未知技能: ${arg}` };
155
+ }
156
+
157
+ const all = app.skills.list();
158
+ const lines = [
159
+ '技能列表:',
160
+ ...all.map(s => {
161
+ const mark = app.skills.isActive(s.id) ? '✓' : '·';
162
+ return ` ${mark} ${s.id} ${s.description}`;
163
+ }),
164
+ '',
165
+ '用法: /技能 <id> 切换',
166
+ ];
167
+ return { handled: true, output: lines.join('\n') };
168
+ }
169
+
170
+ // ── /mcp ────────────────────────────────────────────
171
+ if (name === '/mcp') {
172
+ return {
173
+ handled: true,
174
+ output: [
175
+ 'MCP 配置: ~/.thatgfsj/mcp.json',
176
+ '',
177
+ ' {',
178
+ ' "servers": {',
179
+ ' "名称": { "command": "npx", "args": ["-y", "server"] }',
180
+ ' }',
181
+ ' }',
182
+ ].join('\n'),
183
+ };
184
+ }
185
+
186
+ // ── /thinking on|off ─────────────────────────────────
187
+ if (name === '/thinking' || name === '/思考') {
188
+ if (!arg) {
189
+ return {
190
+ handled: true,
191
+ output: `思考块显示: ${app.showThinking ? '开启 (显示完整 <think>...</think>)' : '关闭 (压缩为单行提示)'}`,
192
+ };
193
+ }
194
+ const want = arg.toLowerCase();
195
+ if (want === 'on' || want === '开启' || want === 'true' || want === '1') {
196
+ app.showThinking = true;
197
+ return { handled: true, output: '✓ 已开启完整思考块显示' };
198
+ }
199
+ if (want === 'off' || want === '关闭' || want === 'false' || want === '0') {
200
+ app.showThinking = false;
201
+ return { handled: true, output: '✓ 已关闭思考块显示 (压缩为单行提示)' };
202
+ }
203
+ return { handled: true, output: `用法: /thinking on|off (当前: ${app.showThinking ? 'on' : 'off'})` };
204
+ }
205
+
206
+ // ── /help ───────────────────────────────────────────
207
+ if (name === '/help') {
208
+ return {
209
+ handled: true,
210
+ output: [
211
+ '命令列表:',
212
+ ' /模型 <名称> 切换模型',
213
+ ' /服务商 更换服务商',
214
+ ' /新建 新建会话',
215
+ ' /压缩 压缩上下文',
216
+ ' /缓存 查看缓存命中率',
217
+ ' /思考 [on|off] 切换思考块显示',
218
+ ' /技能 [id] 管理技能',
219
+ ' /mcp MCP 设置',
220
+ ' /帮助 查看帮助',
221
+ ' exit 退出',
222
+ '',
223
+ '快捷键:',
224
+ ' ↑/↓ 历史记录',
225
+ ' Ctrl+C 退出',
226
+ ].join('\n'),
227
+ };
228
+ }
229
+
230
+ return { handled: false };
231
+ }, [app]);
232
+
233
+ return { handleCommand };
234
+ }
package/src/tui/index.ts CHANGED
@@ -1,6 +1,6 @@
1
- /**
2
- * TUI Module - Ink-based Terminal UI
3
- */
4
-
5
- export { TuiApp } from './app.js';
6
- export { WelcomeScreen } from './welcome.js';
1
+ /**
2
+ * TUI Module - Ink-based Terminal UI
3
+ */
4
+
5
+ export { TuiApp } from './app.js';
6
+ export { WelcomeScreen } from './welcome.js';