@muyichengshayu/promptx 0.2.7 → 0.2.9

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 (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/apps/runner/src/engines/claudeCodeRunner.js +69 -1
  3. package/apps/runner/src/engines/claudeCodeRunner.test.js +279 -0
  4. package/apps/runner/src/engines/index.js +2 -0
  5. package/apps/runner/src/engines/kimiCodeRunner.js +561 -0
  6. package/apps/runner/src/engines/openCodeRunner.test.js +73 -0
  7. package/apps/runner/src/engines/shellRunner.test.js +46 -0
  8. package/apps/runner/src/runManager.js +115 -11
  9. package/apps/runner/src/runManager.test.js +913 -0
  10. package/apps/runner/src/serverClient.test.js +93 -0
  11. package/apps/server/src/agentSessionDiscovery.js +136 -0
  12. package/apps/server/src/agentSessionDiscovery.test.js +186 -0
  13. package/apps/server/src/agents/claudeCodeRunner.test.js +433 -0
  14. package/apps/server/src/agents/index.js +2 -0
  15. package/apps/server/src/agents/kimiCodeRunner.js +565 -0
  16. package/apps/server/src/agents/kimiCodeRunner.test.js +127 -0
  17. package/apps/server/src/agents/openCodeRunner.test.js +236 -0
  18. package/apps/server/src/agents/runnerContract.test.js +382 -0
  19. package/apps/server/src/appPaths.test.js +52 -0
  20. package/apps/server/src/assetRoutes.test.js +168 -0
  21. package/apps/server/src/codex.test.js +518 -0
  22. package/apps/server/src/codexRoutes.test.js +376 -0
  23. package/apps/server/src/codexRuns.test.js +160 -0
  24. package/apps/server/src/codexSessions.js +1 -1
  25. package/apps/server/src/codexSessions.test.js +369 -0
  26. package/apps/server/src/db.test.js +182 -0
  27. package/apps/server/src/gitDiff.test.js +542 -0
  28. package/apps/server/src/gitDiffClient.test.js +140 -0
  29. package/apps/server/src/internalRoutes.test.js +134 -0
  30. package/apps/server/src/maintenance.test.js +154 -0
  31. package/apps/server/src/processControl.test.js +147 -0
  32. package/apps/server/src/relayClient.test.js +478 -0
  33. package/apps/server/src/relayConfig.test.js +73 -0
  34. package/apps/server/src/relayProtocol.test.js +49 -0
  35. package/apps/server/src/relayServer.test.js +798 -0
  36. package/apps/server/src/relayTenants.test.js +137 -0
  37. package/apps/server/src/relayUsageStore.test.js +65 -0
  38. package/apps/server/src/repository.test.js +150 -0
  39. package/apps/server/src/runDispatchService.js +14 -2
  40. package/apps/server/src/runDispatchService.test.js +563 -0
  41. package/apps/server/src/runEventIngest.test.js +225 -0
  42. package/apps/server/src/runRecovery.test.js +73 -0
  43. package/apps/server/src/runnerClient.test.js +80 -0
  44. package/apps/server/src/runnerDispatch.test.js +136 -0
  45. package/apps/server/src/systemConfig.test.js +112 -0
  46. package/apps/server/src/systemRoutes.test.js +319 -0
  47. package/apps/server/src/taskRoutes.test.js +726 -0
  48. package/apps/server/src/upload.test.js +30 -0
  49. package/apps/server/src/webAppRoutes.test.js +67 -0
  50. package/apps/server/src/workspaceFiles.test.js +262 -0
  51. package/apps/web/dist/assets/{CodexSessionManagerDialog-B_F9ZWKy.js → CodexSessionManagerDialog-_qLljY7F.js} +1 -1
  52. package/apps/web/dist/assets/{TaskDiffReviewDialog-CPqGk_q2.js → TaskDiffReviewDialog-DpW8S8yT.js} +1 -1
  53. package/apps/web/dist/assets/{WorkbenchSettingsDialog-CWl81vlG.js → WorkbenchSettingsDialog-CYfh5G7c.js} +1 -1
  54. package/apps/web/dist/assets/WorkbenchView-A8nm0NH9.js +60 -0
  55. package/apps/web/dist/assets/index-DHF_zkYI.js +2 -0
  56. package/apps/web/dist/index.html +1 -1
  57. package/package.json +14 -21
  58. package/packages/shared/src/index.js +6 -0
  59. package/scripts/doctor.mjs +8 -0
  60. package/apps/web/dist/assets/WorkbenchView-gbRu02Lv.js +0 -60
  61. package/apps/web/dist/assets/index-5LxHpYf5.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.9
4
+
5
+ - 接入 `Kimi Code CLI` 执行引擎:工作台 Agent 选择器新增 Kimi Code 选项,支持本地会话发现、线程复用、TodoList 过程展示与停止控制,与现有 Codex / Claude Code / OpenCode 并列为第四类 Agent。
6
+ - 工作台 Agent 选择器与过滤状态持久化:切换任务后会自动恢复上次选中的 Agent 引擎和中栏过滤条件,不再每次回到默认值。
7
+ - runner 状态提示支持多语言:idle 进度提示(排队中、运行中、停止中)通过 `messageKey` 机制走前端 i18n 翻译,英文环境下显示对应英文文案。
8
+ - 修复图片上传地址在云主机部署下失效的问题:前端 `API_BASE` 改为运行时按 `window.location.origin` 计算,数据库中只存相对路径;同时兼容已存的老数据(`localhost` / `127.0.0.1` 绝对路径在显示时自动替换为当前 host),runner 收到的 prompt 仍会正确转换为本地地址。
9
+
10
+ ## 0.2.8
11
+
12
+ - 修复 `Claude Code` 的 `TodoWrite` 过程映射:待办列表会被归一为结构化 `todo_list` 事件,正确展示待办内容、进行中与已完成状态,不再只暴露原始工具输入。
13
+ - 优化 runner 长时间静默时的可见反馈:排队、运行中和停止中的任务会周期性补发状态进度事件,避免前端看起来像卡住,同时保持心跳与并发队列诊断信息一致。
14
+
3
15
  ## 0.2.7
4
16
 
5
17
  - 新增 `Aqua Classic` 主题:以复古 macOS Aqua / Snow Leopard 的银灰工具窗口为方向,补齐工作台、设置弹窗、按钮、输入框、消息卡片、确认删除等核心区域的主题 token 与专属样式。
@@ -171,6 +171,52 @@ function isClaudeCollabToolName(name = '') {
171
171
  return ['agent', 'task'].includes(String(name || '').trim().toLowerCase())
172
172
  }
173
173
 
174
+ function isClaudeTodoToolName(name = '') {
175
+ return String(name || '').trim().toLowerCase() === 'todowrite'
176
+ }
177
+
178
+ function normalizeClaudeTodoStatus(status = '') {
179
+ const normalized = String(status || '').trim().toLowerCase()
180
+ if (['completed', 'complete', 'done', 'checked'].includes(normalized)) {
181
+ return 'completed'
182
+ }
183
+ if (['in_progress', 'in-progress', 'active', 'doing', 'running'].includes(normalized)) {
184
+ return 'in_progress'
185
+ }
186
+ return 'pending'
187
+ }
188
+
189
+ function normalizeClaudeTodoText(entry = {}, status = 'pending') {
190
+ const content = String(entry?.content || entry?.text || entry?.title || entry?.label || '').trim()
191
+ const activeForm = String(entry?.activeForm || '').trim()
192
+ if (status === 'in_progress' && activeForm) {
193
+ return activeForm
194
+ }
195
+ return content || activeForm
196
+ }
197
+
198
+ function normalizeClaudeTodoItems(items = []) {
199
+ return (Array.isArray(items) ? items : [])
200
+ .map((entry) => {
201
+ if (!entry || typeof entry !== 'object') {
202
+ return null
203
+ }
204
+
205
+ const status = normalizeClaudeTodoStatus(entry.status)
206
+ const text = normalizeClaudeTodoText(entry, status)
207
+ if (!text) {
208
+ return null
209
+ }
210
+
211
+ return {
212
+ text,
213
+ status,
214
+ completed: status === 'completed',
215
+ }
216
+ })
217
+ .filter(Boolean)
218
+ }
219
+
174
220
  function collectTextParts(value, parts = []) {
175
221
  if (!value) {
176
222
  return parts
@@ -333,23 +379,26 @@ function createClaudeToolUseEvent(block = {}, state = createClaudeNormalizationS
333
379
  const input = block?.input && typeof block.input === 'object' ? block.input : {}
334
380
  const command = buildClaudeToolCommand(name, input)
335
381
  const isCollabTool = isClaudeCollabToolName(name)
382
+ const isTodoTool = isClaudeTodoToolName(name)
336
383
  const collabPrompt = String(input.prompt || '').trim()
337
384
  const collabDescription = String(input.description || '').trim()
338
385
  const collabRole = String(input.subagent_type || input.agent || '').trim()
339
386
  const collabModel = String(input.model || '').trim()
340
387
  const collabTarget = extractAgentTargetFromTexts(collabDescription, collabPrompt)
388
+ const todoItems = normalizeClaudeTodoItems(input.todos)
341
389
 
342
390
  if (toolUseId) {
343
391
  state.toolUses.set(toolUseId, {
344
392
  name,
345
393
  command,
346
- kind: isCollabTool ? 'collab' : 'command',
394
+ kind: isCollabTool ? 'collab' : (isTodoTool ? 'todo' : 'command'),
347
395
  prompt: collabPrompt || collabDescription,
348
396
  description: collabDescription,
349
397
  role: collabRole,
350
398
  model: collabModel,
351
399
  target: collabTarget,
352
400
  taskIds: [],
401
+ todoItems,
353
402
  })
354
403
  }
355
404
 
@@ -365,6 +414,15 @@ function createClaudeToolUseEvent(block = {}, state = createClaudeNormalizationS
365
414
  }
366
415
  }
367
416
 
417
+ if (isTodoTool) {
418
+ return {
419
+ ...createItemStartedEvent({
420
+ type: AGENT_RUN_ITEM_TYPES.TODO_LIST,
421
+ items: todoItems,
422
+ }),
423
+ }
424
+ }
425
+
368
426
  return {
369
427
  ...createItemStartedEvent({
370
428
  type: AGENT_RUN_ITEM_TYPES.COMMAND_EXECUTION,
@@ -381,6 +439,7 @@ function createClaudeToolResultEvent(block = {}, state = createClaudeNormalizati
381
439
  const isError = Boolean(block?.is_error)
382
440
  const taskIds = Array.isArray(remembered?.taskIds) ? remembered.taskIds.filter(Boolean) : []
383
441
  const collabTool = remembered?.kind === 'collab'
442
+ const todoTool = remembered?.kind === 'todo'
384
443
 
385
444
  if (toolUseId && state.completedCollabToolUseIds.has(toolUseId)) {
386
445
  return null
@@ -419,6 +478,15 @@ function createClaudeToolResultEvent(block = {}, state = createClaudeNormalizati
419
478
  }
420
479
  }
421
480
 
481
+ if (todoTool) {
482
+ return {
483
+ ...createItemCompletedEvent({
484
+ type: AGENT_RUN_ITEM_TYPES.TODO_LIST,
485
+ items: Array.isArray(remembered?.todoItems) ? remembered.todoItems : [],
486
+ }),
487
+ }
488
+ }
489
+
422
490
  return {
423
491
  ...createItemCompletedEvent({
424
492
  type: AGENT_RUN_ITEM_TYPES.COMMAND_EXECUTION,
@@ -0,0 +1,279 @@
1
+ import test from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ import { createClaudeNormalizationState, normalizeClaudeEvents } from './claudeCodeRunner.js'
5
+
6
+ test('runner claudeCodeRunner maps fatal auth api_retry to error event', () => {
7
+ assert.deepEqual(
8
+ normalizeClaudeEvents({
9
+ type: 'system',
10
+ subtype: 'api_retry',
11
+ attempt: 1,
12
+ max_retries: 10,
13
+ error_status: 401,
14
+ error: 'authentication_failed',
15
+ }),
16
+ [{
17
+ type: 'error',
18
+ message: 'Claude Code 认证失败(HTTP 401 authentication_failed)。请重新登录 Claude Code,或检查当前环境中的认证令牌配置。',
19
+ }]
20
+ )
21
+ })
22
+
23
+ test('runner claudeCodeRunner maps transient api_retry to reconnecting error event', () => {
24
+ assert.deepEqual(
25
+ normalizeClaudeEvents({
26
+ type: 'system',
27
+ subtype: 'api_retry',
28
+ attempt: 2,
29
+ max_retries: 10,
30
+ error_status: 503,
31
+ error: 'overloaded',
32
+ }),
33
+ [{
34
+ type: 'error',
35
+ message: 'Reconnecting... 2/10 (HTTP 503 overloaded)',
36
+ }]
37
+ )
38
+ })
39
+
40
+ test('runner claudeCodeRunner maps Agent sub-agents into collaboration events', () => {
41
+ const state = createClaudeNormalizationState()
42
+
43
+ assert.deepEqual(
44
+ normalizeClaudeEvents({
45
+ type: 'assistant',
46
+ message: {
47
+ content: [
48
+ {
49
+ type: 'tool_use',
50
+ id: 'agent-tool-1',
51
+ name: 'Agent',
52
+ input: {
53
+ description: 'Analyze a.js exports',
54
+ subagent_type: 'general-purpose',
55
+ prompt: 'Analyze a.js in the current directory.',
56
+ model: 'sonnet',
57
+ },
58
+ },
59
+ ],
60
+ },
61
+ }, state),
62
+ [{
63
+ type: 'item.started',
64
+ item: {
65
+ type: 'collab_tool_call',
66
+ tool: 'spawn_agent',
67
+ receiver_thread_ids: [],
68
+ prompt: 'Analyze a.js in the current directory.',
69
+ agents_states: {},
70
+ },
71
+ }]
72
+ )
73
+
74
+ assert.deepEqual(
75
+ normalizeClaudeEvents({
76
+ type: 'system',
77
+ subtype: 'task_started',
78
+ tool_use_id: 'agent-tool-1',
79
+ task_id: 'task-a',
80
+ description: 'Analyze a.js exports',
81
+ }, state),
82
+ [{
83
+ type: 'item.completed',
84
+ item: {
85
+ type: 'collab_tool_call',
86
+ tool: 'spawn_agent',
87
+ receiver_thread_ids: ['task-a'],
88
+ prompt: 'Analyze a.js in the current directory.',
89
+ agents_states: {
90
+ 'task-a': {
91
+ status: 'running',
92
+ message: '',
93
+ title: 'Analyze a.js exports',
94
+ role: 'general-purpose',
95
+ target: 'a.js',
96
+ model: 'sonnet',
97
+ task_id: 'task-a',
98
+ },
99
+ },
100
+ },
101
+ }]
102
+ )
103
+ })
104
+
105
+ test('runner claudeCodeRunner maps task_completed and ignores duplicate tool_result for Agent sub-agents', () => {
106
+ const state = createClaudeNormalizationState()
107
+
108
+ normalizeClaudeEvents({
109
+ type: 'assistant',
110
+ message: {
111
+ content: [
112
+ {
113
+ type: 'tool_use',
114
+ id: 'agent-tool-2',
115
+ name: 'Agent',
116
+ input: {
117
+ description: 'Analyze b.js exports',
118
+ subagent_type: 'general-purpose',
119
+ prompt: 'Analyze b.js in the current directory.',
120
+ model: 'sonnet',
121
+ },
122
+ },
123
+ ],
124
+ },
125
+ }, state)
126
+
127
+ normalizeClaudeEvents({
128
+ type: 'system',
129
+ subtype: 'task_started',
130
+ tool_use_id: 'agent-tool-2',
131
+ task_id: 'task-b',
132
+ description: 'Analyze b.js exports',
133
+ }, state)
134
+
135
+ assert.deepEqual(
136
+ normalizeClaudeEvents({
137
+ type: 'system',
138
+ subtype: 'task_completed',
139
+ task_id: 'task-b',
140
+ result: 'found 2 exports',
141
+ description: 'Analyze b.js exports',
142
+ }, state),
143
+ [{
144
+ type: 'item.completed',
145
+ item: {
146
+ type: 'collab_tool_call',
147
+ tool: 'wait',
148
+ receiver_thread_ids: ['task-b'],
149
+ prompt: 'Analyze b.js in the current directory.',
150
+ agents_states: {
151
+ 'task-b': {
152
+ status: 'completed',
153
+ message: 'found 2 exports',
154
+ title: 'Analyze b.js exports',
155
+ role: 'general-purpose',
156
+ target: 'b.js',
157
+ model: 'sonnet',
158
+ task_id: 'task-b',
159
+ },
160
+ },
161
+ },
162
+ }]
163
+ )
164
+
165
+ assert.deepEqual(
166
+ normalizeClaudeEvents({
167
+ type: 'user',
168
+ message: {
169
+ content: [
170
+ {
171
+ type: 'tool_result',
172
+ tool_use_id: 'agent-tool-2',
173
+ content: 'duplicate result',
174
+ is_error: false,
175
+ },
176
+ ],
177
+ },
178
+ }, state),
179
+ []
180
+ )
181
+ })
182
+
183
+ test('runner claudeCodeRunner maps TodoWrite into todo_list events', () => {
184
+ const state = createClaudeNormalizationState()
185
+
186
+ assert.deepEqual(
187
+ normalizeClaudeEvents({
188
+ type: 'assistant',
189
+ message: {
190
+ content: [
191
+ {
192
+ type: 'tool_use',
193
+ id: 'todo-tool-1',
194
+ name: 'TodoWrite',
195
+ input: {
196
+ todos: [
197
+ {
198
+ content: 'Inspect relevant backend and admin codepaths',
199
+ activeForm: 'Inspecting relevant backend and admin codepaths',
200
+ status: 'in_progress',
201
+ },
202
+ {
203
+ content: 'Implement hospital database model and admin APIs',
204
+ status: 'pending',
205
+ },
206
+ {
207
+ content: 'Add tests',
208
+ status: 'completed',
209
+ },
210
+ ],
211
+ },
212
+ },
213
+ ],
214
+ },
215
+ }, state),
216
+ [{
217
+ type: 'item.started',
218
+ item: {
219
+ type: 'todo_list',
220
+ items: [
221
+ {
222
+ text: 'Inspecting relevant backend and admin codepaths',
223
+ status: 'in_progress',
224
+ completed: false,
225
+ },
226
+ {
227
+ text: 'Implement hospital database model and admin APIs',
228
+ status: 'pending',
229
+ completed: false,
230
+ },
231
+ {
232
+ text: 'Add tests',
233
+ status: 'completed',
234
+ completed: true,
235
+ },
236
+ ],
237
+ },
238
+ }]
239
+ )
240
+
241
+ assert.deepEqual(
242
+ normalizeClaudeEvents({
243
+ type: 'user',
244
+ message: {
245
+ content: [
246
+ {
247
+ type: 'tool_result',
248
+ tool_use_id: 'todo-tool-1',
249
+ content: 'Todos have been modified successfully.',
250
+ is_error: false,
251
+ },
252
+ ],
253
+ },
254
+ }, state),
255
+ [{
256
+ type: 'item.completed',
257
+ item: {
258
+ type: 'todo_list',
259
+ items: [
260
+ {
261
+ text: 'Inspecting relevant backend and admin codepaths',
262
+ status: 'in_progress',
263
+ completed: false,
264
+ },
265
+ {
266
+ text: 'Implement hospital database model and admin APIs',
267
+ status: 'pending',
268
+ completed: false,
269
+ },
270
+ {
271
+ text: 'Add tests',
272
+ status: 'completed',
273
+ completed: true,
274
+ },
275
+ ],
276
+ },
277
+ }]
278
+ )
279
+ })
@@ -7,12 +7,14 @@ import {
7
7
  import { codexRunner } from './codexRunner.js'
8
8
  import { claudeCodeRunner } from './claudeCodeRunner.js'
9
9
  import { openCodeRunner } from './openCodeRunner.js'
10
+ import { kimiCodeRunner } from './kimiCodeRunner.js'
10
11
  import { shellRunner } from './shellRunner.js'
11
12
 
12
13
  const runnerRegistry = new Map([
13
14
  [codexRunner.engine, codexRunner],
14
15
  [claudeCodeRunner.engine, claudeCodeRunner],
15
16
  [openCodeRunner.engine, openCodeRunner],
17
+ [kimiCodeRunner.engine, kimiCodeRunner],
16
18
  [shellRunner.engine, shellRunner],
17
19
  ])
18
20