@armadra/agent 0.6.2 → 0.6.4

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 (147) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/CHANGELOG.zh-CN.md +59 -0
  3. package/README.md +168 -575
  4. package/README.zh-CN.md +165 -596
  5. package/dist/agent/queue.d.ts +9 -0
  6. package/dist/agent/queue.js +27 -0
  7. package/dist/agent/session-subagent.d.ts +1 -0
  8. package/dist/agent/session-subagent.js +9 -0
  9. package/dist/agent/session.d.ts +11 -0
  10. package/dist/agent/session.js +29 -2
  11. package/dist/agent/subagent-background.d.ts +75 -0
  12. package/dist/agent/subagent-background.js +209 -0
  13. package/dist/agent/subagent-direct.d.ts +5 -2
  14. package/dist/agent/subagent-direct.js +34 -1
  15. package/dist/agent/subagent-registry.d.ts +26 -6
  16. package/dist/agent/subagent-registry.js +66 -94
  17. package/dist/agent/types-w5.d.ts +11 -1
  18. package/dist/agent/types.d.ts +12 -0
  19. package/dist/agents/builtin.js +0 -1
  20. package/dist/agents/external.js +0 -1
  21. package/dist/agents/parse.js +4 -3
  22. package/dist/agents/result.d.ts +7 -1
  23. package/dist/agents/result.js +20 -1
  24. package/dist/agents/task-control.d.ts +13 -2
  25. package/dist/agents/task-record.d.ts +16 -4
  26. package/dist/agents/task-record.js +32 -0
  27. package/dist/agents/types.d.ts +5 -1
  28. package/dist/ai/apis/chatgpt-rate-limits.js +7 -2
  29. package/dist/ai/providers/discovered-cache.d.ts +10 -4
  30. package/dist/ai/providers/discovered-cache.js +30 -14
  31. package/dist/ai/types.d.ts +2 -1
  32. package/dist/auth/chatgpt/backend-client.d.ts +6 -5
  33. package/dist/auth/chatgpt/backend-client.js +8 -7
  34. package/dist/bundle/ama.cjs +2034 -552
  35. package/dist/cli/compose-agents.d.ts +2 -1
  36. package/dist/cli/compose-agents.js +11 -2
  37. package/dist/cli/subcommands/models-discover.d.ts +1 -0
  38. package/dist/cli/subcommands/models-discover.js +12 -2
  39. package/dist/config/json-schema.js +10 -2
  40. package/dist/config/key-docs.js +9 -2
  41. package/dist/config/merge.d.ts +1 -1
  42. package/dist/config/merge.js +20 -3
  43. package/dist/config/schema-w5.js +4 -2
  44. package/dist/config/schema.js +4 -0
  45. package/dist/config/settings-registry.js +5 -0
  46. package/dist/config/types-w5.d.ts +10 -0
  47. package/dist/config/types-w5.js +2 -0
  48. package/dist/config/types.d.ts +5 -1
  49. package/dist/drivers/runner.js +29 -2
  50. package/dist/git/info.d.ts +19 -0
  51. package/dist/git/info.js +64 -8
  52. package/dist/i18n/catalog.d.ts +58 -8
  53. package/dist/i18n/messages/agents.d.ts +60 -0
  54. package/dist/i18n/messages/agents.js +62 -2
  55. package/dist/i18n/messages/config-keys.d.ts +8 -0
  56. package/dist/i18n/messages/config-keys.js +18 -10
  57. package/dist/i18n/messages/config.d.ts +8 -0
  58. package/dist/i18n/messages/interactive-startup.d.ts +0 -16
  59. package/dist/i18n/messages/interactive-startup.js +0 -16
  60. package/dist/i18n/messages/interactive-view.d.ts +8 -0
  61. package/dist/i18n/messages/interactive-view.js +10 -0
  62. package/dist/i18n/messages/interactive.d.ts +33 -16
  63. package/dist/i18n/messages/interactive.js +31 -0
  64. package/dist/i18n/messages/print.d.ts +4 -0
  65. package/dist/i18n/messages/print.js +4 -0
  66. package/dist/i18n/messages/report.d.ts +8 -0
  67. package/dist/i18n/messages/report.js +12 -4
  68. package/dist/i18n/messages/settings.d.ts +8 -0
  69. package/dist/i18n/messages/settings.js +8 -0
  70. package/dist/i18n/messages/subcommands-config.d.ts +4 -0
  71. package/dist/i18n/messages/subcommands-config.js +4 -0
  72. package/dist/i18n/messages/subcommands.d.ts +4 -0
  73. package/dist/index.d.ts +1 -0
  74. package/dist/modes/commands-core.js +19 -4
  75. package/dist/modes/interactive/agent-bar.d.ts +3 -1
  76. package/dist/modes/interactive/agent-bar.js +12 -5
  77. package/dist/modes/interactive/agent-ui.d.ts +21 -3
  78. package/dist/modes/interactive/agent-ui.js +82 -12
  79. package/dist/modes/interactive/agent-view.d.ts +9 -0
  80. package/dist/modes/interactive/agent-view.js +28 -4
  81. package/dist/modes/interactive/approval-dock.d.ts +51 -0
  82. package/dist/modes/interactive/approval-dock.js +112 -0
  83. package/dist/modes/interactive/approval-ui.d.ts +43 -0
  84. package/dist/modes/interactive/approval-ui.js +64 -0
  85. package/dist/modes/interactive/commands.js +4 -1
  86. package/dist/modes/interactive/event-notices.d.ts +6 -1
  87. package/dist/modes/interactive/event-notices.js +7 -1
  88. package/dist/modes/interactive/interactive-mode.d.ts +4 -2
  89. package/dist/modes/interactive/interactive-mode.js +46 -39
  90. package/dist/modes/interactive/interrupt-send.d.ts +25 -0
  91. package/dist/modes/interactive/interrupt-send.js +32 -0
  92. package/dist/modes/interactive/key-dispatch.d.ts +29 -5
  93. package/dist/modes/interactive/key-dispatch.js +97 -8
  94. package/dist/modes/interactive/line/line-mode.d.ts +1 -0
  95. package/dist/modes/interactive/line/line-mode.js +34 -7
  96. package/dist/modes/interactive/run-indicator.d.ts +34 -2
  97. package/dist/modes/interactive/run-indicator.js +62 -8
  98. package/dist/modes/interactive/session-events.js +5 -1
  99. package/dist/modes/interactive/startup-header.d.ts +29 -14
  100. package/dist/modes/interactive/startup-header.js +93 -59
  101. package/dist/modes/interactive/startup-logo.d.ts +83 -0
  102. package/dist/modes/interactive/startup-logo.js +183 -0
  103. package/dist/modes/interactive/status-area.d.ts +18 -0
  104. package/dist/modes/interactive/status-area.js +67 -1
  105. package/dist/modes/interactive/status-bar.d.ts +13 -2
  106. package/dist/modes/interactive/status-bar.js +60 -17
  107. package/dist/modes/interactive/status-line.d.ts +11 -8
  108. package/dist/modes/interactive/status-line.js +52 -39
  109. package/dist/modes/interactive/status-quota.d.ts +58 -0
  110. package/dist/modes/interactive/status-quota.js +155 -0
  111. package/dist/modes/interactive/subagent-view.d.ts +1 -0
  112. package/dist/modes/interactive/subagent-view.js +8 -0
  113. package/dist/modes/interactive/task-background.d.ts +31 -0
  114. package/dist/modes/interactive/task-background.js +68 -0
  115. package/dist/modes/interactive/tool-view.d.ts +7 -1
  116. package/dist/modes/interactive/tool-view.js +24 -1
  117. package/dist/modes/print/print-mode.d.ts +11 -0
  118. package/dist/modes/print/print-mode.js +36 -1
  119. package/dist/modes/rpc/commands.d.ts +4 -1
  120. package/dist/modes/rpc/commands.js +24 -2
  121. package/dist/rpc.d.ts +20 -0
  122. package/dist/rpc.js +3 -0
  123. package/dist/tools/task-ctl.d.ts +2 -0
  124. package/dist/tools/task-ctl.js +7 -2
  125. package/dist/tools/task.d.ts +11 -0
  126. package/dist/tools/task.js +20 -2
  127. package/dist/tools/types.d.ts +6 -0
  128. package/dist/tui/components/editor.d.ts +2 -0
  129. package/dist/tui/components/editor.js +4 -0
  130. package/dist/tui/components/loader.d.ts +5 -1
  131. package/dist/tui/components/loader.js +18 -5
  132. package/dist/tui/keybindings.d.ts +15 -3
  133. package/dist/tui/keybindings.js +15 -3
  134. package/docs/agents.md +52 -28
  135. package/docs/en/host-api.md +5 -1
  136. package/docs/en/providers.md +1 -1
  137. package/docs/en/rpc.md +28 -14
  138. package/docs/en/sessions.md +3 -1
  139. package/docs/en/tui.md +106 -70
  140. package/docs/host-api.md +5 -1
  141. package/docs/providers.md +4 -2
  142. package/docs/rpc.md +28 -14
  143. package/docs/session-format.md +1 -1
  144. package/docs/sessions.md +2 -1
  145. package/docs/tui-design.md +42 -29
  146. package/docs/tui.md +106 -70
  147. package/package.json +1 -1
@@ -20,6 +20,7 @@ export const en = {
20
20
  host: "host",
21
21
  task: "subagent notice",
22
22
  plan: "plan",
23
+ interrupt: "interrupt",
23
24
  },
24
25
  planHandoff: "Start executing the approved plan",
25
26
  thinkingStreaming: (glyph, ellipsis) => `${glyph} Thinking${ellipsis}`,
@@ -48,6 +49,12 @@ export const en = {
48
49
  thinking: "Thinking",
49
50
  queueMore: (ellipsis, n) => `${ellipsis} ${n} more`,
50
51
  queueHint: (arrow) => `Alt+${arrow} take back · Esc refill and interrupt`,
52
+ /** 有排队的插话时(`key` = 立即送出它们的键:专用键,或 interrupt 模式下的 Enter)。 */
53
+ queueHintNow: (arrow, key) => `Alt+${arrow} take back · ${key} send now · Esc refill and interrupt`,
54
+ /** 输入框有字时:Enter 与专用键各做什么(`ui.enterWhileRunning`)。 */
55
+ sendHint: (mode, key) => mode === "queue"
56
+ ? `Enter queue · ${key} interrupt & send`
57
+ : `Enter interrupt & send · ${key} queue`,
51
58
  },
52
59
  tool: {
53
60
  interrupted: "interrupted",
@@ -86,6 +93,7 @@ export const zh = {
86
93
  host: "宿主",
87
94
  task: "子 Agent 通知",
88
95
  plan: "计划",
96
+ interrupt: "打断",
89
97
  },
90
98
  planHandoff: "按批准的计划开始执行",
91
99
  thinkingStreaming: (glyph, ellipsis) => `${glyph} 思考中${ellipsis}`,
@@ -114,6 +122,8 @@ export const zh = {
114
122
  thinking: "思考中",
115
123
  queueMore: (ellipsis, n) => `${ellipsis} 另 ${n} 条`,
116
124
  queueHint: (arrow) => `Alt+${arrow} 取回 · Esc 回填并中断`,
125
+ queueHintNow: (arrow, key) => `Alt+${arrow} 取回 · ${key} 立即发送 · Esc 回填并中断`,
126
+ sendHint: (mode, key) => mode === "queue" ? `Enter 排队 · ${key} 打断并发送` : `Enter 打断并发送 · ${key} 排队`,
117
127
  },
118
128
  tool: {
119
129
  interrupted: "已中断",
@@ -49,6 +49,8 @@ export declare const en: {
49
49
  clearedCtrlC: string;
50
50
  ctrlCAgain: string;
51
51
  interrupted: string;
52
+ interruptSent: string;
53
+ nothingToSend: string;
52
54
  toolsExpanded: string;
53
55
  toolsCollapsed: string;
54
56
  };
@@ -91,6 +93,18 @@ export declare const en: {
91
93
  cacheSilent: string;
92
94
  sandbox: string;
93
95
  cycleHint: string;
96
+ /** [W6] 订阅配额行(full 第三行)与窄屏 / compact 短格式;标签自带分隔(英文冒号后空格)。 */
97
+ quota: {
98
+ session: string;
99
+ reset: string;
100
+ weekly: string;
101
+ weeklyReset: string;
102
+ window: (duration: string) => string;
103
+ windowReset: (duration: string) => string;
104
+ short5h: string;
105
+ shortWeek: string;
106
+ pending: string;
107
+ };
94
108
  };
95
109
  subagent: {
96
110
  running: (elapsed: string) => string;
@@ -128,6 +142,7 @@ export declare const en: {
128
142
  host: string;
129
143
  task: string;
130
144
  plan: string;
145
+ interrupt: string;
131
146
  };
132
147
  planHandoff: string;
133
148
  thinkingStreaming: (glyph: string, ellipsis: string) => string;
@@ -156,6 +171,8 @@ export declare const en: {
156
171
  thinking: string;
157
172
  queueMore: (ellipsis: string, n: number) => string;
158
173
  queueHint: (arrow: string) => string;
174
+ queueHintNow: (arrow: string, key: string) => string;
175
+ sendHint: (mode: "queue" | "interrupt", key: string) => string;
159
176
  };
160
177
  tool: {
161
178
  interrupted: string;
@@ -189,16 +206,8 @@ export declare const en: {
189
206
  templates: (n: number) => string;
190
207
  host: (host: string) => string;
191
208
  warnings: (n: number) => string;
192
- hintCompact: string;
193
- keyModel: string;
194
- keyDir: string;
195
- keyMode: string;
196
- keyLoaded: string;
197
- keyHost: string;
198
- keyWarnings: string;
199
209
  thinking: (level: string) => string;
200
210
  preset: (preset: string) => string;
201
- warningsValue: (n: number) => string;
202
211
  hint: string;
203
212
  };
204
213
  ui: {
@@ -288,6 +297,8 @@ export declare const zh: {
288
297
  clearedCtrlC: string;
289
298
  ctrlCAgain: string;
290
299
  interrupted: string;
300
+ interruptSent: string;
301
+ nothingToSend: string;
291
302
  toolsExpanded: string;
292
303
  toolsCollapsed: string;
293
304
  };
@@ -328,6 +339,17 @@ export declare const zh: {
328
339
  cacheSilent: string;
329
340
  sandbox: string;
330
341
  cycleHint: string;
342
+ quota: {
343
+ session: string;
344
+ reset: string;
345
+ weekly: string;
346
+ weeklyReset: string;
347
+ window: (duration: string) => string;
348
+ windowReset: (duration: string) => string;
349
+ short5h: string;
350
+ shortWeek: string;
351
+ pending: string;
352
+ };
331
353
  };
332
354
  subagent: {
333
355
  running: (elapsed: string) => string;
@@ -365,6 +387,7 @@ export declare const zh: {
365
387
  host: string;
366
388
  task: string;
367
389
  plan: string;
390
+ interrupt: string;
368
391
  };
369
392
  planHandoff: string;
370
393
  thinkingStreaming: (glyph: string, ellipsis: string) => string;
@@ -393,6 +416,8 @@ export declare const zh: {
393
416
  thinking: string;
394
417
  queueMore: (ellipsis: string, n: number) => string;
395
418
  queueHint: (arrow: string) => string;
419
+ queueHintNow: (arrow: string, key: string) => string;
420
+ sendHint: (mode: "interrupt" | "queue", key: string) => string;
396
421
  };
397
422
  tool: {
398
423
  interrupted: string;
@@ -426,16 +451,8 @@ export declare const zh: {
426
451
  templates: (n: number) => string;
427
452
  host: (host: string) => string;
428
453
  warnings: (n: number) => string;
429
- hintCompact: string;
430
- keyModel: string;
431
- keyDir: string;
432
- keyMode: string;
433
- keyLoaded: string;
434
- keyHost: string;
435
- keyWarnings: string;
436
454
  thinking: (level: string) => string;
437
455
  preset: (preset: string) => string;
438
- warningsValue: (n: number) => string;
439
456
  hint: string;
440
457
  };
441
458
  ui: {
@@ -20,10 +20,12 @@ export const en = {
20
20
  keyHints: [
21
21
  "Enter send (while running = steer) Alt+Enter queue after this turn Shift+Enter / Ctrl+J newline",
22
22
  "Esc interrupt (queued messages go back to the editor) Alt+↑ take back the last queued message",
23
+ "Ctrl+X (while running) interrupt the current turn and send the input now, queued steers first; ui.enterWhileRunning: interrupt swaps it with Enter",
23
24
  "Idle Esc Esc: empty input = rewind (/rewind), with text = clear (↑ to restore)",
24
25
  "Shift+Tab / Tab (empty input) cycle permission mode (confirm before Bypass) Ctrl+L model Ctrl+T thinking level Ctrl+O expand tool output and thinking",
25
26
  "Approval: 1–3 or ↑↓ Enter to choose, y allow a allow for this session n / Esc deny v full input",
26
27
  "Plan approval: 1 approve 2 run in a fresh context 3 keep revising 4 reject and leave Plan e edit plan Esc stay in Plan",
28
+ "Ctrl+B move foreground sub-agent tasks to the background (in tmux: C-b C-b) ↓ (empty input) Agent bar: b background x twice to stop Enter open",
27
29
  "Ctrl+V paste a clipboard image (inserts @path) Ctrl+G footer two rows / one row",
28
30
  "Ctrl+C clear input (again to quit) Ctrl+D quit on empty input Tab complete @ reference a file",
29
31
  ].join("\n"),
@@ -61,6 +63,8 @@ export const en = {
61
63
  clearedCtrlC: "Input cleared · press Ctrl+C again to quit",
62
64
  ctrlCAgain: "Press Ctrl+C again to quit",
63
65
  interrupted: "Interrupted",
66
+ interruptSent: "Interrupted · sending now",
67
+ nothingToSend: "Nothing to send",
64
68
  toolsExpanded: "Tool output: expanded",
65
69
  toolsCollapsed: "Tool output: collapsed",
66
70
  },
@@ -103,6 +107,18 @@ export const en = {
103
107
  cacheSilent: "n/a",
104
108
  sandbox: "sandbox",
105
109
  cycleHint: "shift+tab to cycle",
110
+ /** [W6] 订阅配额行(full 第三行)与窄屏 / compact 短格式;标签自带分隔(英文冒号后空格)。 */
111
+ quota: {
112
+ session: "Session: ",
113
+ reset: "Reset: ",
114
+ weekly: "Weekly: ",
115
+ weeklyReset: "Weekly Reset: ",
116
+ window: (duration) => `${duration}: `,
117
+ windowReset: (duration) => `${duration} Reset: `,
118
+ short5h: "5h",
119
+ shortWeek: "wk",
120
+ pending: "Quota: shown after the first request",
121
+ },
106
122
  },
107
123
  subagent: {
108
124
  running: (elapsed) => `running ${elapsed}`,
@@ -139,10 +155,12 @@ export const zh = {
139
155
  keyHints: [
140
156
  "Enter 发送(运行中 = 插话) Alt+Enter 排到本轮之后 Shift+Enter / Ctrl+J 换行",
141
157
  "Esc 中断(排队消息回填编辑器) Alt+↑ 取回最后一条排队消息",
158
+ "Ctrl+X(运行中)打断当前回合并立即发送输入(排队的插话在前);ui.enterWhileRunning: interrupt 时与 Enter 互换",
142
159
  "空闲时 Esc Esc:输入框为空 = 回滚(/rewind),有字 = 清空(↑ 取回)",
143
160
  "Shift+Tab / Tab(输入为空时)切换权限模式(进入 Bypass 前确认) Ctrl+L 模型 Ctrl+T 思考级别 Ctrl+O 展开工具输出与思考",
144
161
  "审批:1–3 或 ↑↓ Enter 选择,y 允许 a 本会话允许同类 n / Esc 拒绝 v 完整输入",
145
162
  "计划审批:1 批准 2 新上下文执行 3 继续修改 4 放弃并退出 Plan e 编辑计划 Esc 留在 Plan",
163
+ "Ctrl+B 前台子 Agent 任务转后台(tmux 里 C-b C-b) ↓(空输入)Agent 栏:b 转后台 x 连按两次停止 Enter 打开",
146
164
  "Ctrl+V 粘贴剪贴板图片(插入 @路径) Ctrl+G 底部信息行两行 / 一行",
147
165
  "Ctrl+C 清空输入(再按退出) Ctrl+D 空输入时退出 Tab 补全 @ 引用文件",
148
166
  ].join("\n"),
@@ -178,6 +196,8 @@ export const zh = {
178
196
  clearedCtrlC: "已清空输入 · 再按 Ctrl+C 退出",
179
197
  ctrlCAgain: "再按一次 Ctrl+C 退出",
180
198
  interrupted: "已中断",
199
+ interruptSent: "已打断,立即发送",
200
+ nothingToSend: "没有可发送的内容",
181
201
  toolsExpanded: "工具输出:展开",
182
202
  toolsCollapsed: "工具输出:折叠",
183
203
  },
@@ -218,6 +238,17 @@ export const zh = {
218
238
  cacheSilent: "未报告",
219
239
  sandbox: "沙箱",
220
240
  cycleHint: "shift+tab 切换",
241
+ quota: {
242
+ session: "5 小时:",
243
+ reset: "重置:",
244
+ weekly: "本周:",
245
+ weeklyReset: "本周重置:",
246
+ window: (duration) => `${duration}:`,
247
+ windowReset: (duration) => `${duration}重置:`,
248
+ short5h: "5h",
249
+ shortWeek: "周",
250
+ pending: "配额:首次请求后显示",
251
+ },
221
252
  },
222
253
  subagent: {
223
254
  running: (elapsed) => `运行中 ${elapsed}`,
@@ -15,6 +15,7 @@ export declare const en: {
15
15
  needsPrompt: string;
16
16
  retry: (attempt: number, max: number, seconds: number, error: string) => string;
17
17
  modelFailed: string;
18
+ waitingTasks: (n: number) => string;
18
19
  planPending: (version: number, where: string) => string;
19
20
  limitTurns: (limit: number) => string;
20
21
  limitCost: (limit: string, spent: string) => string;
@@ -24,6 +25,7 @@ export declare const en: {
24
25
  rpc: {
25
26
  unknownCommand: (type: string) => string;
26
27
  parseFailed: (error: string) => string;
28
+ badTaskId: string;
27
29
  missingType: string;
28
30
  unsupported: string;
29
31
  noPlan: string;
@@ -53,6 +55,7 @@ export declare const zh: {
53
55
  seconds: (n: number) => string;
54
56
  millis: (n: number) => string;
55
57
  needsPrompt: string;
58
+ waitingTasks: (n: number) => string;
56
59
  retry: (attempt: number, max: number, seconds: number, error: string) => string;
57
60
  modelFailed: string;
58
61
  planPending: (version: number, where: string) => string;
@@ -61,6 +64,7 @@ export declare const zh: {
61
64
  denied: (count: number, tools: readonly string[], reason: string) => string;
62
65
  };
63
66
  rpc: {
67
+ badTaskId: string;
64
68
  unknownCommand: (type: string) => string;
65
69
  parseFailed: (error: string) => string;
66
70
  missingType: string;
@@ -16,6 +16,7 @@ export const en = {
16
16
  needsPrompt: "ama: -p needs a prompt (positional argument or stdin pipe)\n",
17
17
  retry: (attempt, max, seconds, error) => `ama: ↻ retry ${attempt}/${max} (in ${seconds}s): ${error}\n`,
18
18
  modelFailed: "model call failed",
19
+ waitingTasks: (n) => `ama: waiting for ${plural(n, "background task")} and their notification turns (Ctrl+C stops them)\n`,
19
20
  planPending: (version, where) => `ama: plan v${version} saved, awaiting approval (not executed): ${where}; -p does not approve on anyone's behalf — ` +
20
21
  "approve it in the interactive UI or via RPC plan_response, or set plan.unattended: approve to let -p approve and continue",
21
22
  limitTurns: (limit) => `ama: reached the turn limit ${limit} (--max-turns / limits.maxTurns); run ended before finishing`,
@@ -27,6 +28,7 @@ export const en = {
27
28
  rpc: {
28
29
  unknownCommand: (type) => `unknown command: ${type}`,
29
30
  parseFailed: (error) => `JSON parse failed: ${error}`,
31
+ badTaskId: "taskId must be a string",
30
32
  missingType: "missing type",
31
33
  unsupported: "this session does not support this command",
32
34
  noPlan: "this session has no plan extension",
@@ -56,6 +58,7 @@ export const zh = {
56
58
  seconds: (n) => `${n} 秒`,
57
59
  millis: (n) => `${n} 毫秒`,
58
60
  needsPrompt: "ama: -p 需要提示(位置参数或 stdin 管道)\n",
61
+ waitingTasks: (n) => `ama: 等待 ${n} 个后台任务及其通知回合结束(Ctrl+C 中止)\n`,
59
62
  retry: (attempt, max, seconds, error) => `ama: ↻ 重试 ${attempt}/${max}(${seconds}s 后):${error}\n`,
60
63
  modelFailed: "模型调用失败",
61
64
  planPending: (version, where) => `ama: 计划 v${version} 已落盘、待审批(未执行):${where};-p 不替人批准——` +
@@ -66,6 +69,7 @@ export const zh = {
66
69
  "-p 没有人审批,需要放行时用 --permission-mode auto-edit|auto 或 --allow <规则>",
67
70
  },
68
71
  rpc: {
72
+ badTaskId: "taskId 应为字符串",
69
73
  unknownCommand: (type) => `未知命令:${type}`,
70
74
  parseFailed: (error) => `JSON 解析失败:${error}`,
71
75
  missingType: "缺少 type",
@@ -36,6 +36,8 @@ export declare const en: {
36
36
  tasks: string;
37
37
  agents: string;
38
38
  paste: string;
39
+ interruptArgs: string;
40
+ interrupt: string;
39
41
  exit: string;
40
42
  config: string;
41
43
  traceArgs: string;
@@ -54,6 +56,8 @@ export declare const en: {
54
56
  cacheUsage: string;
55
57
  taskStopped: (id: string) => string;
56
58
  tasksUsage: string;
59
+ interruptUsage: string;
60
+ interruptSent: (text: string) => string;
57
61
  newSession: (id: string) => string;
58
62
  resumed: (id: string, messages: number) => string;
59
63
  forked: (id: string) => string;
@@ -228,6 +232,8 @@ export declare const zh: {
228
232
  tasks: string;
229
233
  agents: string;
230
234
  paste: string;
235
+ interruptArgs: string;
236
+ interrupt: string;
231
237
  exit: string;
232
238
  config: string;
233
239
  traceArgs: string;
@@ -245,6 +251,8 @@ export declare const zh: {
245
251
  cacheUsage: string;
246
252
  taskStopped: (id: string) => string;
247
253
  tasksUsage: string;
254
+ interruptUsage: string;
255
+ interruptSent: (text: string) => string;
248
256
  newSession: (id: string) => string;
249
257
  resumed: (id: string, messages: number) => string;
250
258
  forked: (id: string) => string;
@@ -33,9 +33,11 @@ export const en = {
33
33
  statusline: "Footer info two lines / one line (Ctrl+G)",
34
34
  planArgs: "[goal] | approve [mode|fresh] | reject",
35
35
  plan: "Show the plan and status; with a goal, enter Plan mode; approve / discard a pending plan",
36
- tasks: "Sub-agent tasks: status, output, stop",
36
+ tasks: "Sub-agent tasks: status, output, stop, background",
37
37
  agents: "Sub-agent types and external agents (installed, version)",
38
38
  paste: "Paste an image from the clipboard (Ctrl+V)",
39
+ interruptArgs: "<text>",
40
+ interrupt: "Interrupt the current turn and send this now, queued steers first (Ctrl+X)",
39
41
  exit: "Exit",
40
42
  config: "Settings panel; key=value sets one item directly (user level)",
41
43
  traceArgs: "[task id]",
@@ -53,7 +55,9 @@ export const en = {
53
55
  warmingSet: (mode) => `Warming: ${mode} (this session)`,
54
56
  cacheUsage: "usage: /cache [warm off|streaming|idle | fingerprint]",
55
57
  taskStopped: (id) => `Stopped ${id}`,
56
- tasksUsage: "usage: /tasks [id] | /tasks stop <id>",
58
+ tasksUsage: "usage: /tasks [id] | /tasks stop <id> | /tasks bg [id]",
59
+ interruptUsage: "usage: /interrupt <text>",
60
+ interruptSent: (text) => `Interrupted; sending now: ${text}`,
57
61
  newSession: (id) => `New session ${id}`,
58
62
  resumed: (id, messages) => `Resumed session ${id} (${plural(messages, "message")})`,
59
63
  forked: (id) => `Forked to new session ${id}`,
@@ -276,9 +280,11 @@ export const zh = {
276
280
  statusline: "底部信息行两行 / 一行(Ctrl+G)",
277
281
  planArgs: "[目标] | approve [模式|fresh] | reject",
278
282
  plan: "查看计划与状态;带目标进入 Plan 模式;批准 / 放弃待审批的计划",
279
- tasks: "子 Agent 任务:状态、输出、停止",
283
+ tasks: "子 Agent 任务:状态、输出、停止、转后台",
280
284
  agents: "子 Agent 类型与外部 Agent(安装状态、版本)",
281
285
  paste: "粘贴剪贴板里的图片(Ctrl+V)",
286
+ interruptArgs: "<文本>",
287
+ interrupt: "打断当前回合并立即发送这段文字,排队的插话在前(Ctrl+X)",
282
288
  exit: "退出",
283
289
  config: "设置面板;key=value 直接设一项(用户级)",
284
290
  traceArgs: "[任务 id]",
@@ -295,7 +301,9 @@ export const zh = {
295
301
  warmingSet: (mode) => `保温:${mode}(本会话)`,
296
302
  cacheUsage: "用法:/cache [warm off|streaming|idle | fingerprint]",
297
303
  taskStopped: (id) => `已停止 ${id}`,
298
- tasksUsage: "用法:/tasks [id] | /tasks stop <id>",
304
+ tasksUsage: "用法:/tasks [id] | /tasks stop <id> | /tasks bg [id]",
305
+ interruptUsage: "用法:/interrupt <文本>",
306
+ interruptSent: (text) => `已打断,立即发送:${text}`,
299
307
  newSession: (id) => `已新建会话 ${id}`,
300
308
  resumed: (id, messages) => `已恢复会话 ${id}(${messages} 条消息)`,
301
309
  forked: (id) => `已分叉到新会话 ${id}`,
@@ -25,8 +25,10 @@ export declare const en: {
25
25
  "ui.showThinking": string;
26
26
  "ui.compact": string;
27
27
  "ui.animation": string;
28
+ "ui.logo": string;
28
29
  "ui.statusLine": string;
29
30
  "ui.restoreOnCancel": string;
31
+ "ui.enterWhileRunning": string;
30
32
  "ui.quietStartup": string;
31
33
  "ui.ascii": string;
32
34
  "ui.language": string;
@@ -84,6 +86,8 @@ export declare const en: {
84
86
  "agents.sessionBudgetUsd": string;
85
87
  "subagents.maxConcurrent": string;
86
88
  "subagents.maxPending": string;
89
+ "subagents.background": string;
90
+ "subagents.autoBackgroundAfterMs": string;
87
91
  "memory.enabled": string;
88
92
  "memory.subagents": string;
89
93
  };
@@ -199,8 +203,10 @@ export declare const zh: {
199
203
  "ui.showThinking": string;
200
204
  "ui.compact": string;
201
205
  "ui.animation": string;
206
+ "ui.logo": string;
202
207
  "ui.statusLine": string;
203
208
  "ui.restoreOnCancel": string;
209
+ "ui.enterWhileRunning": string;
204
210
  "ui.quietStartup": string;
205
211
  "ui.ascii": string;
206
212
  "ui.language": string;
@@ -258,6 +264,8 @@ export declare const zh: {
258
264
  "agents.sessionBudgetUsd": string;
259
265
  "subagents.maxConcurrent": string;
260
266
  "subagents.maxPending": string;
267
+ "subagents.background": string;
268
+ "subagents.autoBackgroundAfterMs": string;
261
269
  "memory.enabled": string;
262
270
  "memory.subagents": string;
263
271
  };
@@ -25,8 +25,10 @@ export const en = {
25
25
  "ui.showThinking": "Thinking display",
26
26
  "ui.compact": "Compact layout",
27
27
  "ui.animation": "Spinner animation",
28
+ "ui.logo": "Startup logo",
28
29
  "ui.statusLine": "Status line",
29
30
  "ui.restoreOnCancel": "Restore on cancel",
31
+ "ui.enterWhileRunning": "Enter while running",
30
32
  "ui.quietStartup": "Startup screen",
31
33
  "ui.ascii": "ASCII glyphs",
32
34
  "ui.language": "Interface language",
@@ -84,6 +86,8 @@ export const en = {
84
86
  "agents.sessionBudgetUsd": "External agent budget",
85
87
  "subagents.maxConcurrent": "Subagents in parallel",
86
88
  "subagents.maxPending": "Subagent queue limit",
89
+ "subagents.background": "Subagents in background",
90
+ "subagents.autoBackgroundAfterMs": "Auto-background after (ms)",
87
91
  "memory.enabled": "Memory",
88
92
  "memory.subagents": "Memory in subagents",
89
93
  },
@@ -193,8 +197,10 @@ export const zh = {
193
197
  "ui.showThinking": "思考内容",
194
198
  "ui.compact": "紧凑布局",
195
199
  "ui.animation": "spinner 动画",
200
+ "ui.logo": "启动字符画",
196
201
  "ui.statusLine": "底部信息行",
197
202
  "ui.restoreOnCancel": "中断后放回原消息",
203
+ "ui.enterWhileRunning": "运行中按 Enter",
198
204
  "ui.quietStartup": "启动画面",
199
205
  "ui.ascii": "ASCII 字形",
200
206
  "ui.language": "界面语言",
@@ -252,6 +258,8 @@ export const zh = {
252
258
  "agents.sessionBudgetUsd": "外部 Agent 预算",
253
259
  "subagents.maxConcurrent": "子 Agent 并发",
254
260
  "subagents.maxPending": "子 Agent 排队上限",
261
+ "subagents.background": "子 Agent 缺省后台",
262
+ "subagents.autoBackgroundAfterMs": "自动转后台(毫秒)",
255
263
  "memory.enabled": "记忆",
256
264
  "memory.subagents": "子 Agent 的记忆",
257
265
  },
@@ -48,6 +48,8 @@ export declare const en: {
48
48
  listFailed: (provider: string, error: string) => string;
49
49
  found: (provider: string, count: number, url: string) => string;
50
50
  unmatched: string;
51
+ fromBackend: string;
52
+ noBackendWindow: (ids: string) => string;
51
53
  image: string;
52
54
  reasoning: string;
53
55
  noTools: string;
@@ -101,6 +103,8 @@ export declare const zh: {
101
103
  listFailed: (provider: string, error: string) => string;
102
104
  found: (provider: string, count: number, url: string) => string;
103
105
  unmatched: string;
106
+ fromBackend: string;
107
+ noBackendWindow: (ids: string) => string;
104
108
  image: string;
105
109
  reasoning: string;
106
110
  noTools: string;
@@ -56,6 +56,8 @@ export const en = {
56
56
  listFailed: (provider, error) => `ama: failed to fetch the model list of ${provider}: ${error}\n`,
57
57
  found: (provider, count, url) => `${provider}: found ${plural(count, "model")} (${url})\n`,
58
58
  unmatched: " models.dev: no match",
59
+ fromBackend: " (backend)",
60
+ noBackendWindow: (ids) => `The backend did not report a context window for ${ids}; using models.dev (128k when unmatched)\n`,
59
61
  image: " · image",
60
62
  reasoning: " · reasoning",
61
63
  noTools: " · no tool calling",
@@ -116,6 +118,8 @@ export const zh = {
116
118
  listFailed: (provider, error) => `ama: ${provider} 模型列表获取失败:${error}\n`,
117
119
  found: (provider, count, url) => `${provider}:发现 ${count} 个模型(${url})\n`,
118
120
  unmatched: " models.dev 未匹配",
121
+ fromBackend: "(后端)",
122
+ noBackendWindow: (ids) => `后端没有给出 ${ids} 的上下文窗口,改用 models.dev 的值(未匹配时按 128k)\n`,
119
123
  image: " · 图片",
120
124
  reasoning: " · 思考",
121
125
  noTools: " · 不支持工具调用",
@@ -280,6 +280,8 @@ export declare const en: {
280
280
  listFailed: (provider: string, error: string) => string;
281
281
  found: (provider: string, count: number, url: string) => string;
282
282
  unmatched: string;
283
+ fromBackend: string;
284
+ noBackendWindow: (ids: string) => string;
283
285
  image: string;
284
286
  reasoning: string;
285
287
  noTools: string;
@@ -564,6 +566,8 @@ export declare const zh: {
564
566
  listFailed: (provider: string, error: string) => string;
565
567
  found: (provider: string, count: number, url: string) => string;
566
568
  unmatched: string;
569
+ fromBackend: string;
570
+ noBackendWindow: (ids: string) => string;
567
571
  image: string;
568
572
  reasoning: string;
569
573
  noTools: string;
package/dist/index.d.ts CHANGED
@@ -38,6 +38,7 @@ export { createAgentSession, createRuntime } from "./sdk.js";
38
38
  export type { CreateSessionOptions, RuntimeOptions, SessionAuth } from "./sdk.js";
39
39
  export type { PlanDecision, PlanResponse, PlanResponseResult, SdkAgentSession, SessionPlanApi, SessionPlanOptions, } from "./sdk.js";
40
40
  export { AgentSessionImpl } from "./agent/session.js";
41
+ export type { BackgroundReason } from "./agent/subagent-background.js";
41
42
  export { SessionManager } from "./session/manager.js";
42
43
  export { ProviderRegistry } from "./ai/providers/registry.js";
43
44
  export { FakeProvider } from "./ai/fake/fake-provider.js";
@@ -22,6 +22,7 @@ import { pasteImage } from "./interactive/clipboard-paste.js";
22
22
  import { planCommand } from "./interactive/plan-command.js";
23
23
  import { rewindCommand } from "./interactive/rewind-command.js";
24
24
  import { describeAgents, describeTaskOutput, describeTasks, stopTask, } from "./interactive/tasks-report.js";
25
+ import { backgroundTasks, backgroundedText } from "./interactive/task-background.js";
25
26
  import { describeCache, describeFingerprint, describeSession } from "./session-report.js";
26
27
  import { msg } from "../i18n/index.js";
27
28
  export { describeSession } from "./session-report.js";
@@ -63,9 +64,10 @@ export const BUILTIN_COMMANDS = [
63
64
  command("cache", "cache", "[warm off|streaming|idle | fingerprint]"),
64
65
  command("statusline", "statusline", "[full|compact]"),
65
66
  command("plan", "plan", { key: "planArgs" }),
66
- command("tasks", "tasks", "[id] | stop <id>"),
67
+ command("tasks", "tasks", "[id] | stop <id> | bg [id]"),
67
68
  command("agents", "agents"),
68
69
  command("paste", "paste"),
70
+ command("interrupt", "interrupt", { key: "interruptArgs" }),
69
71
  command("exit", "exit"),
70
72
  // [W6-C0] 第六波(W6-S / W6-T1 / W6-M 实现)
71
73
  command("config", "config", "[key=value]"),
@@ -110,12 +112,15 @@ function cacheCommand(session, args) {
110
112
  }
111
113
  throw new AmaError("invalid_arguments", msg().report.command.cacheUsage);
112
114
  }
113
- /** `/tasks`、`/tasks <id>`、`/tasks stop <id>`。 */
114
- async function tasksCommand(sessionId, args) {
115
+ /** `/tasks`、`/tasks <id>`、`/tasks stop <id>`、`/tasks bg [id]`([W7-C] 无 id = 全部前台任务)。 */
116
+ async function tasksCommand(session, args) {
117
+ const sessionId = session.state.sessionId;
115
118
  const [first, second, extra] = args.split(/\s+/).filter((s) => s !== "");
116
119
  const now = Date.now();
117
120
  if (first === undefined)
118
121
  return describeTasks(sessionId, now);
122
+ if (first === "bg" && extra === undefined)
123
+ return backgroundedText(backgroundTasks(session, second));
119
124
  if (first === "stop" && second !== undefined && extra === undefined) {
120
125
  await stopTask(sessionId, second);
121
126
  return msg().report.command.taskStopped(second);
@@ -241,7 +246,17 @@ export async function runSlashCommand(line, ctx) {
241
246
  case "plan":
242
247
  return planCommand(session, args, ctx);
243
248
  case "tasks":
244
- return { kind: "handled", message: await tasksCommand(session.state.sessionId, args) };
249
+ return { kind: "handled", message: await tasksCommand(session, args) };
250
+ case "interrupt": {
251
+ // 打断并立即发送:运行中中止当前回合、以「排队的插话 + 本条」开新回合;空闲时就是普通提示
252
+ if (args === "")
253
+ throw new AmaError("invalid_arguments", msg().report.command.interruptUsage);
254
+ const { isStreaming, isCompacting } = session.state;
255
+ if (!isStreaming && !isCompacting)
256
+ return { kind: "prompt", text: args };
257
+ void session.prompt(args, { interrupt: true }).catch(() => undefined);
258
+ return { kind: "handled", message: msg().report.command.interruptSent(args) };
259
+ }
245
260
  case "agents":
246
261
  return { kind: "handled", message: describeAgents(session.state.sessionId) };
247
262
  case "paste": {
@@ -13,7 +13,9 @@
13
13
  * - 显示条件:有排队 / 运行中 / 等审批的任务,或本会话里看着结束、还没查看过的任务(结束后最多 10 分钟);
14
14
  * `ui.agentBar: "off"`(嵌入宿主缺省)整个不显示。
15
15
  * - 聚焦(`Ctrl+B` / 空输入 `↓` / `/tasks`):列出本会话全部任务,`›` 标当前项,窗口跟着选择滚动,
16
- * 末行是按键提示。按键处理在 agent-ui.ts。
16
+ * 末行是按键提示(`↑↓ 选择 · Enter 打开 · b 转后台 · x 停止 · Esc 返回`,放不下时丢 b / x 说明)。
17
+ * 按键处理在 agent-ui.ts。
18
+ * - [W7-C] 等审批的行(含停靠在栏里的后台任务审批)整行警告色。
17
19
  * - 状态来自任务注册表(`TaskInfo`、`live().queued`)、子 Agent 折叠视图的跟踪(轮数、最近工具、用时,界面时钟)
18
20
  * 与 `permission_request.context.taskId`(等审批)。
19
21
  */
@@ -13,12 +13,14 @@
13
13
  * - 显示条件:有排队 / 运行中 / 等审批的任务,或本会话里看着结束、还没查看过的任务(结束后最多 10 分钟);
14
14
  * `ui.agentBar: "off"`(嵌入宿主缺省)整个不显示。
15
15
  * - 聚焦(`Ctrl+B` / 空输入 `↓` / `/tasks`):列出本会话全部任务,`›` 标当前项,窗口跟着选择滚动,
16
- * 末行是按键提示。按键处理在 agent-ui.ts。
16
+ * 末行是按键提示(`↑↓ 选择 · Enter 打开 · b 转后台 · x 停止 · Esc 返回`,放不下时丢 b / x 说明)。
17
+ * 按键处理在 agent-ui.ts。
18
+ * - [W7-C] 等审批的行(含停靠在栏里的后台任务审批)整行警告色。
17
19
  * - 状态来自任务注册表(`TaskInfo`、`live().queued`)、子 Agent 折叠视图的跟踪(轮数、最近工具、用时,界面时钟)
18
20
  * 与 `permission_request.context.taskId`(等审批)。
19
21
  */
20
22
  import { msg } from "../../i18n/index.js";
21
- import { formatElapsed, truncateToWidth } from "../../tui.js";
23
+ import { formatElapsed, truncateToWidth, visibleWidth, } from "../../tui.js";
22
24
  export const BAR_ROWS = 3;
23
25
  /** 结束后未查看的任务在栏里保留多久。 */
24
26
  export const BAR_RETAIN_MS = 10 * 60_000;
@@ -224,8 +226,11 @@ export class AgentBar {
224
226
  const tail = [];
225
227
  if (hidden > 0)
226
228
  tail.push(m.bar.more(hidden));
227
- if (focused)
228
- tail.push(m.bar.keys(t.glyphs.arrowUp, t.glyphs.arrowDown));
229
+ if (focused) {
230
+ const [up, down] = [t.glyphs.arrowUp, t.glyphs.arrowDown];
231
+ const full = [...tail, m.bar.keysFull(up, down)].join(" · ");
232
+ tail.push(visibleWidth(full) <= width ? m.bar.keysFull(up, down) : m.bar.keys(up, down));
233
+ }
229
234
  if (tail.length > 0)
230
235
  out.push(truncateToWidth(t.fg("dim", tail.join(" · ")), width, t.glyphs.ellipsis));
231
236
  return out;
@@ -236,7 +241,9 @@ export class AgentBar {
236
241
  const agent = agentLabel(row);
237
242
  const lead = focused ? (selected ? t.fg("accent", g.prompt) : " ") + " " : "";
238
243
  const marker = t.fg(statusColor(row.status), g.tool);
239
- const id = selected ? t.bold(row.taskId) : row.taskId;
244
+ const approval = row.status === "approval";
245
+ const plainId = selected || approval ? t.bold(row.taskId) : row.taskId;
246
+ const id = approval ? t.fg("warning", plainId) : plainId;
240
247
  const description = row.description.replace(/\s+/g, " ").trim();
241
248
  const text = `${lead}${marker} ${id} ${t.fg("tool", agent)}` +
242
249
  t.fg("dim", " · ") +