@armadra/agent 0.6.2 → 0.6.3
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 +63 -0
- package/CHANGELOG.zh-CN.md +44 -0
- package/README.md +168 -575
- package/README.zh-CN.md +165 -596
- package/dist/agent/session.d.ts +6 -0
- package/dist/agent/session.js +8 -0
- package/dist/agent/subagent-background.d.ts +75 -0
- package/dist/agent/subagent-background.js +209 -0
- package/dist/agent/subagent-registry.d.ts +24 -5
- package/dist/agent/subagent-registry.js +64 -92
- package/dist/agent/types-w5.d.ts +11 -1
- package/dist/agent/types.d.ts +5 -0
- package/dist/agents/builtin.js +0 -1
- package/dist/agents/external.js +0 -1
- package/dist/agents/parse.js +4 -3
- package/dist/agents/result.d.ts +7 -1
- package/dist/agents/result.js +20 -1
- package/dist/agents/task-control.d.ts +13 -2
- package/dist/agents/task-record.d.ts +13 -1
- package/dist/agents/task-record.js +32 -0
- package/dist/agents/types.d.ts +5 -1
- package/dist/ai/providers/discovered-cache.d.ts +10 -4
- package/dist/ai/providers/discovered-cache.js +30 -14
- package/dist/auth/chatgpt/backend-client.d.ts +6 -5
- package/dist/auth/chatgpt/backend-client.js +8 -7
- package/dist/bundle/ama.cjs +1691 -500
- package/dist/cli/compose-agents.d.ts +2 -1
- package/dist/cli/compose-agents.js +11 -2
- package/dist/cli/subcommands/models-discover.d.ts +1 -0
- package/dist/cli/subcommands/models-discover.js +12 -2
- package/dist/config/json-schema.js +9 -2
- package/dist/config/key-docs.js +2 -2
- package/dist/config/merge.d.ts +1 -1
- package/dist/config/merge.js +20 -3
- package/dist/config/schema-w5.js +4 -2
- package/dist/config/schema.js +2 -0
- package/dist/config/settings-registry.js +4 -0
- package/dist/config/types-w5.d.ts +10 -0
- package/dist/config/types-w5.js +2 -0
- package/dist/config/types.d.ts +3 -1
- package/dist/git/info.d.ts +19 -0
- package/dist/git/info.js +64 -8
- package/dist/i18n/catalog.d.ts +45 -8
- package/dist/i18n/messages/agents.d.ts +56 -0
- package/dist/i18n/messages/agents.js +58 -2
- package/dist/i18n/messages/config-keys.d.ts +6 -0
- package/dist/i18n/messages/config-keys.js +16 -10
- package/dist/i18n/messages/config.d.ts +6 -0
- package/dist/i18n/messages/interactive-startup.d.ts +0 -16
- package/dist/i18n/messages/interactive-startup.js +0 -16
- package/dist/i18n/messages/interactive.d.ts +23 -16
- package/dist/i18n/messages/interactive.js +25 -0
- package/dist/i18n/messages/print.d.ts +4 -0
- package/dist/i18n/messages/print.js +4 -0
- package/dist/i18n/messages/report.js +4 -4
- package/dist/i18n/messages/settings.d.ts +6 -0
- package/dist/i18n/messages/settings.js +6 -0
- package/dist/i18n/messages/subcommands-config.d.ts +4 -0
- package/dist/i18n/messages/subcommands-config.js +4 -0
- package/dist/i18n/messages/subcommands.d.ts +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/modes/commands-core.js +8 -4
- package/dist/modes/interactive/agent-bar.d.ts +3 -1
- package/dist/modes/interactive/agent-bar.js +12 -5
- package/dist/modes/interactive/agent-ui.d.ts +21 -3
- package/dist/modes/interactive/agent-ui.js +81 -12
- package/dist/modes/interactive/agent-view.d.ts +4 -0
- package/dist/modes/interactive/agent-view.js +14 -1
- package/dist/modes/interactive/approval-dock.d.ts +51 -0
- package/dist/modes/interactive/approval-dock.js +112 -0
- package/dist/modes/interactive/approval-ui.d.ts +43 -0
- package/dist/modes/interactive/approval-ui.js +64 -0
- package/dist/modes/interactive/commands.js +4 -1
- package/dist/modes/interactive/event-notices.d.ts +6 -1
- package/dist/modes/interactive/event-notices.js +7 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -2
- package/dist/modes/interactive/interactive-mode.js +33 -38
- package/dist/modes/interactive/key-dispatch.d.ts +21 -4
- package/dist/modes/interactive/key-dispatch.js +60 -8
- package/dist/modes/interactive/line/line-mode.js +5 -0
- package/dist/modes/interactive/run-indicator.d.ts +15 -0
- package/dist/modes/interactive/run-indicator.js +37 -5
- package/dist/modes/interactive/session-events.js +5 -1
- package/dist/modes/interactive/startup-header.d.ts +29 -14
- package/dist/modes/interactive/startup-header.js +93 -59
- package/dist/modes/interactive/startup-logo.d.ts +83 -0
- package/dist/modes/interactive/startup-logo.js +183 -0
- package/dist/modes/interactive/status-area.d.ts +18 -0
- package/dist/modes/interactive/status-area.js +67 -1
- package/dist/modes/interactive/status-bar.d.ts +9 -1
- package/dist/modes/interactive/status-bar.js +43 -11
- package/dist/modes/interactive/status-line.d.ts +2 -0
- package/dist/modes/interactive/status-line.js +11 -6
- package/dist/modes/interactive/status-quota.d.ts +44 -0
- package/dist/modes/interactive/status-quota.js +135 -0
- package/dist/modes/interactive/subagent-view.d.ts +1 -0
- package/dist/modes/interactive/subagent-view.js +8 -0
- package/dist/modes/interactive/task-background.d.ts +31 -0
- package/dist/modes/interactive/task-background.js +68 -0
- package/dist/modes/interactive/tool-view.d.ts +7 -1
- package/dist/modes/interactive/tool-view.js +24 -1
- package/dist/modes/print/print-mode.d.ts +11 -0
- package/dist/modes/print/print-mode.js +36 -1
- package/dist/modes/rpc/commands.d.ts +2 -1
- package/dist/modes/rpc/commands.js +9 -1
- package/dist/rpc.d.ts +13 -0
- package/dist/rpc.js +3 -0
- package/dist/tools/task-ctl.d.ts +2 -0
- package/dist/tools/task-ctl.js +7 -2
- package/dist/tools/task.d.ts +11 -0
- package/dist/tools/task.js +20 -2
- package/dist/tui/components/editor.d.ts +2 -0
- package/dist/tui/components/editor.js +4 -0
- package/dist/tui/components/loader.d.ts +5 -1
- package/dist/tui/components/loader.js +18 -5
- package/dist/tui/keybindings.d.ts +8 -3
- package/dist/tui/keybindings.js +8 -3
- package/docs/agents.md +52 -28
- package/docs/en/host-api.md +5 -1
- package/docs/en/providers.md +1 -1
- package/docs/en/rpc.md +19 -7
- package/docs/en/sessions.md +3 -1
- package/docs/en/tui.md +84 -66
- package/docs/host-api.md +5 -1
- package/docs/providers.md +4 -2
- package/docs/rpc.md +19 -7
- package/docs/sessions.md +2 -1
- package/docs/tui-design.md +42 -29
- package/docs/tui.md +67 -49
- package/package.json +1 -1
package/dist/bundle/ama.cjs
CHANGED
|
@@ -41,7 +41,7 @@ var AMA_VERSION;
|
|
|
41
41
|
var init_version = __esm({
|
|
42
42
|
"src/version.ts"() {
|
|
43
43
|
"use strict";
|
|
44
|
-
AMA_VERSION = true ? "0.6.
|
|
44
|
+
AMA_VERSION = true ? "0.6.3" : readPackageVersion();
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
@@ -117,7 +117,7 @@ function agentEntry(agents, agentId) {
|
|
|
117
117
|
const entry = agents[agentId];
|
|
118
118
|
return typeof entry === "object" && !Array.isArray(entry) ? entry : void 0;
|
|
119
119
|
}
|
|
120
|
-
var STATUS_LINE_MODES, IMAGE_RESIZE_MODES, PLAN_BASH_MODES_STRICT_FIRST, PLAN_UNATTENDED_MODES, AGENTS_RESERVED_KEYS, MODELS_ENABLED_REF;
|
|
120
|
+
var STATUS_LINE_MODES, IMAGE_RESIZE_MODES, PLAN_BASH_MODES_STRICT_FIRST, PLAN_UNATTENDED_MODES, AGENTS_RESERVED_KEYS, SUBAGENT_BACKGROUND_MODES, MODELS_ENABLED_REF;
|
|
121
121
|
var init_types_w5 = __esm({
|
|
122
122
|
"src/config/types-w5.ts"() {
|
|
123
123
|
"use strict";
|
|
@@ -126,6 +126,7 @@ var init_types_w5 = __esm({
|
|
|
126
126
|
PLAN_BASH_MODES_STRICT_FIRST = ["deny", "readonly", "ask"];
|
|
127
127
|
PLAN_UNATTENDED_MODES = ["stop", "approve"];
|
|
128
128
|
AGENTS_RESERVED_KEYS = ["maxConcurrent", "sessionBudgetUsd", "dirs"];
|
|
129
|
+
SUBAGENT_BACKGROUND_MODES = ["auto", "always", "never"];
|
|
129
130
|
MODELS_ENABLED_REF = /^[^/\s]+\/\S+$/;
|
|
130
131
|
}
|
|
131
132
|
});
|
|
@@ -898,6 +899,9 @@ Wrote ${path}: ${provider} +${plural(added, "model")}${kept > 0 ? `, ${kept} alr
|
|
|
898
899
|
found: (provider, count2, url) => `${provider}: found ${plural(count2, "model")} (${url})
|
|
899
900
|
`,
|
|
900
901
|
unmatched: " models.dev: no match",
|
|
902
|
+
fromBackend: " (backend)",
|
|
903
|
+
noBackendWindow: (ids) => `The backend did not report a context window for ${ids}; using models.dev (128k when unmatched)
|
|
904
|
+
`,
|
|
901
905
|
image: " · image",
|
|
902
906
|
reasoning: " · reasoning",
|
|
903
907
|
noTools: " · no tool calling",
|
|
@@ -971,6 +975,9 @@ Probing protocols: ${plural(count2, "model")} (${order}), at most ${plural(reque
|
|
|
971
975
|
found: (provider, count2, url) => `${provider}:发现 ${count2} 个模型(${url})
|
|
972
976
|
`,
|
|
973
977
|
unmatched: " models.dev 未匹配",
|
|
978
|
+
fromBackend: "(后端)",
|
|
979
|
+
noBackendWindow: (ids) => `后端没有给出 ${ids} 的上下文窗口,改用 models.dev 的值(未匹配时按 128k)
|
|
980
|
+
`,
|
|
974
981
|
image: " · 图片",
|
|
975
982
|
reasoning: " · 思考",
|
|
976
983
|
noTools: " · 不支持工具调用",
|
|
@@ -1274,7 +1281,7 @@ Estimated cost: ${estimate} (2 × ${tokens} tokens × catalog price)
|
|
|
1274
1281
|
needsYes: "ama: cache-probe sends two billed requests; add --yes in non-interactive environments\n",
|
|
1275
1282
|
requestFailed: (n, error2) => `ama: request ${n} failed: ${error2}
|
|
1276
1283
|
`,
|
|
1277
|
-
share: (
|
|
1284
|
+
share: (percent3) => ` (the second request read ${percent3}% of the prefix)`,
|
|
1278
1285
|
usageFields: (api, fields) => `usage fields (read for ${api}): ${fields.join(" / ")}`,
|
|
1279
1286
|
verdict: (verdict, share) => `Verdict: ${verdict}${share}`,
|
|
1280
1287
|
advice: (advice) => `Advice: ${advice}`
|
|
@@ -1526,7 +1533,7 @@ Estimated cost: ${estimate} (2 × ${tokens} tokens × catalog price)
|
|
|
1526
1533
|
needsYes: "ama: cache-probe 会发两次计费请求,非交互环境需加 --yes\n",
|
|
1527
1534
|
requestFailed: (n, error2) => `ama: 第 ${n} 次请求失败:${error2}
|
|
1528
1535
|
`,
|
|
1529
|
-
share: (
|
|
1536
|
+
share: (percent3) => `(第二次读到前缀的 ${percent3}%)`,
|
|
1530
1537
|
usageFields: (api, fields) => `usage 字段(${api} 读取):${fields.join(" / ")}`,
|
|
1531
1538
|
verdict: (verdict, share) => `判定:${verdict}${share}`,
|
|
1532
1539
|
advice: (advice) => `建议:${advice}`
|
|
@@ -1637,16 +1644,8 @@ var init_interactive_startup = __esm({
|
|
|
1637
1644
|
templates: (n) => plural(n, "template"),
|
|
1638
1645
|
host: (host) => `host ${host}`,
|
|
1639
1646
|
warnings: (n) => `${plural(n, "warning")} (ama doctor)`,
|
|
1640
|
-
hintCompact: "/help · Shift+Tab mode",
|
|
1641
|
-
keyModel: "Model",
|
|
1642
|
-
keyDir: "Folder",
|
|
1643
|
-
keyMode: "Mode",
|
|
1644
|
-
keyLoaded: "Loaded",
|
|
1645
|
-
keyHost: "Host",
|
|
1646
|
-
keyWarnings: "Warnings",
|
|
1647
1647
|
thinking: (level) => `thinking ${level}`,
|
|
1648
1648
|
preset: (preset) => `preset ${preset}`,
|
|
1649
|
-
warningsValue: (n) => `${n} (see ama doctor)`,
|
|
1650
1649
|
hint: "/help commands · Shift+Tab mode · Ctrl+O expand tool output"
|
|
1651
1650
|
},
|
|
1652
1651
|
ui: {
|
|
@@ -1683,16 +1682,8 @@ var init_interactive_startup = __esm({
|
|
|
1683
1682
|
templates: (n) => `${n} 模板`,
|
|
1684
1683
|
host: (host) => `宿主 ${host}`,
|
|
1685
1684
|
warnings: (n) => `警告 ${n} 条(ama doctor)`,
|
|
1686
|
-
hintCompact: "/help · Shift+Tab 切模式",
|
|
1687
|
-
keyModel: "模型",
|
|
1688
|
-
keyDir: "目录",
|
|
1689
|
-
keyMode: "模式",
|
|
1690
|
-
keyLoaded: "已加载",
|
|
1691
|
-
keyHost: "宿主",
|
|
1692
|
-
keyWarnings: "警告",
|
|
1693
1685
|
thinking: (level) => `思考 ${level}`,
|
|
1694
1686
|
preset: (preset) => `预设 ${preset}`,
|
|
1695
|
-
warningsValue: (n) => `${n} 条(ama doctor 查看)`,
|
|
1696
1687
|
hint: "/help 命令 · Shift+Tab 切模式 · Ctrl+O 展开工具输出"
|
|
1697
1688
|
},
|
|
1698
1689
|
ui: {
|
|
@@ -1888,6 +1879,7 @@ var init_interactive = __esm({
|
|
|
1888
1879
|
"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",
|
|
1889
1880
|
"Approval: 1–3 or ↑↓ Enter to choose, y allow a allow for this session n / Esc deny v full input",
|
|
1890
1881
|
"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",
|
|
1882
|
+
"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",
|
|
1891
1883
|
"Ctrl+V paste a clipboard image (inserts @path) Ctrl+G footer two rows / one row",
|
|
1892
1884
|
"Ctrl+C clear input (again to quit) Ctrl+D quit on empty input Tab complete @ reference a file"
|
|
1893
1885
|
].join("\n"),
|
|
@@ -1966,7 +1958,19 @@ var init_interactive = __esm({
|
|
|
1966
1958
|
compact: "Status line: compact (one row)",
|
|
1967
1959
|
cacheSilent: "n/a",
|
|
1968
1960
|
sandbox: "sandbox",
|
|
1969
|
-
cycleHint: "shift+tab to cycle"
|
|
1961
|
+
cycleHint: "shift+tab to cycle",
|
|
1962
|
+
/** [W6] 订阅配额行(full 第三行)与窄屏 / compact 短格式;标签自带分隔(英文冒号后空格)。 */
|
|
1963
|
+
quota: {
|
|
1964
|
+
session: "Session: ",
|
|
1965
|
+
reset: "Reset: ",
|
|
1966
|
+
weekly: "Weekly: ",
|
|
1967
|
+
weeklyReset: "Weekly Reset: ",
|
|
1968
|
+
window: (duration) => `${duration}: `,
|
|
1969
|
+
windowReset: (duration) => `${duration} Reset: `,
|
|
1970
|
+
short5h: "5h",
|
|
1971
|
+
shortWeek: "wk",
|
|
1972
|
+
pending: "Quota: shown after the first request"
|
|
1973
|
+
}
|
|
1970
1974
|
},
|
|
1971
1975
|
subagent: {
|
|
1972
1976
|
running: (elapsed) => `running ${elapsed}`,
|
|
@@ -2007,6 +2011,7 @@ var init_interactive = __esm({
|
|
|
2007
2011
|
"Shift+Tab / Tab(输入为空时)切换权限模式(进入 Bypass 前确认) Ctrl+L 模型 Ctrl+T 思考级别 Ctrl+O 展开工具输出与思考",
|
|
2008
2012
|
"审批:1–3 或 ↑↓ Enter 选择,y 允许 a 本会话允许同类 n / Esc 拒绝 v 完整输入",
|
|
2009
2013
|
"计划审批:1 批准 2 新上下文执行 3 继续修改 4 放弃并退出 Plan e 编辑计划 Esc 留在 Plan",
|
|
2014
|
+
"Ctrl+B 前台子 Agent 任务转后台(tmux 里 C-b C-b) ↓(空输入)Agent 栏:b 转后台 x 连按两次停止 Enter 打开",
|
|
2010
2015
|
"Ctrl+V 粘贴剪贴板图片(插入 @路径) Ctrl+G 底部信息行两行 / 一行",
|
|
2011
2016
|
"Ctrl+C 清空输入(再按退出) Ctrl+D 空输入时退出 Tab 补全 @ 引用文件"
|
|
2012
2017
|
].join("\n"),
|
|
@@ -2081,7 +2086,18 @@ var init_interactive = __esm({
|
|
|
2081
2086
|
compact: "状态栏:精简(一行)",
|
|
2082
2087
|
cacheSilent: "未报告",
|
|
2083
2088
|
sandbox: "沙箱",
|
|
2084
|
-
cycleHint: "shift+tab 切换"
|
|
2089
|
+
cycleHint: "shift+tab 切换",
|
|
2090
|
+
quota: {
|
|
2091
|
+
session: "5 小时:",
|
|
2092
|
+
reset: "重置:",
|
|
2093
|
+
weekly: "本周:",
|
|
2094
|
+
weeklyReset: "本周重置:",
|
|
2095
|
+
window: (duration) => `${duration}:`,
|
|
2096
|
+
windowReset: (duration) => `${duration}重置:`,
|
|
2097
|
+
short5h: "5h",
|
|
2098
|
+
shortWeek: "周",
|
|
2099
|
+
pending: "配额:首次请求后显示"
|
|
2100
|
+
}
|
|
2085
2101
|
},
|
|
2086
2102
|
subagent: {
|
|
2087
2103
|
running: (elapsed) => `运行中 ${elapsed}`,
|
|
@@ -2964,7 +2980,7 @@ var init_report = __esm({
|
|
|
2964
2980
|
statusline: "Footer info two lines / one line (Ctrl+G)",
|
|
2965
2981
|
planArgs: "[goal] | approve [mode|fresh] | reject",
|
|
2966
2982
|
plan: "Show the plan and status; with a goal, enter Plan mode; approve / discard a pending plan",
|
|
2967
|
-
tasks: "Sub-agent tasks: status, output, stop",
|
|
2983
|
+
tasks: "Sub-agent tasks: status, output, stop, background",
|
|
2968
2984
|
agents: "Sub-agent types and external agents (installed, version)",
|
|
2969
2985
|
paste: "Paste an image from the clipboard (Ctrl+V)",
|
|
2970
2986
|
exit: "Exit",
|
|
@@ -2984,7 +3000,7 @@ var init_report = __esm({
|
|
|
2984
3000
|
warmingSet: (mode) => `Warming: ${mode} (this session)`,
|
|
2985
3001
|
cacheUsage: "usage: /cache [warm off|streaming|idle | fingerprint]",
|
|
2986
3002
|
taskStopped: (id) => `Stopped ${id}`,
|
|
2987
|
-
tasksUsage: "usage: /tasks [id] | /tasks stop <id>",
|
|
3003
|
+
tasksUsage: "usage: /tasks [id] | /tasks stop <id> | /tasks bg [id]",
|
|
2988
3004
|
newSession: (id) => `New session ${id}`,
|
|
2989
3005
|
resumed: (id, messages) => `Resumed session ${id} (${plural(messages, "message")})`,
|
|
2990
3006
|
forked: (id) => `Forked to new session ${id}`,
|
|
@@ -3041,9 +3057,9 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3041
3057
|
missPrefix: "prefix changed",
|
|
3042
3058
|
missEvicted: "evicted by the server",
|
|
3043
3059
|
missNotice: (reason, tokens, cost2) => `Cache miss (${reason}): re-billed ${tokens} tokens${cost2 === void 0 ? "" : ` (about ${cost2})`}`,
|
|
3044
|
-
pressure: (
|
|
3045
|
-
pressureTurns: (
|
|
3046
|
-
pressureTokens: (
|
|
3060
|
+
pressure: (percent3) => `Context ${percent3}% used`,
|
|
3061
|
+
pressureTurns: (percent3, turns) => `Context ${percent3}% used, about ${plural(turns, "turn")} left (average of the last 5 turns)`,
|
|
3062
|
+
pressureTokens: (percent3, tokens) => `Context ${percent3}% used, ${tokens} tokens left`,
|
|
3047
3063
|
warmSent: (read2, cost2) => {
|
|
3048
3064
|
const parts = [
|
|
3049
3065
|
...read2 !== void 0 ? [`read ${read2} tokens`] : [],
|
|
@@ -3086,7 +3102,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3086
3102
|
keyMisses: "Misses",
|
|
3087
3103
|
keyWarming: "Warming",
|
|
3088
3104
|
keyContext: "Context",
|
|
3089
|
-
context: (
|
|
3105
|
+
context: (percent3, remaining, turns) => `${percent3}%${remaining !== void 0 ? `, ≈ ${remaining} tokens left` : ""}${turns !== void 0 ? ` ≈ ${plural(turns, "turn")}` : ""}`,
|
|
3090
3106
|
keySubtasks: "Subtasks",
|
|
3091
3107
|
subtasks: (count2, rate, rebilled) => `${plural(count2, "session")}, hit rate ${rate}${rebilled !== void 0 ? `, re-billed ${rebilled} tokens` : ""}`,
|
|
3092
3108
|
title: "Cache"
|
|
@@ -3099,14 +3115,14 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3099
3115
|
tasks: (total) => plural(total, "task"),
|
|
3100
3116
|
running: (count2) => `running ${count2}`,
|
|
3101
3117
|
status: (status, count2) => {
|
|
3102
|
-
const
|
|
3118
|
+
const labels2 = {
|
|
3103
3119
|
completed: "completed",
|
|
3104
3120
|
failed: "failed",
|
|
3105
3121
|
aborted: "stopped",
|
|
3106
3122
|
max_turns: "out of turns",
|
|
3107
3123
|
interrupted: "interrupted"
|
|
3108
3124
|
};
|
|
3109
|
-
return `${
|
|
3125
|
+
return `${labels2[status] ?? status} ${count2}`;
|
|
3110
3126
|
},
|
|
3111
3127
|
tasksLine: (parts) => `${parts.join(" · ")} (/tasks)`,
|
|
3112
3128
|
keySession: "Session",
|
|
@@ -3118,7 +3134,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3118
3134
|
keyUsage: "Usage",
|
|
3119
3135
|
usage: (input2, output, cacheRead, cacheWrite, cost2) => `input ${input2} · output ${output} · cache read ${cacheRead} · cache write ${cacheWrite} · ${cost2}`,
|
|
3120
3136
|
keyContext: "Context",
|
|
3121
|
-
context: (tokens, window2,
|
|
3137
|
+
context: (tokens, window2, percent3) => `${tokens} / ${window2} (${percent3}%)`,
|
|
3122
3138
|
keyAgents: "Sub-agents",
|
|
3123
3139
|
externalTitle: "External agents",
|
|
3124
3140
|
noFingerprint: "This session does not provide a prefix fingerprint",
|
|
@@ -3203,7 +3219,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3203
3219
|
statusline: "底部信息行两行 / 一行(Ctrl+G)",
|
|
3204
3220
|
planArgs: "[目标] | approve [模式|fresh] | reject",
|
|
3205
3221
|
plan: "查看计划与状态;带目标进入 Plan 模式;批准 / 放弃待审批的计划",
|
|
3206
|
-
tasks: "子 Agent
|
|
3222
|
+
tasks: "子 Agent 任务:状态、输出、停止、转后台",
|
|
3207
3223
|
agents: "子 Agent 类型与外部 Agent(安装状态、版本)",
|
|
3208
3224
|
paste: "粘贴剪贴板里的图片(Ctrl+V)",
|
|
3209
3225
|
exit: "退出",
|
|
@@ -3222,7 +3238,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3222
3238
|
warmingSet: (mode) => `保温:${mode}(本会话)`,
|
|
3223
3239
|
cacheUsage: "用法:/cache [warm off|streaming|idle | fingerprint]",
|
|
3224
3240
|
taskStopped: (id) => `已停止 ${id}`,
|
|
3225
|
-
tasksUsage: "用法:/tasks [id] | /tasks stop <id>",
|
|
3241
|
+
tasksUsage: "用法:/tasks [id] | /tasks stop <id> | /tasks bg [id]",
|
|
3226
3242
|
newSession: (id) => `已新建会话 ${id}`,
|
|
3227
3243
|
resumed: (id, messages) => `已恢复会话 ${id}(${messages} 条消息)`,
|
|
3228
3244
|
forked: (id) => `已分叉到新会话 ${id}`,
|
|
@@ -3277,9 +3293,9 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3277
3293
|
missPrefix: "前缀变化",
|
|
3278
3294
|
missEvicted: "服务端已淘汰",
|
|
3279
3295
|
missNotice: (reason, tokens, cost2) => `缓存未命中(${reason}):重计费 ${tokens} token${cost2 === void 0 ? "" : `(约 ${cost2})`}`,
|
|
3280
|
-
pressure: (
|
|
3281
|
-
pressureTurns: (
|
|
3282
|
-
pressureTokens: (
|
|
3296
|
+
pressure: (percent3) => `上下文已用 ${percent3}%`,
|
|
3297
|
+
pressureTurns: (percent3, turns) => `上下文已用 ${percent3}%,约剩 ${turns} 回合(按最近 5 回合均值)`,
|
|
3298
|
+
pressureTokens: (percent3, tokens) => `上下文已用 ${percent3}%,余量 ${tokens} token`,
|
|
3283
3299
|
warmSent: (read2, cost2) => {
|
|
3284
3300
|
const text = `${read2 !== void 0 ? `读 ${read2} token` : ""}${cost2 !== void 0 ? `${read2 !== void 0 ? "," : ""}${cost2}` : ""}`;
|
|
3285
3301
|
return `缓存保温已刷新${text !== "" ? `(${text})` : ""}`;
|
|
@@ -3319,7 +3335,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3319
3335
|
keyMisses: "未命中",
|
|
3320
3336
|
keyWarming: "保温",
|
|
3321
3337
|
keyContext: "上下文",
|
|
3322
|
-
context: (
|
|
3338
|
+
context: (percent3, remaining, turns) => `${percent3}%${remaining !== void 0 ? `,余量 ≈ ${remaining} token` : ""}${turns !== void 0 ? ` ≈ ${turns} 回合` : ""}`,
|
|
3323
3339
|
keySubtasks: "子任务",
|
|
3324
3340
|
subtasks: (count2, rate, rebilled) => `${count2} 个会话,命中率 ${rate}${rebilled !== void 0 ? `,重计费 ${rebilled} token` : ""}`,
|
|
3325
3341
|
title: "缓存"
|
|
@@ -3331,14 +3347,14 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3331
3347
|
tasks: (total) => `${total} 个任务`,
|
|
3332
3348
|
running: (count2) => `运行中 ${count2}`,
|
|
3333
3349
|
status: (status, count2) => {
|
|
3334
|
-
const
|
|
3350
|
+
const labels2 = {
|
|
3335
3351
|
completed: "完成",
|
|
3336
3352
|
failed: "失败",
|
|
3337
3353
|
aborted: "已停止",
|
|
3338
3354
|
max_turns: "轮数耗尽",
|
|
3339
3355
|
interrupted: "已中断"
|
|
3340
3356
|
};
|
|
3341
|
-
return `${
|
|
3357
|
+
return `${labels2[status] ?? status} ${count2}`;
|
|
3342
3358
|
},
|
|
3343
3359
|
tasksLine: (parts) => `${parts.join(" · ")}(/tasks)`,
|
|
3344
3360
|
keySession: "会话",
|
|
@@ -3350,7 +3366,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3350
3366
|
keyUsage: "用量",
|
|
3351
3367
|
usage: (input2, output, cacheRead, cacheWrite, cost2) => `输入 ${input2} · 输出 ${output} · 缓存读 ${cacheRead} · 缓存写 ${cacheWrite} · ${cost2}`,
|
|
3352
3368
|
keyContext: "上下文",
|
|
3353
|
-
context: (tokens, window2,
|
|
3369
|
+
context: (tokens, window2, percent3) => `${tokens} / ${window2}(${percent3}%)`,
|
|
3354
3370
|
keyAgents: "子 Agent",
|
|
3355
3371
|
externalTitle: "外部 Agent",
|
|
3356
3372
|
noFingerprint: "当前会话不提供前缀指纹",
|
|
@@ -3432,6 +3448,8 @@ var init_print = __esm({
|
|
|
3432
3448
|
retry: (attempt, max, seconds2, error2) => `ama: ↻ retry ${attempt}/${max} (in ${seconds2}s): ${error2}
|
|
3433
3449
|
`,
|
|
3434
3450
|
modelFailed: "model call failed",
|
|
3451
|
+
waitingTasks: (n) => `ama: waiting for ${plural(n, "background task")} and their notification turns (Ctrl+C stops them)
|
|
3452
|
+
`,
|
|
3435
3453
|
planPending: (version, where) => `ama: plan v${version} saved, awaiting approval (not executed): ${where}; -p does not approve on anyone's behalf — approve it in the interactive UI or via RPC plan_response, or set plan.unattended: approve to let -p approve and continue`,
|
|
3436
3454
|
limitTurns: (limit) => `ama: reached the turn limit ${limit} (--max-turns / limits.maxTurns); run ended before finishing`,
|
|
3437
3455
|
limitCost: (limit, spent) => `ama: reached the cost limit ${limit} (spent ${spent}; --max-cost / limits.maxCostUsd); run ended before finishing`,
|
|
@@ -3441,6 +3459,7 @@ var init_print = __esm({
|
|
|
3441
3459
|
rpc: {
|
|
3442
3460
|
unknownCommand: (type) => `unknown command: ${type}`,
|
|
3443
3461
|
parseFailed: (error2) => `JSON parse failed: ${error2}`,
|
|
3462
|
+
badTaskId: "taskId must be a string",
|
|
3444
3463
|
missingType: "missing type",
|
|
3445
3464
|
unsupported: "this session does not support this command",
|
|
3446
3465
|
noPlan: "this session has no plan extension",
|
|
@@ -3471,6 +3490,8 @@ var init_print = __esm({
|
|
|
3471
3490
|
seconds: (n) => `${n} 秒`,
|
|
3472
3491
|
millis: (n) => `${n} 毫秒`,
|
|
3473
3492
|
needsPrompt: "ama: -p 需要提示(位置参数或 stdin 管道)\n",
|
|
3493
|
+
waitingTasks: (n) => `ama: 等待 ${n} 个后台任务及其通知回合结束(Ctrl+C 中止)
|
|
3494
|
+
`,
|
|
3474
3495
|
retry: (attempt, max, seconds2, error2) => `ama: ↻ 重试 ${attempt}/${max}(${seconds2}s 后):${error2}
|
|
3475
3496
|
`,
|
|
3476
3497
|
modelFailed: "模型调用失败",
|
|
@@ -3480,6 +3501,7 @@ var init_print = __esm({
|
|
|
3480
3501
|
denied: (count2, tools, reason) => `ama: ${count2} 次工具调用被拒:${tools.join("、")}${reason !== "" ? `(${reason})` : ""};-p 没有人审批,需要放行时用 --permission-mode auto-edit|auto 或 --allow <规则>`
|
|
3481
3502
|
},
|
|
3482
3503
|
rpc: {
|
|
3504
|
+
badTaskId: "taskId 应为字符串",
|
|
3483
3505
|
unknownCommand: (type) => `未知命令:${type}`,
|
|
3484
3506
|
parseFailed: (error2) => `JSON 解析失败:${error2}`,
|
|
3485
3507
|
missingType: "缺少 type",
|
|
@@ -3530,7 +3552,7 @@ var init_config_keys = __esm({
|
|
|
3530
3552
|
"limits.maxTurns": "unset: unlimited",
|
|
3531
3553
|
"limits.maxCostUsd": "unset: unlimited",
|
|
3532
3554
|
"ui.replyLanguage": "unset: no reply-language rule is appended (zero-byte change)",
|
|
3533
|
-
"ui.agentBar": "auto
|
|
3555
|
+
"ui.agentBar": "auto (embedding hosts turn it off in their profile)",
|
|
3534
3556
|
"auth.chatgpt.clientId": "siwc registers dynamically on first login; codex uses the public client id (AMA_CHATGPT_CLIENT_ID overrides)",
|
|
3535
3557
|
"auth.chatgpt.redirectPorts": "siwc 1455 → any free port; codex 1455 → 1457"
|
|
3536
3558
|
};
|
|
@@ -3553,7 +3575,7 @@ var init_config_keys = __esm({
|
|
|
3553
3575
|
"limits.maxTurns": "不设:不限",
|
|
3554
3576
|
"limits.maxCostUsd": "不设:不限",
|
|
3555
3577
|
"ui.replyLanguage": "不设:不追加回复语言规则(零字节变化)",
|
|
3556
|
-
"ui.agentBar": "
|
|
3578
|
+
"ui.agentBar": "auto(嵌入宿主要关在自己的 profile 写 off)",
|
|
3557
3579
|
"auth.chatgpt.clientId": "siwc 首次登录动态注册;codex 用公开客户端 id(AMA_CHATGPT_CLIENT_ID 覆盖)",
|
|
3558
3580
|
"auth.chatgpt.redirectPorts": "siwc 1455 → 任意空闲端口;codex 1455 → 1457"
|
|
3559
3581
|
};
|
|
@@ -3602,13 +3624,14 @@ var init_config_keys = __esm({
|
|
|
3602
3624
|
"ui.tuiMode": "Terminal interface layout (only regular for now)",
|
|
3603
3625
|
"ui.quietStartup": "How much the startup screen shows",
|
|
3604
3626
|
"ui.ascii": "ASCII glyphs (> * L, + - |); when unset it is detected: on when the locale lacks UTF-8, TERM=linux or a legacy conhost; AMA_ASCII=1/0 overrides",
|
|
3605
|
-
"ui.compact": "No blank lines between message blocks and no
|
|
3606
|
-
"ui.
|
|
3627
|
+
"ui.compact": "No blank lines between message blocks and no AMA logo in the startup header",
|
|
3628
|
+
"ui.logo": "AMA logo in the startup header: auto draws it when the terminal is at least 48 columns wide, off shows only the info lines",
|
|
3629
|
+
"ui.animation": "false: the spinner stays still while running and redraws only when seconds change; the startup logo does not animate",
|
|
3607
3630
|
"ui.restoreOnCancel": "When Esc interrupts a run before any reply or tool call in this turn, withdraw the turn and put the message back into the input box",
|
|
3608
3631
|
"ui.statusLine": "Bottom info line: full shows two lines (rate line + status line), compact one; toggle at runtime with Ctrl+G or /statusline (effective from wave 5 W5-A)",
|
|
3609
3632
|
"ui.language": "Interface language: auto decides from LC_ALL / LC_MESSAGES / LANG (zh* is Chinese, anything else English), zh, en; AMA_LANG and --lang override; affects the interface only, text sent to the model is always English",
|
|
3610
3633
|
"ui.replyLanguage": "Reply language for the model (e.g. Chinese): one English rule is appended to the end of the rules section at session start; zero-byte change when unset; user level only (effective from wave 6)",
|
|
3611
|
-
"ui.agentBar": "Agent bar (sub-agent list above the status line): auto shows it while tasks exist, off hides it;
|
|
3634
|
+
"ui.agentBar": "Agent bar (sub-agent list above the status line): auto shows it while tasks exist, off hides it; press ↓ on an empty input to enter it",
|
|
3612
3635
|
memory: "Cross-session memory (docs/memory.md): off by default, requests are byte-identical while off; project level can only set enabled: false (effective from wave 6 W6-M)",
|
|
3613
3636
|
"memory.enabled": "Master switch; --memory / --no-memory and AMA_MEMORY=0|1 override",
|
|
3614
3637
|
"memory.scopes": "Enabled scopes: user (data directory, across projects), project (keyed by a hash of the repository path)",
|
|
@@ -3655,10 +3678,12 @@ var init_config_keys = __esm({
|
|
|
3655
3678
|
"agents.maxConcurrent": "Total concurrency of external agents",
|
|
3656
3679
|
"agents.sessionBudgetUsd": "USD budget for external agents in this session",
|
|
3657
3680
|
"agents.dirs": "Extra sub-agent definition directories (*.md); accumulated across levels",
|
|
3658
|
-
subagents: "ama's own task sub-sessions; user level only (effective from wave 5 W5-G)",
|
|
3681
|
+
subagents: "ama's own task sub-sessions; user level only except background / autoBackgroundAfterMs (effective from wave 5 W5-G)",
|
|
3659
3682
|
"subagents.maxConcurrent": "Sub-sessions running at the same time",
|
|
3660
3683
|
"subagents.maxPending": "Queue limit; task fails beyond it",
|
|
3661
3684
|
"subagents.defaultModel": "Default sub-session model provider/model[@channel]",
|
|
3685
|
+
"subagents.background": "Whether task runs in the background by default: auto = background in the TUI / RPC / ACP and foreground with -p; always / never are fixed. The call argument and the agent type's background: override it; user, project and host level",
|
|
3686
|
+
"subagents.autoBackgroundAfterMs": "Move a foreground task to the background after it has run this many milliseconds; 0 disables; user and project level",
|
|
3662
3687
|
models: "Model aliases and the model picker list; user level only (effective from wave 5 W5-G)",
|
|
3663
3688
|
"models.aliases": "Models that model: fast / strong in sub-agent definitions point to",
|
|
3664
3689
|
"models.aliases.fast": "Model for the fast alias provider/model[@channel]",
|
|
@@ -3721,13 +3746,14 @@ var init_config_keys = __esm({
|
|
|
3721
3746
|
"ui.tuiMode": "终端界面形态(目前只有 regular)",
|
|
3722
3747
|
"ui.quietStartup": "启动画面详略",
|
|
3723
3748
|
"ui.ascii": "ASCII 字形(> * L、+ - |);不写时自动检测:区域设置不含 UTF-8、TERM=linux、旧 conhost 时开启;AMA_ASCII=1/0 覆盖",
|
|
3724
|
-
"ui.compact": "
|
|
3725
|
-
"ui.
|
|
3749
|
+
"ui.compact": "消息区块间不空行、启动头不画 AMA 字符画",
|
|
3750
|
+
"ui.logo": "启动头的 AMA 字符画:auto 在终端宽 48 列以上时画,off 只显示信息行",
|
|
3751
|
+
"ui.animation": "false:运行中 spinner 静止,只在秒数变化时重绘;启动字符画不播放动画",
|
|
3726
3752
|
"ui.restoreOnCancel": "运行中 Esc 中断、本回合还没有任何回复或工具调用时,撤回该回合并把原消息放回输入框",
|
|
3727
3753
|
"ui.statusLine": "底部信息行:full 两行(速率行 + 状态行),compact 一行;运行时 Ctrl+G 或 /statusline 切换(第五波 W5-A 起生效)",
|
|
3728
3754
|
"ui.language": "界面语言:auto 按 LC_ALL / LC_MESSAGES / LANG 判断(zh* 为中文,其余英文),zh,en;AMA_LANG、--lang 覆盖;只影响界面,发给模型的文本固定英文",
|
|
3729
3755
|
"ui.replyLanguage": "模型回复语言(如 Chinese):会话开始在 rules 节末尾追加一句英文规则;不设时零字节变化;只认用户级(第六波起生效)",
|
|
3730
|
-
"ui.agentBar": "Agent 栏(状态行上方的子 Agent 列表):auto 有任务时显示,off
|
|
3756
|
+
"ui.agentBar": "Agent 栏(状态行上方的子 Agent 列表):auto 有任务时显示,off 不显示;空输入时按 ↓ 进入",
|
|
3731
3757
|
memory: "跨会话记忆(docs/memory.md):缺省关闭,关闭时请求逐字节不变;项目级只能设 enabled: false(第六波 W6-M 起生效)",
|
|
3732
3758
|
"memory.enabled": "总开关;--memory / --no-memory、AMA_MEMORY=0|1 覆盖",
|
|
3733
3759
|
"memory.scopes": "启用的作用域:user(数据目录,跨项目)、project(按仓库路径哈希)",
|
|
@@ -3774,10 +3800,12 @@ var init_config_keys = __esm({
|
|
|
3774
3800
|
"agents.maxConcurrent": "外部 Agent 的总并发",
|
|
3775
3801
|
"agents.sessionBudgetUsd": "本会话外部 Agent 的美元预算",
|
|
3776
3802
|
"agents.dirs": "追加的子 Agent 定义目录(*.md);各层累加",
|
|
3777
|
-
subagents: "ama 自己的 task
|
|
3803
|
+
subagents: "ama 自己的 task 子会话;除 background / autoBackgroundAfterMs 外只认用户级(第五波 W5-G 起生效)",
|
|
3778
3804
|
"subagents.maxConcurrent": "同时运行的子会话数",
|
|
3779
3805
|
"subagents.maxPending": "排队上限,超出时 task 报错",
|
|
3780
3806
|
"subagents.defaultModel": "子会话缺省模型 provider/model[@channel]",
|
|
3807
|
+
"subagents.background": "task 缺省是否后台:auto = TUI / RPC / ACP 下后台、-p 下前台;always / never 固定。调用参数与类型定义的 background: 优先;用户、项目、宿主级都认",
|
|
3808
|
+
"subagents.autoBackgroundAfterMs": "前台任务运行超过该毫秒数自动转后台;0 关闭;用户、项目级都认",
|
|
3781
3809
|
models: "模型别名与模型选择器清单;只认用户级(第五波 W5-G 起生效)",
|
|
3782
3810
|
"models.aliases": "子 Agent 定义里 model: fast / strong 指向的模型",
|
|
3783
3811
|
"models.aliases.fast": "fast 别名的模型 provider/model[@channel]",
|
|
@@ -4628,7 +4656,37 @@ var init_agents = __esm({
|
|
|
4628
4656
|
bar: {
|
|
4629
4657
|
more: (n) => `${n} more`,
|
|
4630
4658
|
keys: (up, down) => `${up}${down} select · Enter open · Esc back`,
|
|
4631
|
-
|
|
4659
|
+
/** [W7-C] 聚焦时的完整按键行(窄屏退回 `keys`)。 */
|
|
4660
|
+
keysFull: (up, down) => `${up}${down} select · Enter open · b background · x stop · Esc back`,
|
|
4661
|
+
empty: "No sub-agent tasks yet",
|
|
4662
|
+
/** [W7-A] 运行提示行的附加项(有子 Agent 任务时)。 */
|
|
4663
|
+
runHint: (down) => `${down} Agent bar`
|
|
4664
|
+
},
|
|
4665
|
+
/** [W7-A] 进栏键落空时的一行提示。 */
|
|
4666
|
+
focus: {
|
|
4667
|
+
busyInput: (down) => `Input is not empty; clear it and press ${down} for the Agent bar`,
|
|
4668
|
+
disabled: "Agent bar is off (ui.agentBar); use /tasks"
|
|
4669
|
+
},
|
|
4670
|
+
/** [W7-C] 前台任务转后台。 */
|
|
4671
|
+
background: {
|
|
4672
|
+
done: (ids) => `Moved to the background: ${ids}; you'll be notified when it finishes`,
|
|
4673
|
+
none: "No foreground task to move to the background",
|
|
4674
|
+
notForeground: (taskId) => `${taskId} is not a running foreground task`,
|
|
4675
|
+
runHint: (key) => `${key} to background`,
|
|
4676
|
+
timeout: (taskId, agent) => `${taskId} ${agent} ran long and moved to the background (subagents.autoBackgroundAfterMs)`,
|
|
4677
|
+
host: (taskId, agent) => `${taskId} ${agent} was moved to the background by the host`,
|
|
4678
|
+
moved: (elapsed) => `moved to the background · ${elapsed}`,
|
|
4679
|
+
started: "started in the background",
|
|
4680
|
+
interrupted: (ids) => `Interrupted (background task ${ids} keeps running; Esc doesn't affect it)`
|
|
4681
|
+
},
|
|
4682
|
+
/** [W7-C] 栏内 x 停止(双击确认)。 */
|
|
4683
|
+
stop: {
|
|
4684
|
+
confirm: (taskId) => `Press x again to stop ${taskId}`,
|
|
4685
|
+
ended: (taskId) => `${taskId} has already finished`
|
|
4686
|
+
},
|
|
4687
|
+
/** [W7-C] 后台任务的审批停靠在栏里。 */
|
|
4688
|
+
approval: {
|
|
4689
|
+
runHint: (down) => `${down} handle approval`
|
|
4632
4690
|
},
|
|
4633
4691
|
view: {
|
|
4634
4692
|
back: "Esc back",
|
|
@@ -4640,7 +4698,7 @@ var init_agents = __esm({
|
|
|
4640
4698
|
resumed: (taskId) => `Sent to ${taskId}; it continues in the background`,
|
|
4641
4699
|
sendFailed: (message) => `Could not send: ${message}`,
|
|
4642
4700
|
stopped: (taskId) => `Stopped ${taskId}`,
|
|
4643
|
-
commandsHere: "Only /tasks stop
|
|
4701
|
+
commandsHere: "Only /tasks stop and /tasks bg work here; press Esc to go back for other commands",
|
|
4644
4702
|
removed: (taskId) => `Task ${taskId} is gone`,
|
|
4645
4703
|
unknown: (taskId) => `No task ${taskId}`,
|
|
4646
4704
|
turn: (n) => `turn ${n}`,
|
|
@@ -4666,7 +4724,31 @@ var init_agents = __esm({
|
|
|
4666
4724
|
bar: {
|
|
4667
4725
|
more: (n) => `另 ${n} 个`,
|
|
4668
4726
|
keys: (up, down) => `${up}${down} 选择 · Enter 打开 · Esc 返回`,
|
|
4669
|
-
|
|
4727
|
+
keysFull: (up, down) => `${up}${down} 选择 · Enter 打开 · b 转后台 · x 停止 · Esc 返回`,
|
|
4728
|
+
empty: "还没有子 Agent 任务",
|
|
4729
|
+
runHint: (down) => `${down} Agent 栏`
|
|
4730
|
+
},
|
|
4731
|
+
focus: {
|
|
4732
|
+
busyInput: (down) => `输入框有字;清空后再按 ${down} 进 Agent 栏`,
|
|
4733
|
+
disabled: "Agent 栏已关闭(ui.agentBar),用 /tasks"
|
|
4734
|
+
},
|
|
4735
|
+
background: {
|
|
4736
|
+
done: (ids) => `已转后台:${ids},完成后会通知`,
|
|
4737
|
+
none: "没有可转后台的前台任务",
|
|
4738
|
+
notForeground: (taskId) => `${taskId} 不是运行中的前台任务`,
|
|
4739
|
+
runHint: (key) => `${key} 转后台`,
|
|
4740
|
+
timeout: (taskId, agent) => `${taskId} ${agent} 运行较久,已自动转后台(subagents.autoBackgroundAfterMs)`,
|
|
4741
|
+
host: (taskId, agent) => `${taskId} ${agent} 已由宿主转后台`,
|
|
4742
|
+
moved: (elapsed) => `已转后台 · ${elapsed}`,
|
|
4743
|
+
started: "已在后台启动",
|
|
4744
|
+
interrupted: (ids) => `已中断(后台任务 ${ids} 仍在运行,Esc 不影响)`
|
|
4745
|
+
},
|
|
4746
|
+
stop: {
|
|
4747
|
+
confirm: (taskId) => `再按 x 停止 ${taskId}`,
|
|
4748
|
+
ended: (taskId) => `${taskId} 已结束`
|
|
4749
|
+
},
|
|
4750
|
+
approval: {
|
|
4751
|
+
runHint: (down) => `${down} 处理审批`
|
|
4670
4752
|
},
|
|
4671
4753
|
view: {
|
|
4672
4754
|
back: "Esc 返回",
|
|
@@ -4678,7 +4760,7 @@ var init_agents = __esm({
|
|
|
4678
4760
|
resumed: (taskId) => `已发给 ${taskId},在后台继续`,
|
|
4679
4761
|
sendFailed: (message) => `发送失败:${message}`,
|
|
4680
4762
|
stopped: (taskId) => `已停止 ${taskId}`,
|
|
4681
|
-
commandsHere: "这里只能用 /tasks stop;其它命令按 Esc 返回后输入",
|
|
4763
|
+
commandsHere: "这里只能用 /tasks stop 与 /tasks bg;其它命令按 Esc 返回后输入",
|
|
4682
4764
|
removed: (taskId) => `任务 ${taskId} 已不存在`,
|
|
4683
4765
|
unknown: (taskId) => `没有任务 ${taskId}`,
|
|
4684
4766
|
turn: (n) => `第 ${n} 轮`,
|
|
@@ -4702,7 +4784,7 @@ var init_trace = __esm({
|
|
|
4702
4784
|
title: "Trace",
|
|
4703
4785
|
/** 顶部汇总行。 */
|
|
4704
4786
|
summary: (turns, requests, tools) => `${plural(turns, "turn")} · ${plural(requests, "request")} · ${plural(tools, "tool call")}`,
|
|
4705
|
-
cache: (
|
|
4787
|
+
cache: (percent3) => `cache ${percent3}`,
|
|
4706
4788
|
empty: "No turns yet",
|
|
4707
4789
|
/** 子轨迹标题(`/trace t2`)。 */
|
|
4708
4790
|
taskTitle: (taskId, agent) => `Trace · task ${taskId} ${agent}`,
|
|
@@ -4820,7 +4902,7 @@ var init_trace = __esm({
|
|
|
4820
4902
|
zh24 = {
|
|
4821
4903
|
title: "轨迹",
|
|
4822
4904
|
summary: (turns, requests, tools) => `${turns} 回合 · ${requests} 请求 · ${tools} 次工具`,
|
|
4823
|
-
cache: (
|
|
4905
|
+
cache: (percent3) => `缓存 ${percent3}`,
|
|
4824
4906
|
empty: "还没有回合",
|
|
4825
4907
|
taskTitle: (taskId, agent) => `轨迹 · 任务 ${taskId} ${agent}`,
|
|
4826
4908
|
taskNotFound: (taskId) => `本会话没有任务 ${taskId}(见 /tasks)`,
|
|
@@ -5156,7 +5238,7 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
|
|
|
5156
5238
|
expired: " access token expired (refreshed on next use)",
|
|
5157
5239
|
needsLogin: (provider) => ` sign-in expired: run ama auth login ${provider}`,
|
|
5158
5240
|
quota: (parts) => ` quota: ${parts}`,
|
|
5159
|
-
quotaWindow: (window2,
|
|
5241
|
+
quotaWindow: (window2, percent3, reset) => `${window2} ${percent3}%${reset !== void 0 ? ` (resets ${reset})` : ""}`,
|
|
5160
5242
|
window5h: "5h",
|
|
5161
5243
|
windowWeek: "weekly",
|
|
5162
5244
|
windowOther: (duration) => `${duration} window`,
|
|
@@ -5263,7 +5345,7 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
|
|
|
5263
5345
|
expired: " access token 已过期(下次使用时自动刷新)",
|
|
5264
5346
|
needsLogin: (provider) => ` 登录已失效:运行 ama auth login ${provider}`,
|
|
5265
5347
|
quota: (parts) => ` 配额:${parts}`,
|
|
5266
|
-
quotaWindow: (window2,
|
|
5348
|
+
quotaWindow: (window2, percent3, reset) => `${window2} ${percent3}%${reset !== void 0 ? `(${reset} 重置)` : ""}`,
|
|
5267
5349
|
window5h: "5 小时",
|
|
5268
5350
|
windowWeek: "周",
|
|
5269
5351
|
windowOther: (duration) => `${duration} 窗口`,
|
|
@@ -5311,6 +5393,7 @@ var init_settings = __esm({
|
|
|
5311
5393
|
"ui.showThinking": "Thinking display",
|
|
5312
5394
|
"ui.compact": "Compact layout",
|
|
5313
5395
|
"ui.animation": "Spinner animation",
|
|
5396
|
+
"ui.logo": "Startup logo",
|
|
5314
5397
|
"ui.statusLine": "Status line",
|
|
5315
5398
|
"ui.restoreOnCancel": "Restore on cancel",
|
|
5316
5399
|
"ui.quietStartup": "Startup screen",
|
|
@@ -5370,6 +5453,8 @@ var init_settings = __esm({
|
|
|
5370
5453
|
"agents.sessionBudgetUsd": "External agent budget",
|
|
5371
5454
|
"subagents.maxConcurrent": "Subagents in parallel",
|
|
5372
5455
|
"subagents.maxPending": "Subagent queue limit",
|
|
5456
|
+
"subagents.background": "Subagents in background",
|
|
5457
|
+
"subagents.autoBackgroundAfterMs": "Auto-background after (ms)",
|
|
5373
5458
|
"memory.enabled": "Memory",
|
|
5374
5459
|
"memory.subagents": "Memory in subagents"
|
|
5375
5460
|
},
|
|
@@ -5406,8 +5491,8 @@ var init_settings = __esm({
|
|
|
5406
5491
|
defaultChoice: "(unset: default)",
|
|
5407
5492
|
summaryTitle: "Settings changed",
|
|
5408
5493
|
summaryLine: (label2, from, to, scope) => `${label2}: ${from} → ${to} (${scope})`,
|
|
5409
|
-
summaryRestart: (
|
|
5410
|
-
summaryNextSession: (
|
|
5494
|
+
summaryRestart: (labels2) => `Takes effect after restart: ${labels2}`,
|
|
5495
|
+
summaryNextSession: (labels2) => `Takes effect in a new session (/new): ${labels2}`,
|
|
5411
5496
|
setDone: (key, value, scope) => `${key} = ${value} (${scope})`,
|
|
5412
5497
|
unsetDone: (key, value, scope) => `${key} reset (${scope}); now ${value}`,
|
|
5413
5498
|
stillOverridden: (key, source) => `${key} is still overridden by ${source}; the saved value applies once that is removed`,
|
|
@@ -5479,6 +5564,7 @@ var init_settings = __esm({
|
|
|
5479
5564
|
"ui.showThinking": "思考内容",
|
|
5480
5565
|
"ui.compact": "紧凑布局",
|
|
5481
5566
|
"ui.animation": "spinner 动画",
|
|
5567
|
+
"ui.logo": "启动字符画",
|
|
5482
5568
|
"ui.statusLine": "底部信息行",
|
|
5483
5569
|
"ui.restoreOnCancel": "中断后放回原消息",
|
|
5484
5570
|
"ui.quietStartup": "启动画面",
|
|
@@ -5538,6 +5624,8 @@ var init_settings = __esm({
|
|
|
5538
5624
|
"agents.sessionBudgetUsd": "外部 Agent 预算",
|
|
5539
5625
|
"subagents.maxConcurrent": "子 Agent 并发",
|
|
5540
5626
|
"subagents.maxPending": "子 Agent 排队上限",
|
|
5627
|
+
"subagents.background": "子 Agent 缺省后台",
|
|
5628
|
+
"subagents.autoBackgroundAfterMs": "自动转后台(毫秒)",
|
|
5541
5629
|
"memory.enabled": "记忆",
|
|
5542
5630
|
"memory.subagents": "子 Agent 的记忆"
|
|
5543
5631
|
},
|
|
@@ -5574,8 +5662,8 @@ var init_settings = __esm({
|
|
|
5574
5662
|
defaultChoice: "(不设:缺省)",
|
|
5575
5663
|
summaryTitle: "设置已修改",
|
|
5576
5664
|
summaryLine: (label2, from, to, scope) => `${label2}:${from} → ${to}(${scope})`,
|
|
5577
|
-
summaryRestart: (
|
|
5578
|
-
summaryNextSession: (
|
|
5665
|
+
summaryRestart: (labels2) => `以下项重启后生效:${labels2}`,
|
|
5666
|
+
summaryNextSession: (labels2) => `以下项新会话(/new)生效:${labels2}`,
|
|
5579
5667
|
setDone: (key, value, scope) => `${key} = ${value}(${scope})`,
|
|
5580
5668
|
unsetDone: (key, value, scope) => `已恢复 ${key}(${scope}),现为 ${value}`,
|
|
5581
5669
|
stillOverridden: (key, source) => `${key} 仍被 ${source} 覆盖,撤掉后写入的值才生效`,
|
|
@@ -6327,11 +6415,19 @@ function validateConfigW5(c, config) {
|
|
|
6327
6415
|
}
|
|
6328
6416
|
);
|
|
6329
6417
|
checkAgents(c, config);
|
|
6330
|
-
checkSection(
|
|
6331
|
-
c
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6418
|
+
checkSection(
|
|
6419
|
+
c,
|
|
6420
|
+
config,
|
|
6421
|
+
"subagents",
|
|
6422
|
+
["maxConcurrent", "maxPending", "defaultModel", "background", "autoBackgroundAfterMs"],
|
|
6423
|
+
(s2, p) => {
|
|
6424
|
+
c.number(s2, "maxConcurrent", p, 1, 64);
|
|
6425
|
+
c.number(s2, "maxPending", p, 0, 1024);
|
|
6426
|
+
c.string(s2, "defaultModel", p);
|
|
6427
|
+
c.oneOf(s2, "background", p, SUBAGENT_BACKGROUND_MODES);
|
|
6428
|
+
c.number(s2, "autoBackgroundAfterMs", p, 0);
|
|
6429
|
+
}
|
|
6430
|
+
);
|
|
6335
6431
|
checkSection(c, config, "models", ["aliases", "enabled"], (s2, p) => {
|
|
6336
6432
|
c.stringArray(s2, "enabled", p);
|
|
6337
6433
|
const enabled = s2["enabled"];
|
|
@@ -7002,6 +7098,7 @@ function validateConfig(value) {
|
|
|
7002
7098
|
"quietStartup",
|
|
7003
7099
|
"ascii",
|
|
7004
7100
|
"compact",
|
|
7101
|
+
"logo",
|
|
7005
7102
|
"animation",
|
|
7006
7103
|
"restoreOnCancel",
|
|
7007
7104
|
...W5_UI_KEYS,
|
|
@@ -7015,6 +7112,7 @@ function validateConfig(value) {
|
|
|
7015
7112
|
c.oneOf(s2, "quietStartup", p, ["normal", "header", "silent"]);
|
|
7016
7113
|
c.boolean(s2, "ascii", p);
|
|
7017
7114
|
c.boolean(s2, "compact", p);
|
|
7115
|
+
c.oneOf(s2, "logo", p, ["auto", "off"]);
|
|
7018
7116
|
c.boolean(s2, "animation", p);
|
|
7019
7117
|
c.boolean(s2, "restoreOnCancel", p);
|
|
7020
7118
|
checkUiW5(c, s2, p);
|
|
@@ -8260,6 +8358,25 @@ function restrictProjectConfig(project, currentMode, label2 = ".ama/config.json"
|
|
|
8260
8358
|
if (project.reminders !== void 0)
|
|
8261
8359
|
accepted.reminders = structuredClone(project.reminders);
|
|
8262
8360
|
break;
|
|
8361
|
+
case "subagents": {
|
|
8362
|
+
const subagents = project.subagents ?? {};
|
|
8363
|
+
const result = {};
|
|
8364
|
+
for (const sub of Object.keys(subagents)) {
|
|
8365
|
+
if (sub !== "background" && sub !== "autoBackgroundAfterMs")
|
|
8366
|
+
warnings.push(
|
|
8367
|
+
msg().config.merge.projectOnlyKeys(
|
|
8368
|
+
label2,
|
|
8369
|
+
"subagents.background / subagents.autoBackgroundAfterMs",
|
|
8370
|
+
`subagents.${sub}`
|
|
8371
|
+
)
|
|
8372
|
+
);
|
|
8373
|
+
}
|
|
8374
|
+
if (subagents.background !== void 0) result.background = subagents.background;
|
|
8375
|
+
if (subagents.autoBackgroundAfterMs !== void 0)
|
|
8376
|
+
result.autoBackgroundAfterMs = subagents.autoBackgroundAfterMs;
|
|
8377
|
+
if (Object.keys(result).length > 0) accepted.subagents = result;
|
|
8378
|
+
break;
|
|
8379
|
+
}
|
|
8263
8380
|
case "plan": {
|
|
8264
8381
|
const plan2 = restrictPlan(project.plan ?? {}, currentPlanBash, label2, warnings);
|
|
8265
8382
|
if (plan2 !== void 0) accepted.plan = plan2;
|
|
@@ -8512,8 +8629,9 @@ var init_merge = __esm({
|
|
|
8512
8629
|
skills: { dirs: [] }
|
|
8513
8630
|
});
|
|
8514
8631
|
PROFILE_DEFAULTS = Object.freeze({
|
|
8515
|
-
// [W5-A] 嵌入宿主以「最后一行 = 状态栏」锚定,底部信息行缺省单行;[
|
|
8516
|
-
|
|
8632
|
+
// [W5-A] 嵌入宿主以「最后一行 = 状态栏」锚定,底部信息行缺省单行;[W7-A] Agent 栏不再缺省关,
|
|
8633
|
+
// 宿主要关就在自己的 profile 写 `ui.agentBar: "off"`
|
|
8634
|
+
ui: { quietStartup: "header", statusLine: "compact" }
|
|
8517
8635
|
});
|
|
8518
8636
|
RULE_SOURCE = {
|
|
8519
8637
|
default: "builtin",
|
|
@@ -10865,8 +10983,8 @@ var init_event_stream = __esm({
|
|
|
10865
10983
|
resolveResult;
|
|
10866
10984
|
resultPromise;
|
|
10867
10985
|
constructor() {
|
|
10868
|
-
this.resultPromise = new Promise((
|
|
10869
|
-
this.resolveResult =
|
|
10986
|
+
this.resultPromise = new Promise((resolve39) => {
|
|
10987
|
+
this.resolveResult = resolve39;
|
|
10870
10988
|
});
|
|
10871
10989
|
}
|
|
10872
10990
|
/** 最近一个事件携带的部分消息。 */
|
|
@@ -10910,7 +11028,7 @@ var init_event_stream = __esm({
|
|
|
10910
11028
|
const value = this.queue.shift();
|
|
10911
11029
|
if (value) return Promise.resolve({ value, done: false });
|
|
10912
11030
|
if (this.closed) return Promise.resolve({ value: void 0, done: true });
|
|
10913
|
-
return new Promise((
|
|
11031
|
+
return new Promise((resolve39) => this.waiters.push(resolve39));
|
|
10914
11032
|
},
|
|
10915
11033
|
return: () => Promise.resolve({ value: void 0, done: true })
|
|
10916
11034
|
};
|
|
@@ -11603,22 +11721,22 @@ function chunks(text, size) {
|
|
|
11603
11721
|
return out;
|
|
11604
11722
|
}
|
|
11605
11723
|
function sleep(ms, signal) {
|
|
11606
|
-
return new Promise((
|
|
11724
|
+
return new Promise((resolve39) => {
|
|
11607
11725
|
if (signal.aborted || ms <= 0) {
|
|
11608
|
-
setTimeout(
|
|
11726
|
+
setTimeout(resolve39, 0);
|
|
11609
11727
|
return;
|
|
11610
11728
|
}
|
|
11611
11729
|
const timer = setTimeout(done, ms);
|
|
11612
11730
|
function done() {
|
|
11613
11731
|
clearTimeout(timer);
|
|
11614
11732
|
signal.removeEventListener("abort", done);
|
|
11615
|
-
|
|
11733
|
+
resolve39();
|
|
11616
11734
|
}
|
|
11617
11735
|
signal.addEventListener("abort", done, { once: true });
|
|
11618
11736
|
});
|
|
11619
11737
|
}
|
|
11620
11738
|
function tick() {
|
|
11621
|
-
return new Promise((
|
|
11739
|
+
return new Promise((resolve39) => setImmediate(resolve39));
|
|
11622
11740
|
}
|
|
11623
11741
|
var import_node_fs13, FAKE_PROVIDER_ID, FAKE_API_ID, FAKE_SCRIPT_ENV, FAKE_RECORD_ENV, FAKE_MODEL_BASE, FAKE_MODELS, AbortedError, FakeProvider, defaultFakeProvider, fakeApi;
|
|
11624
11742
|
var init_fake_provider = __esm({
|
|
@@ -14824,13 +14942,13 @@ function taskkillArgs(pid) {
|
|
|
14824
14942
|
return ["/PID", String(pid), "/T", "/F"];
|
|
14825
14943
|
}
|
|
14826
14944
|
function defaultTaskkill(args) {
|
|
14827
|
-
return new Promise((
|
|
14945
|
+
return new Promise((resolve39) => {
|
|
14828
14946
|
try {
|
|
14829
14947
|
const child = (0, import_node_child_process4.spawn)("taskkill", [...args], { stdio: "ignore", windowsHide: true });
|
|
14830
|
-
child.on("error", () =>
|
|
14831
|
-
child.on("exit", () =>
|
|
14948
|
+
child.on("error", () => resolve39());
|
|
14949
|
+
child.on("exit", () => resolve39());
|
|
14832
14950
|
} catch {
|
|
14833
|
-
|
|
14951
|
+
resolve39();
|
|
14834
14952
|
}
|
|
14835
14953
|
});
|
|
14836
14954
|
}
|
|
@@ -14902,7 +15020,7 @@ var init_process_tree = __esm({
|
|
|
14902
15020
|
import_node_os6 = require("node:os");
|
|
14903
15021
|
KILL_GRACE_MS2 = 2e3;
|
|
14904
15022
|
POLL_MS = 50;
|
|
14905
|
-
sleep3 = (ms) => new Promise((
|
|
15023
|
+
sleep3 = (ms) => new Promise((resolve39) => setTimeout(resolve39, ms));
|
|
14906
15024
|
tracked = /* @__PURE__ */ new Set();
|
|
14907
15025
|
exitHookInstalled = false;
|
|
14908
15026
|
}
|
|
@@ -15064,9 +15182,9 @@ var init_background_jobs = __esm({
|
|
|
15064
15182
|
notified: false,
|
|
15065
15183
|
stopping: false,
|
|
15066
15184
|
processDeps: options.processDeps,
|
|
15067
|
-
done: new Promise((
|
|
15185
|
+
done: new Promise((resolve39) => {
|
|
15068
15186
|
const finish2 = (code, signal) => {
|
|
15069
|
-
if (job.status !== "running") return
|
|
15187
|
+
if (job.status !== "running") return resolve39();
|
|
15070
15188
|
job.exitCode = exitCodeOf(code, signal);
|
|
15071
15189
|
job.endedAt = Date.now();
|
|
15072
15190
|
job.status = entry.stopping ? "stopped" : "exited";
|
|
@@ -15074,7 +15192,7 @@ var init_background_jobs = __esm({
|
|
|
15074
15192
|
if (pid !== void 0 && !isWindows && !isGroupAlive(pid, options.processDeps ?? {}))
|
|
15075
15193
|
untrackProcessGroup(pid);
|
|
15076
15194
|
this.notify({ phase: job.status === "stopped" ? "stopped" : "exited", job });
|
|
15077
|
-
|
|
15195
|
+
resolve39();
|
|
15078
15196
|
};
|
|
15079
15197
|
child.once("exit", finish2);
|
|
15080
15198
|
child.once("error", () => finish2(127, null));
|
|
@@ -15100,9 +15218,9 @@ var init_background_jobs = __esm({
|
|
|
15100
15218
|
let onAbort;
|
|
15101
15219
|
await Promise.race([
|
|
15102
15220
|
entry.done,
|
|
15103
|
-
new Promise((
|
|
15104
|
-
timer = setTimeout(
|
|
15105
|
-
onAbort = () =>
|
|
15221
|
+
new Promise((resolve39) => {
|
|
15222
|
+
timer = setTimeout(resolve39, Math.max(0, timeoutMs));
|
|
15223
|
+
onAbort = () => resolve39();
|
|
15106
15224
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
15107
15225
|
})
|
|
15108
15226
|
]);
|
|
@@ -15391,13 +15509,13 @@ function fail2(message) {
|
|
|
15391
15509
|
return { content: message, isError: true };
|
|
15392
15510
|
}
|
|
15393
15511
|
function waitForExit(child) {
|
|
15394
|
-
return new Promise((
|
|
15512
|
+
return new Promise((resolve39, reject2) => {
|
|
15395
15513
|
let exit;
|
|
15396
15514
|
let settled = false;
|
|
15397
15515
|
const done = () => {
|
|
15398
15516
|
if (settled || exit === void 0) return;
|
|
15399
15517
|
settled = true;
|
|
15400
|
-
|
|
15518
|
+
resolve39(exit);
|
|
15401
15519
|
};
|
|
15402
15520
|
child.once("error", (err) => {
|
|
15403
15521
|
if (!settled) {
|
|
@@ -16101,7 +16219,6 @@ function builtin(name, description, prompt, permissionMode) {
|
|
|
16101
16219
|
model: "inherit",
|
|
16102
16220
|
maxTurns: 30,
|
|
16103
16221
|
isolation: "none",
|
|
16104
|
-
background: false,
|
|
16105
16222
|
runner: "ama",
|
|
16106
16223
|
prompt,
|
|
16107
16224
|
source: "builtin"
|
|
@@ -16264,7 +16381,17 @@ function taskNotification(input2) {
|
|
|
16264
16381
|
${input2.report}
|
|
16265
16382
|
</task-notification>`;
|
|
16266
16383
|
}
|
|
16267
|
-
|
|
16384
|
+
function startedText(taskId, agent) {
|
|
16385
|
+
return `Started background task ${taskId} (agent ${agent}). ${NOTIFY_HINT}`;
|
|
16386
|
+
}
|
|
16387
|
+
function backgroundedText(reason, afterMs) {
|
|
16388
|
+
const head = reason === "timeout" ? `Still running after ${Math.round(afterMs / 1e3)}s and moved to the background` : "Moved to the background by the user";
|
|
16389
|
+
return `${head}; it was not interrupted. ${NOTIFY_HINT} Do not wait for it unless the user asks.`;
|
|
16390
|
+
}
|
|
16391
|
+
function waitDetachedText(taskId) {
|
|
16392
|
+
return `Task ${taskId} is still running and was moved to the background by the user; do not wait again — a <task-notification> arrives when it finishes.`;
|
|
16393
|
+
}
|
|
16394
|
+
var import_node_fs25, import_node_path34, TASK_RESULT_LIMIT_BYTES, HEAD_SHARE, MAX_TURNS_NOTE, NOTIFY_HINT, TASK_NOTIFICATION_RULE;
|
|
16268
16395
|
var init_result = __esm({
|
|
16269
16396
|
"src/agents/result.ts"() {
|
|
16270
16397
|
"use strict";
|
|
@@ -16273,7 +16400,8 @@ var init_result = __esm({
|
|
|
16273
16400
|
TASK_RESULT_LIMIT_BYTES = 50 * 1024;
|
|
16274
16401
|
HEAD_SHARE = 0.7;
|
|
16275
16402
|
MAX_TURNS_NOTE = "[Turn limit reached; the sub-agent's last output follows.]";
|
|
16276
|
-
|
|
16403
|
+
NOTIFY_HINT = "A <task-notification> arrives when it finishes; use task_ctl to wait, stop or read output.";
|
|
16404
|
+
TASK_NOTIFICATION_RULE = "A <task-notification> is a background task's report, not the user speaking; never sleep or poll for it.";
|
|
16277
16405
|
}
|
|
16278
16406
|
});
|
|
16279
16407
|
|
|
@@ -16281,6 +16409,9 @@ var init_result = __esm({
|
|
|
16281
16409
|
function bindTaskAgents(tool, catalog) {
|
|
16282
16410
|
if (tool !== void 0) catalogs.set(tool, catalog);
|
|
16283
16411
|
}
|
|
16412
|
+
function bindTaskBackground(tool, background) {
|
|
16413
|
+
if (tool !== void 0) backgrounds.set(tool, background);
|
|
16414
|
+
}
|
|
16284
16415
|
function fail3(message) {
|
|
16285
16416
|
return { content: message, isError: true };
|
|
16286
16417
|
}
|
|
@@ -16323,7 +16454,8 @@ function createTaskTool(_options = {}) {
|
|
|
16323
16454
|
label: "Task",
|
|
16324
16455
|
get description() {
|
|
16325
16456
|
const catalog = catalogs.get(tool) ?? new AgentCatalog();
|
|
16326
|
-
|
|
16457
|
+
const base4 = backgrounds.get(tool) === true ? BACKGROUND_DESCRIPTION : FOREGROUND_DESCRIPTION;
|
|
16458
|
+
return `${base4}${TASK_AGENTS_HEADING}${catalog.describe()}`;
|
|
16327
16459
|
},
|
|
16328
16460
|
parameters: {
|
|
16329
16461
|
type: "object",
|
|
@@ -16377,7 +16509,7 @@ function createTaskTool(_options = {}) {
|
|
|
16377
16509
|
};
|
|
16378
16510
|
return tool;
|
|
16379
16511
|
}
|
|
16380
|
-
var MAX_TASK_DEPTH, THINKING,
|
|
16512
|
+
var MAX_TASK_DEPTH, THINKING, FOREGROUND_DESCRIPTION, BACKGROUND_DESCRIPTION, TASK_AGENTS_HEADING, catalogs, backgrounds;
|
|
16381
16513
|
var init_task = __esm({
|
|
16382
16514
|
"src/tools/task.ts"() {
|
|
16383
16515
|
"use strict";
|
|
@@ -16392,9 +16524,11 @@ var init_task = __esm({
|
|
|
16392
16524
|
"high",
|
|
16393
16525
|
"xhigh"
|
|
16394
16526
|
];
|
|
16395
|
-
|
|
16527
|
+
FOREGROUND_DESCRIPTION = "Delegate to a sub-agent (fresh context; give full instructions). Returns its final report. Tasks in one reply run in parallel; writers should use isolation worktree. background: returns a taskId now (see task_ctl); taskId: continue that task.";
|
|
16528
|
+
BACKGROUND_DESCRIPTION = "Delegate to a sub-agent (fresh context; give full instructions). Runs in the background by default: returns a taskId; a <task-notification> follows when done, so keep working. background:false if your next step needs the result. taskId: continue a task. Tasks in one reply run in parallel; writers use isolation worktree.";
|
|
16396
16529
|
TASK_AGENTS_HEADING = "\nAgents:\n";
|
|
16397
16530
|
catalogs = /* @__PURE__ */ new WeakMap();
|
|
16531
|
+
backgrounds = /* @__PURE__ */ new WeakMap();
|
|
16398
16532
|
}
|
|
16399
16533
|
});
|
|
16400
16534
|
|
|
@@ -16492,7 +16626,9 @@ ${body}` };
|
|
|
16492
16626
|
}
|
|
16493
16627
|
case "wait": {
|
|
16494
16628
|
const timeout = Math.min(Math.max(input2.timeoutMs ?? DEFAULT_WAIT_MS, 0), MAX_WAIT_MS);
|
|
16495
|
-
const
|
|
16629
|
+
const signal = control.detachSignal(taskId);
|
|
16630
|
+
const result = await control.wait(taskId, timeout, { signal });
|
|
16631
|
+
if (result === void 0 && signal.aborted) return { content: waitDetachedText(taskId) };
|
|
16496
16632
|
if (result === void 0) {
|
|
16497
16633
|
const turns = control.get(taskId)?.turns ?? 0;
|
|
16498
16634
|
return {
|
|
@@ -16872,9 +17008,9 @@ async function execute(prepared, options, signal, emit, parent) {
|
|
|
16872
17008
|
const grace = options.abortGraceMs ?? DEFAULT_ABORT_GRACE_MS;
|
|
16873
17009
|
let onAbort;
|
|
16874
17010
|
let graceTimer;
|
|
16875
|
-
const abortRace = new Promise((
|
|
17011
|
+
const abortRace = new Promise((resolve39) => {
|
|
16876
17012
|
onAbort = () => {
|
|
16877
|
-
graceTimer = setTimeout(() =>
|
|
17013
|
+
graceTimer = setTimeout(() => resolve39(errorResult(ABORTED_TOOL_TEXT)), grace);
|
|
16878
17014
|
};
|
|
16879
17015
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
16880
17016
|
});
|
|
@@ -17279,7 +17415,7 @@ function retryDelayMs(attempt, settings) {
|
|
|
17279
17415
|
return Math.min(raw, settings.maxDelayMs);
|
|
17280
17416
|
}
|
|
17281
17417
|
function sleep4(ms, signal) {
|
|
17282
|
-
return new Promise((
|
|
17418
|
+
return new Promise((resolve39, reject2) => {
|
|
17283
17419
|
if (signal?.aborted === true) {
|
|
17284
17420
|
reject2(new AmaError("aborted", "aborted"));
|
|
17285
17421
|
return;
|
|
@@ -17287,7 +17423,7 @@ function sleep4(ms, signal) {
|
|
|
17287
17423
|
const timer = setTimeout(
|
|
17288
17424
|
() => {
|
|
17289
17425
|
signal?.removeEventListener("abort", onAbort);
|
|
17290
|
-
|
|
17426
|
+
resolve39();
|
|
17291
17427
|
},
|
|
17292
17428
|
Math.max(0, ms)
|
|
17293
17429
|
);
|
|
@@ -17905,10 +18041,10 @@ var init_classifier = __esm({
|
|
|
17905
18041
|
let timer;
|
|
17906
18042
|
const onAbort = () => controller.abort();
|
|
17907
18043
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
17908
|
-
const timedOut = new Promise((
|
|
18044
|
+
const timedOut = new Promise((resolve39) => {
|
|
17909
18045
|
timer = setTimeout(() => {
|
|
17910
18046
|
controller.abort();
|
|
17911
|
-
|
|
18047
|
+
resolve39("timeout");
|
|
17912
18048
|
}, timeoutMs);
|
|
17913
18049
|
});
|
|
17914
18050
|
try {
|
|
@@ -18153,8 +18289,8 @@ var init_agent = __esm({
|
|
|
18153
18289
|
}
|
|
18154
18290
|
let resolveIdle = () => {
|
|
18155
18291
|
};
|
|
18156
|
-
const promise = new Promise((
|
|
18157
|
-
resolveIdle =
|
|
18292
|
+
const promise = new Promise((resolve39) => {
|
|
18293
|
+
resolveIdle = resolve39;
|
|
18158
18294
|
});
|
|
18159
18295
|
this.active = { controller, promise };
|
|
18160
18296
|
const options = this.options;
|
|
@@ -20061,15 +20197,15 @@ var init_session_cache = __esm({
|
|
|
20061
20197
|
const window2 = model.contextWindow;
|
|
20062
20198
|
if (window2 === void 0 || window2 <= 0) return;
|
|
20063
20199
|
const used = record3.promptTokens + record3.usage.output;
|
|
20064
|
-
const
|
|
20200
|
+
const percent3 = Math.min(100, Math.round(used / window2 * 1e3) / 10);
|
|
20065
20201
|
const before = this.lastPercent;
|
|
20066
|
-
this.lastPercent =
|
|
20202
|
+
this.lastPercent = percent3;
|
|
20067
20203
|
for (const threshold of PRESSURE_THRESHOLDS) {
|
|
20068
|
-
if (before >= threshold ||
|
|
20204
|
+
if (before >= threshold || percent3 < threshold) continue;
|
|
20069
20205
|
const remainingTokens = Math.max(0, window2 - used);
|
|
20070
20206
|
const event = {
|
|
20071
20207
|
type: "context_pressure",
|
|
20072
|
-
percent:
|
|
20208
|
+
percent: percent3,
|
|
20073
20209
|
threshold,
|
|
20074
20210
|
remainingTokens
|
|
20075
20211
|
};
|
|
@@ -20313,20 +20449,20 @@ function entriesBetween(index2, ancestorId, fromId) {
|
|
|
20313
20449
|
return at < 0 ? path : path.slice(at + 1);
|
|
20314
20450
|
}
|
|
20315
20451
|
function collectLabels(entries) {
|
|
20316
|
-
const
|
|
20452
|
+
const labels2 = /* @__PURE__ */ new Map();
|
|
20317
20453
|
for (const entry of entries) {
|
|
20318
20454
|
if (entry.type !== "label") continue;
|
|
20319
|
-
if (entry.label === void 0 || entry.label === "")
|
|
20320
|
-
else
|
|
20455
|
+
if (entry.label === void 0 || entry.label === "") labels2.delete(entry.targetId);
|
|
20456
|
+
else labels2.set(entry.targetId, entry.label);
|
|
20321
20457
|
}
|
|
20322
|
-
return
|
|
20458
|
+
return labels2;
|
|
20323
20459
|
}
|
|
20324
20460
|
function buildTree(entries) {
|
|
20325
|
-
const
|
|
20461
|
+
const labels2 = collectLabels(entries);
|
|
20326
20462
|
const nodes = /* @__PURE__ */ new Map();
|
|
20327
20463
|
for (const entry of entries) {
|
|
20328
20464
|
const node = { entry, children: [] };
|
|
20329
|
-
const label2 =
|
|
20465
|
+
const label2 = labels2.get(entry.id);
|
|
20330
20466
|
if (label2 !== void 0) node.label = label2;
|
|
20331
20467
|
nodes.set(entry.id, node);
|
|
20332
20468
|
}
|
|
@@ -22506,6 +22642,32 @@ function recordDisplay(record3, event, now) {
|
|
|
22506
22642
|
return;
|
|
22507
22643
|
}
|
|
22508
22644
|
}
|
|
22645
|
+
function startEvent(record3, handle) {
|
|
22646
|
+
const event = {
|
|
22647
|
+
type: "subagent_start",
|
|
22648
|
+
taskId: record3.info.taskId,
|
|
22649
|
+
parentToolCallId: record3.parentToolCallId,
|
|
22650
|
+
agent: record3.agent.name,
|
|
22651
|
+
runner: record3.agent.runner,
|
|
22652
|
+
description: record3.info.description,
|
|
22653
|
+
background: record3.info.background,
|
|
22654
|
+
cwd: record3.cwd
|
|
22655
|
+
};
|
|
22656
|
+
if (handle.model !== void 0) event.model = handle.model;
|
|
22657
|
+
if (handle.sessionFile !== void 0) event.sessionFile = handle.sessionFile;
|
|
22658
|
+
return event;
|
|
22659
|
+
}
|
|
22660
|
+
function taskStats(records2) {
|
|
22661
|
+
const byStatus = {};
|
|
22662
|
+
let total = 0;
|
|
22663
|
+
let running = 0;
|
|
22664
|
+
for (const { info: info2 } of records2) {
|
|
22665
|
+
total++;
|
|
22666
|
+
if (info2.status === "running") running++;
|
|
22667
|
+
else byStatus[info2.status] = (byStatus[info2.status] ?? 0) + 1;
|
|
22668
|
+
}
|
|
22669
|
+
return total === 0 ? void 0 : { total, running, byStatus };
|
|
22670
|
+
}
|
|
22509
22671
|
function recordData(record3) {
|
|
22510
22672
|
return { ...record3.info, parentToolCallId: record3.parentToolCallId, cwd: record3.cwd };
|
|
22511
22673
|
}
|
|
@@ -22550,12 +22712,12 @@ var init_task_record = __esm({
|
|
|
22550
22712
|
async acquire(signal) {
|
|
22551
22713
|
while (this.running >= this.limit) {
|
|
22552
22714
|
if (signal.aborted) throw new AmaError("aborted", "aborted");
|
|
22553
|
-
await new Promise((
|
|
22715
|
+
await new Promise((resolve39) => {
|
|
22554
22716
|
const wake = () => {
|
|
22555
22717
|
signal.removeEventListener("abort", wake);
|
|
22556
22718
|
const at = this.waiters.indexOf(wake);
|
|
22557
22719
|
if (at >= 0) this.waiters.splice(at, 1);
|
|
22558
|
-
|
|
22720
|
+
resolve39();
|
|
22559
22721
|
};
|
|
22560
22722
|
this.waiters.push(wake);
|
|
22561
22723
|
signal.addEventListener("abort", wake, { once: true });
|
|
@@ -22674,14 +22836,14 @@ var init_worktree = __esm({
|
|
|
22674
22836
|
import_node_fs30 = require("node:fs");
|
|
22675
22837
|
import_node_path42 = require("node:path");
|
|
22676
22838
|
TIMEOUT_MS = 3e4;
|
|
22677
|
-
runGit = (args, cwd) => new Promise((
|
|
22839
|
+
runGit = (args, cwd) => new Promise((resolve39, reject2) => {
|
|
22678
22840
|
(0, import_node_child_process6.execFile)(
|
|
22679
22841
|
"git",
|
|
22680
22842
|
[...args],
|
|
22681
22843
|
{ cwd, timeout: TIMEOUT_MS, maxBuffer: 4 * 1024 * 1024, windowsHide: true },
|
|
22682
22844
|
(error2, stdout, stderr) => {
|
|
22683
22845
|
if (error2) reject2(new Error(String(stderr).trim() || error2.message));
|
|
22684
|
-
else
|
|
22846
|
+
else resolve39(String(stdout));
|
|
22685
22847
|
}
|
|
22686
22848
|
);
|
|
22687
22849
|
});
|
|
@@ -23190,6 +23352,179 @@ var init_subagent_direct = __esm({
|
|
|
23190
23352
|
}
|
|
23191
23353
|
});
|
|
23192
23354
|
|
|
23355
|
+
// src/agent/subagent-background.ts
|
|
23356
|
+
function resolveTaskBackground(setting, unattended) {
|
|
23357
|
+
if (setting === "always") return true;
|
|
23358
|
+
if (setting === "never") return false;
|
|
23359
|
+
return !unattended;
|
|
23360
|
+
}
|
|
23361
|
+
function runningResult(record3, text, outputFile) {
|
|
23362
|
+
const result = {
|
|
23363
|
+
text,
|
|
23364
|
+
usage: { ...ZERO_USAGE },
|
|
23365
|
+
stopReason: "stop",
|
|
23366
|
+
isError: false,
|
|
23367
|
+
taskId: record3.info.taskId,
|
|
23368
|
+
status: "running"
|
|
23369
|
+
};
|
|
23370
|
+
if (outputFile !== void 0) result.outputFile = outputFile;
|
|
23371
|
+
return result;
|
|
23372
|
+
}
|
|
23373
|
+
function startedResult(record3, outputFile) {
|
|
23374
|
+
return runningResult(record3, startedText(record3.info.taskId, record3.agent.name), outputFile);
|
|
23375
|
+
}
|
|
23376
|
+
function backgroundedResult(record3, reason, afterMs, outputFile) {
|
|
23377
|
+
return runningResult(record3, backgroundedText(reason, afterMs), outputFile);
|
|
23378
|
+
}
|
|
23379
|
+
function foregroundWaiter(detachParent) {
|
|
23380
|
+
let resolve39;
|
|
23381
|
+
const promise = new Promise((r) => {
|
|
23382
|
+
resolve39 = r;
|
|
23383
|
+
});
|
|
23384
|
+
return { waiter: { resolve: resolve39, detachParent }, promise };
|
|
23385
|
+
}
|
|
23386
|
+
async function waitForTask(record3, timeoutMs, signal, waits) {
|
|
23387
|
+
const running = record3.running;
|
|
23388
|
+
if (running === void 0) return record3.last;
|
|
23389
|
+
if (signal.aborted) return void 0;
|
|
23390
|
+
const leave = waits.enter(record3.info.taskId);
|
|
23391
|
+
let timer;
|
|
23392
|
+
let onAbort;
|
|
23393
|
+
const stop = new Promise((resolve39) => {
|
|
23394
|
+
timer = setTimeout(() => resolve39(void 0), timeoutMs);
|
|
23395
|
+
onAbort = () => resolve39(void 0);
|
|
23396
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
23397
|
+
});
|
|
23398
|
+
try {
|
|
23399
|
+
return await Promise.race([running, stop]);
|
|
23400
|
+
} finally {
|
|
23401
|
+
clearTimeout(timer);
|
|
23402
|
+
if (onAbort !== void 0) signal.removeEventListener("abort", onAbort);
|
|
23403
|
+
leave();
|
|
23404
|
+
}
|
|
23405
|
+
}
|
|
23406
|
+
function blockingTasks(records2, waits) {
|
|
23407
|
+
const ids = [];
|
|
23408
|
+
for (const r of records2)
|
|
23409
|
+
if (r.foregroundWaiter !== void 0 && r.running !== void 0) ids.push(r.info.taskId);
|
|
23410
|
+
return [.../* @__PURE__ */ new Set([...ids, ...waits.waited()])];
|
|
23411
|
+
}
|
|
23412
|
+
function backgroundRecords(records2, reason, ctx) {
|
|
23413
|
+
const moved = [];
|
|
23414
|
+
for (const record3 of records2) {
|
|
23415
|
+
const waiter = record3.foregroundWaiter;
|
|
23416
|
+
const running = record3.running;
|
|
23417
|
+
if (waiter === void 0 || running === void 0 || record3.info.status !== "running") continue;
|
|
23418
|
+
delete record3.foregroundWaiter;
|
|
23419
|
+
record3.info.background = true;
|
|
23420
|
+
waiter.detachParent();
|
|
23421
|
+
ctx.persist(record3);
|
|
23422
|
+
const taskId = record3.info.taskId;
|
|
23423
|
+
ctx.emit({
|
|
23424
|
+
type: "subagent_background",
|
|
23425
|
+
taskId,
|
|
23426
|
+
parentToolCallId: record3.parentToolCallId,
|
|
23427
|
+
reason
|
|
23428
|
+
});
|
|
23429
|
+
void running.then((result) => ctx.notify(record3, result));
|
|
23430
|
+
waiter.resolve(backgroundedResult(record3, reason, ctx.afterMs, ctx.outputFile(taskId)));
|
|
23431
|
+
moved.push(taskId);
|
|
23432
|
+
}
|
|
23433
|
+
return moved;
|
|
23434
|
+
}
|
|
23435
|
+
async function settleTasks(tasks, notifier, disposed2) {
|
|
23436
|
+
const running = () => [...tasks.values()].flatMap((r) => r.running === void 0 ? [] : [r.running]);
|
|
23437
|
+
for (; ; ) {
|
|
23438
|
+
if (disposed2()) return;
|
|
23439
|
+
const now = running();
|
|
23440
|
+
if (now.length > 0) {
|
|
23441
|
+
await Promise.allSettled(now);
|
|
23442
|
+
continue;
|
|
23443
|
+
}
|
|
23444
|
+
const delivery = notifier.pending();
|
|
23445
|
+
await delivery;
|
|
23446
|
+
if (delivery === notifier.pending() && running().length === 0) return;
|
|
23447
|
+
}
|
|
23448
|
+
}
|
|
23449
|
+
var WaitDetach, TaskNotifier;
|
|
23450
|
+
var init_subagent_background = __esm({
|
|
23451
|
+
"src/agent/subagent-background.ts"() {
|
|
23452
|
+
"use strict";
|
|
23453
|
+
init_result();
|
|
23454
|
+
init_loop();
|
|
23455
|
+
WaitDetach = class {
|
|
23456
|
+
controllers = /* @__PURE__ */ new Map();
|
|
23457
|
+
waiting = /* @__PURE__ */ new Map();
|
|
23458
|
+
signal(taskId) {
|
|
23459
|
+
let controller = this.controllers.get(taskId);
|
|
23460
|
+
if (controller === void 0) {
|
|
23461
|
+
controller = new AbortController();
|
|
23462
|
+
this.controllers.set(taskId, controller);
|
|
23463
|
+
}
|
|
23464
|
+
return controller.signal;
|
|
23465
|
+
}
|
|
23466
|
+
/** 登记一次正在进行的 wait;返回注销函数。 */
|
|
23467
|
+
enter(taskId) {
|
|
23468
|
+
this.waiting.set(taskId, (this.waiting.get(taskId) ?? 0) + 1);
|
|
23469
|
+
return () => {
|
|
23470
|
+
const left = (this.waiting.get(taskId) ?? 1) - 1;
|
|
23471
|
+
if (left <= 0) this.waiting.delete(taskId);
|
|
23472
|
+
else this.waiting.set(taskId, left);
|
|
23473
|
+
};
|
|
23474
|
+
}
|
|
23475
|
+
/** 有 wait 在等的 taskId。 */
|
|
23476
|
+
waited() {
|
|
23477
|
+
return [...this.waiting.keys()];
|
|
23478
|
+
}
|
|
23479
|
+
/** 打断 `taskId`(缺省全部)上的 wait;返回被打断的 taskId。 */
|
|
23480
|
+
detach(taskId) {
|
|
23481
|
+
const ids = taskId === void 0 ? this.waited() : this.waiting.has(taskId) ? [taskId] : [];
|
|
23482
|
+
for (const id of taskId === void 0 ? [...this.controllers.keys()] : [taskId]) {
|
|
23483
|
+
this.controllers.get(id)?.abort();
|
|
23484
|
+
this.controllers.delete(id);
|
|
23485
|
+
}
|
|
23486
|
+
return ids;
|
|
23487
|
+
}
|
|
23488
|
+
};
|
|
23489
|
+
TaskNotifier = class {
|
|
23490
|
+
constructor(host, disposed2) {
|
|
23491
|
+
this.host = host;
|
|
23492
|
+
this.disposed = disposed2;
|
|
23493
|
+
}
|
|
23494
|
+
host;
|
|
23495
|
+
disposed;
|
|
23496
|
+
delivery = Promise.resolve();
|
|
23497
|
+
/** 当前投递链(含已入链通知的整个回合)。 */
|
|
23498
|
+
pending() {
|
|
23499
|
+
return this.delivery;
|
|
23500
|
+
}
|
|
23501
|
+
notify(record3, result) {
|
|
23502
|
+
if (this.disposed() || result.status === "aborted") return;
|
|
23503
|
+
const info2 = record3.info;
|
|
23504
|
+
const text = taskNotification({
|
|
23505
|
+
taskId: info2.taskId,
|
|
23506
|
+
agent: info2.agent,
|
|
23507
|
+
status: result.status ?? "completed",
|
|
23508
|
+
...info2.turns === void 0 ? {} : { turns: info2.turns },
|
|
23509
|
+
...info2.usage === void 0 ? {} : { usage: info2.usage },
|
|
23510
|
+
...info2.outputFile === void 0 ? {} : { outputFile: info2.outputFile },
|
|
23511
|
+
report: result.text
|
|
23512
|
+
});
|
|
23513
|
+
const host = this.host;
|
|
23514
|
+
const followUp = host.followUp;
|
|
23515
|
+
if (followUp === void 0) {
|
|
23516
|
+
host.log("warn", `task ${info2.taskId} finished but the session cannot be notified`);
|
|
23517
|
+
return;
|
|
23518
|
+
}
|
|
23519
|
+
this.delivery = this.delivery.then(async () => {
|
|
23520
|
+
await host.waitForIdle?.();
|
|
23521
|
+
if (!this.disposed()) await followUp.call(host, text, { origin: "task" });
|
|
23522
|
+
}).catch((error2) => host.log("warn", `task notification failed: ${String(error2)}`));
|
|
23523
|
+
}
|
|
23524
|
+
};
|
|
23525
|
+
}
|
|
23526
|
+
});
|
|
23527
|
+
|
|
23193
23528
|
// src/agent/subagent-registry.ts
|
|
23194
23529
|
function taskRegistryView(sessionId) {
|
|
23195
23530
|
return registries.get(sessionId);
|
|
@@ -23227,6 +23562,7 @@ var init_subagent_registry = __esm({
|
|
|
23227
23562
|
init_worktree();
|
|
23228
23563
|
init_session_trace_writer();
|
|
23229
23564
|
init_subagent_direct();
|
|
23565
|
+
init_subagent_background();
|
|
23230
23566
|
DEFAULT_SUBAGENT_CONCURRENCY = 4;
|
|
23231
23567
|
DEFAULT_MAX_PENDING = 16;
|
|
23232
23568
|
DEFAULT_RETAINED = 16;
|
|
@@ -23247,6 +23583,7 @@ var init_subagent_registry = __esm({
|
|
|
23247
23583
|
const rebuilt = rebuildRecords(host.manager.branch(), this.catalog, host.cwd);
|
|
23248
23584
|
this.tasks = rebuilt.records;
|
|
23249
23585
|
this.seq = rebuilt.seq;
|
|
23586
|
+
this.notifier = new TaskNotifier(host, () => this.disposed);
|
|
23250
23587
|
}
|
|
23251
23588
|
host;
|
|
23252
23589
|
env;
|
|
@@ -23256,7 +23593,8 @@ var init_subagent_registry = __esm({
|
|
|
23256
23593
|
retained = [];
|
|
23257
23594
|
seq = 0;
|
|
23258
23595
|
disposed = false;
|
|
23259
|
-
|
|
23596
|
+
notifier;
|
|
23597
|
+
waits = new WaitDetach();
|
|
23260
23598
|
now() {
|
|
23261
23599
|
return this.env.now?.() ?? Date.now();
|
|
23262
23600
|
}
|
|
@@ -23271,33 +23609,46 @@ var init_subagent_registry = __esm({
|
|
|
23271
23609
|
return record3 === void 0 ? void 0 : { ...record3.info };
|
|
23272
23610
|
}
|
|
23273
23611
|
stats() {
|
|
23274
|
-
|
|
23275
|
-
const byStatus = {};
|
|
23276
|
-
let running = 0;
|
|
23277
|
-
for (const { info: info2 } of this.tasks.values()) {
|
|
23278
|
-
if (info2.status === "running") running++;
|
|
23279
|
-
else byStatus[info2.status] = (byStatus[info2.status] ?? 0) + 1;
|
|
23280
|
-
}
|
|
23281
|
-
return { total: this.tasks.size, running, byStatus };
|
|
23612
|
+
return taskStats(this.tasks.values());
|
|
23282
23613
|
}
|
|
23283
23614
|
/** 运行中任务的已有输出(`task_ctl output`);结束后为最终文本。 */
|
|
23284
23615
|
output(taskId) {
|
|
23285
23616
|
return this.tasks.get(taskId)?.text;
|
|
23286
23617
|
}
|
|
23287
|
-
/**
|
|
23288
|
-
async wait(taskId, timeoutMs) {
|
|
23618
|
+
/** 等结束;超时或 signal(缺省本任务的转后台信号,`background()` 触发)返回 undefined。[W7-B1] */
|
|
23619
|
+
async wait(taskId, timeoutMs, options = {}) {
|
|
23289
23620
|
const record3 = this.tasks.get(taskId);
|
|
23290
23621
|
if (record3 === void 0) throw new AmaError("task_not_found", `unknown task ${taskId}`);
|
|
23291
|
-
|
|
23292
|
-
|
|
23293
|
-
|
|
23294
|
-
|
|
23622
|
+
return waitForTask(record3, timeoutMs, options.signal ?? this.waits.signal(taskId), this.waits);
|
|
23623
|
+
}
|
|
23624
|
+
/** [W7-B1] `task_ctl wait` 用的打断信号(`background()` 触发后换新)。 */
|
|
23625
|
+
detachSignal(taskId) {
|
|
23626
|
+
return this.waits.signal(taskId);
|
|
23627
|
+
}
|
|
23628
|
+
/** [W7-B1] 正在阻塞父回合的任务:运行中的前台任务与有 `task_ctl wait` 在等的任务。 */
|
|
23629
|
+
blocking() {
|
|
23630
|
+
return blockingTasks(this.tasks.values(), this.waits);
|
|
23631
|
+
}
|
|
23632
|
+
/**
|
|
23633
|
+
* [W7-B1] 前台任务转后台(§2.5,subagent-background.ts),并打断等它的 `task_ctl wait`;不给 taskId =
|
|
23634
|
+
* 全部。返回被转后台或被打断等待的 taskId(不在运行时为空)。
|
|
23635
|
+
*/
|
|
23636
|
+
background(taskId, reason = "user") {
|
|
23637
|
+
if (this.disposed) return [];
|
|
23638
|
+
const one = taskId === void 0 ? void 0 : this.tasks.get(taskId);
|
|
23639
|
+
const records2 = taskId === void 0 ? [...this.tasks.values()] : one === void 0 ? [] : [one];
|
|
23640
|
+
const moved = backgroundRecords(records2, reason, {
|
|
23641
|
+
emit: (event) => this.host.emit(event),
|
|
23642
|
+
persist: (record3) => this.persist(record3),
|
|
23643
|
+
notify: (record3, result) => this.notifier.notify(record3, result),
|
|
23644
|
+
afterMs: this.env.autoBackgroundAfterMs ?? 0,
|
|
23645
|
+
outputFile: (id) => this.outputFileFor(id)
|
|
23295
23646
|
});
|
|
23296
|
-
|
|
23297
|
-
|
|
23298
|
-
|
|
23299
|
-
|
|
23300
|
-
|
|
23647
|
+
return [.../* @__PURE__ */ new Set([...moved, ...this.waits.detach(taskId)])];
|
|
23648
|
+
}
|
|
23649
|
+
/** [W7-B1] `-p` 收尾:等到没有运行中的任务、通知回合也已跑完;会话关闭立即返回。 */
|
|
23650
|
+
settled() {
|
|
23651
|
+
return settleTasks(this.tasks, this.notifier, () => this.disposed);
|
|
23301
23652
|
}
|
|
23302
23653
|
/** [W6-A] 子 Agent 视图读的实时数据;未知任务 undefined。 */
|
|
23303
23654
|
live(taskId) {
|
|
@@ -23336,7 +23687,7 @@ var init_subagent_registry = __esm({
|
|
|
23336
23687
|
);
|
|
23337
23688
|
const model = resolveAgentModel(agent, request.model, this.env.modelConfig ?? {});
|
|
23338
23689
|
if (model.warning !== void 0) this.host.log("warn", `agent ${name}: ${model.warning}`);
|
|
23339
|
-
const background = request.background ?? agent.background;
|
|
23690
|
+
const background = request.background ?? agent.background ?? this.env.background ?? false;
|
|
23340
23691
|
const taskId = `t${++this.seq}`;
|
|
23341
23692
|
const record3 = newRecord(
|
|
23342
23693
|
{
|
|
@@ -23371,7 +23722,8 @@ var init_subagent_registry = __esm({
|
|
|
23371
23722
|
return Promise.resolve(
|
|
23372
23723
|
failed(`Task ${taskId} cannot be continued (its session was not saved).`)
|
|
23373
23724
|
);
|
|
23374
|
-
|
|
23725
|
+
const background = request.background ?? record3.agent.background ?? this.env.background;
|
|
23726
|
+
return this.launch(record3, request, ama, background ?? false);
|
|
23375
23727
|
}
|
|
23376
23728
|
launch(record3, request, ama, background) {
|
|
23377
23729
|
const controller = new AbortController();
|
|
@@ -23387,29 +23739,33 @@ var init_subagent_registry = __esm({
|
|
|
23387
23739
|
if (parentSignal?.aborted) controller.abort();
|
|
23388
23740
|
else parentSignal?.addEventListener("abort", onParentAbort, { once: true });
|
|
23389
23741
|
this.persist(record3);
|
|
23742
|
+
let timer;
|
|
23390
23743
|
const running = this.execute(record3, request, ama, controller.signal).finally(() => {
|
|
23744
|
+
clearTimeout(timer);
|
|
23391
23745
|
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
23746
|
+
delete record3.foregroundWaiter;
|
|
23392
23747
|
delete record3.running;
|
|
23393
23748
|
delete record3.controller;
|
|
23394
23749
|
if (!this.disposed) drainDirect(record3, this.host);
|
|
23395
23750
|
});
|
|
23396
23751
|
record3.running = running;
|
|
23397
|
-
if (!background) return running;
|
|
23398
|
-
void running.then((result) => this.notify(record3, result));
|
|
23399
|
-
return Promise.resolve(this.startedResult(record3));
|
|
23400
|
-
}
|
|
23401
|
-
startedResult(record3) {
|
|
23402
|
-
const result = {
|
|
23403
|
-
text: `Started background task ${record3.info.taskId} (agent ${record3.agent.name}). A <task-notification> arrives when it finishes; use task_ctl to wait, stop or read output.`,
|
|
23404
|
-
usage: { ...ZERO_USAGE },
|
|
23405
|
-
stopReason: "stop",
|
|
23406
|
-
isError: false,
|
|
23407
|
-
taskId: record3.info.taskId,
|
|
23408
|
-
status: "running"
|
|
23409
|
-
};
|
|
23410
23752
|
const file = this.outputFileFor(record3.info.taskId);
|
|
23411
|
-
if (
|
|
23412
|
-
|
|
23753
|
+
if (background) {
|
|
23754
|
+
void running.then((result) => this.notifier.notify(record3, result));
|
|
23755
|
+
return Promise.resolve(startedResult(record3, file));
|
|
23756
|
+
}
|
|
23757
|
+
const { waiter, promise } = foregroundWaiter(() => {
|
|
23758
|
+
clearTimeout(timer);
|
|
23759
|
+
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
23760
|
+
delete record3.onUpdate;
|
|
23761
|
+
});
|
|
23762
|
+
record3.foregroundWaiter = waiter;
|
|
23763
|
+
const after = this.env.autoBackgroundAfterMs ?? 0;
|
|
23764
|
+
if (after > 0) {
|
|
23765
|
+
timer = setTimeout(() => this.background(record3.info.taskId, "timeout"), after);
|
|
23766
|
+
timer.unref?.();
|
|
23767
|
+
}
|
|
23768
|
+
return Promise.race([running, promise]);
|
|
23413
23769
|
}
|
|
23414
23770
|
async execute(record3, request, ama, signal) {
|
|
23415
23771
|
record3.queued = true;
|
|
@@ -23486,19 +23842,7 @@ var init_subagent_registry = __esm({
|
|
|
23486
23842
|
return handle;
|
|
23487
23843
|
}
|
|
23488
23844
|
emitStart(record3, handle) {
|
|
23489
|
-
|
|
23490
|
-
type: "subagent_start",
|
|
23491
|
-
taskId: record3.info.taskId,
|
|
23492
|
-
parentToolCallId: record3.parentToolCallId,
|
|
23493
|
-
agent: record3.agent.name,
|
|
23494
|
-
runner: record3.agent.runner,
|
|
23495
|
-
description: record3.info.description,
|
|
23496
|
-
background: record3.info.background,
|
|
23497
|
-
cwd: record3.cwd
|
|
23498
|
-
};
|
|
23499
|
-
if (handle.model !== void 0) event.model = handle.model;
|
|
23500
|
-
if (handle.sessionFile !== void 0) event.sessionFile = handle.sessionFile;
|
|
23501
|
-
this.host.emit(event);
|
|
23845
|
+
this.host.emit(startEvent(record3, handle));
|
|
23502
23846
|
}
|
|
23503
23847
|
sink() {
|
|
23504
23848
|
return {
|
|
@@ -23566,29 +23910,6 @@ ${outcome.diffStat ?? ""}`;
|
|
|
23566
23910
|
this.retain(info2.taskId);
|
|
23567
23911
|
return final;
|
|
23568
23912
|
}
|
|
23569
|
-
notify(record3, result) {
|
|
23570
|
-
if (this.disposed || result.status === "aborted") return;
|
|
23571
|
-
const info2 = record3.info;
|
|
23572
|
-
const text = taskNotification({
|
|
23573
|
-
taskId: info2.taskId,
|
|
23574
|
-
agent: info2.agent,
|
|
23575
|
-
status: result.status ?? "completed",
|
|
23576
|
-
...info2.turns === void 0 ? {} : { turns: info2.turns },
|
|
23577
|
-
...info2.usage === void 0 ? {} : { usage: info2.usage },
|
|
23578
|
-
...info2.outputFile === void 0 ? {} : { outputFile: info2.outputFile },
|
|
23579
|
-
report: result.text
|
|
23580
|
-
});
|
|
23581
|
-
const host = this.host;
|
|
23582
|
-
const followUp = host.followUp;
|
|
23583
|
-
if (followUp === void 0) {
|
|
23584
|
-
host.log("warn", `task ${info2.taskId} finished but the session cannot be notified`);
|
|
23585
|
-
return;
|
|
23586
|
-
}
|
|
23587
|
-
this.delivery = this.delivery.then(async () => {
|
|
23588
|
-
await host.waitForIdle?.();
|
|
23589
|
-
if (!this.disposed) await followUp.call(host, text, { origin: "task" });
|
|
23590
|
-
}).catch((error2) => host.log("warn", `task notification failed: ${String(error2)}`));
|
|
23591
|
-
}
|
|
23592
23913
|
// -------------------------------------------------------------------------
|
|
23593
23914
|
// 落盘、保留与重建
|
|
23594
23915
|
// -------------------------------------------------------------------------
|
|
@@ -24451,9 +24772,9 @@ var init_broker = __esm({
|
|
|
24451
24772
|
this.options.timeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS
|
|
24452
24773
|
);
|
|
24453
24774
|
const combined = AbortSignal.any([signal, timeout.signal]);
|
|
24454
|
-
const stopped = new Promise((
|
|
24455
|
-
if (combined.aborted)
|
|
24456
|
-
combined.addEventListener("abort", () =>
|
|
24775
|
+
const stopped = new Promise((resolve39) => {
|
|
24776
|
+
if (combined.aborted) resolve39("stopped");
|
|
24777
|
+
combined.addEventListener("abort", () => resolve39("stopped"), { once: true });
|
|
24457
24778
|
});
|
|
24458
24779
|
try {
|
|
24459
24780
|
const responders = [
|
|
@@ -24929,7 +25250,7 @@ async function requestApproval(core, request, signal) {
|
|
|
24929
25250
|
const answer = await Promise.race([
|
|
24930
25251
|
broker.ask(request, controller.signal).catch(() => void 0),
|
|
24931
25252
|
new Promise(
|
|
24932
|
-
(
|
|
25253
|
+
(resolve39) => controller.signal.addEventListener("abort", () => resolve39(void 0), { once: true })
|
|
24933
25254
|
)
|
|
24934
25255
|
]);
|
|
24935
25256
|
if (answer !== void 0) {
|
|
@@ -25519,6 +25840,7 @@ var init_session2 = __esm({
|
|
|
25519
25840
|
init_session_run();
|
|
25520
25841
|
init_session_state();
|
|
25521
25842
|
init_session_subagent();
|
|
25843
|
+
init_subagent_registry();
|
|
25522
25844
|
init_session_sync();
|
|
25523
25845
|
init_session_extensions();
|
|
25524
25846
|
init_session_settings();
|
|
@@ -25728,8 +26050,8 @@ var init_session2 = __esm({
|
|
|
25728
26050
|
const controller = new AbortController();
|
|
25729
26051
|
let done = () => {
|
|
25730
26052
|
};
|
|
25731
|
-
const promise = new Promise((
|
|
25732
|
-
done =
|
|
26053
|
+
const promise = new Promise((resolve39) => {
|
|
26054
|
+
done = resolve39;
|
|
25733
26055
|
});
|
|
25734
26056
|
this.cycle = { controller, promise };
|
|
25735
26057
|
this.turns = 0;
|
|
@@ -25817,6 +26139,13 @@ var init_session2 = __esm({
|
|
|
25817
26139
|
waitForIdle() {
|
|
25818
26140
|
return this.cycle?.promise ?? Promise.resolve();
|
|
25819
26141
|
}
|
|
26142
|
+
/**
|
|
26143
|
+
* [W7-B1] 把阻塞中的前台子 Agent 任务转后台(不给 taskId = 全部):工具调用立即返回,任务继续,完成后
|
|
26144
|
+
* 照常 `<task-notification>`。返回被转后台(或被打断等待)的 taskId。
|
|
26145
|
+
*/
|
|
26146
|
+
backgroundTask(taskId, reason = "host") {
|
|
26147
|
+
return registryOf(this.manager.id)?.background(taskId, reason) ?? [];
|
|
26148
|
+
}
|
|
25820
26149
|
clearQueue() {
|
|
25821
26150
|
const cleared = {
|
|
25822
26151
|
steering: this.agent.steeringQueue.clear().map(queuedText),
|
|
@@ -29382,8 +29711,9 @@ function parseAgentDefinition(text, filePath, source) {
|
|
|
29382
29711
|
const isolation = data2["isolation"] ?? "none";
|
|
29383
29712
|
if (isolation !== "none" && isolation !== "worktree")
|
|
29384
29713
|
return fail6("isolation must be none or worktree");
|
|
29385
|
-
const background = data2["background"]
|
|
29386
|
-
if (
|
|
29714
|
+
const background = data2["background"];
|
|
29715
|
+
if (background !== void 0 && typeof background !== "boolean")
|
|
29716
|
+
return fail6("background must be true or false");
|
|
29387
29717
|
if (runner !== "ama") {
|
|
29388
29718
|
const ignored = ["tools", "disallowed-tools", "permission-mode"].filter(
|
|
29389
29719
|
(key) => data2[key] !== void 0
|
|
@@ -29400,12 +29730,12 @@ function parseAgentDefinition(text, filePath, source) {
|
|
|
29400
29730
|
model: model.trim(),
|
|
29401
29731
|
maxTurns,
|
|
29402
29732
|
isolation,
|
|
29403
|
-
background,
|
|
29404
29733
|
runner,
|
|
29405
29734
|
prompt: fm.body.trim(),
|
|
29406
29735
|
source,
|
|
29407
29736
|
filePath
|
|
29408
29737
|
};
|
|
29738
|
+
if (background !== void 0) agent.background = background;
|
|
29409
29739
|
if (tools !== void 0) agent.tools = tools;
|
|
29410
29740
|
if (disallowedTools !== void 0) agent.disallowedTools = disallowedTools;
|
|
29411
29741
|
if (typeof thinking === "string") agent.thinking = thinking;
|
|
@@ -29676,7 +30006,7 @@ function spawnTransport(spec2, deps = {}) {
|
|
|
29676
30006
|
const line2 = commandLine(spec2, platform);
|
|
29677
30007
|
let tail = "";
|
|
29678
30008
|
let resolveExit;
|
|
29679
|
-
const exited = new Promise((
|
|
30009
|
+
const exited = new Promise((resolve39) => resolveExit = resolve39);
|
|
29680
30010
|
const child = (0, import_node_child_process9.spawn)(line2.file, line2.args, {
|
|
29681
30011
|
cwd: spec2.cwd,
|
|
29682
30012
|
env: spec2.env,
|
|
@@ -29723,7 +30053,7 @@ ${error2.message}`.slice(-STDERR_TAIL_BYTES);
|
|
|
29723
30053
|
if (done) return;
|
|
29724
30054
|
child.stdin?.end();
|
|
29725
30055
|
const timer = new Promise(
|
|
29726
|
-
(
|
|
30056
|
+
(resolve39) => setTimeout(() => resolve39("timeout"), graceMs).unref()
|
|
29727
30057
|
);
|
|
29728
30058
|
if (await Promise.race([exited, timer]) !== "timeout") return;
|
|
29729
30059
|
if (pid !== void 0) await killProcessTree(pid, { platform, ...deps.process });
|
|
@@ -30087,7 +30417,7 @@ async function writeChunked(stream5, text, chunkBytes = WRITE_CHUNK_BYTES) {
|
|
|
30087
30417
|
for (let offset = 0; offset < bytes.length; offset += chunkBytes) {
|
|
30088
30418
|
const piece = bytes.subarray(offset, Math.min(bytes.length, offset + chunkBytes));
|
|
30089
30419
|
if (!stream5.write(piece)) {
|
|
30090
|
-
await new Promise((
|
|
30420
|
+
await new Promise((resolve39) => stream5.once("drain", resolve39));
|
|
30091
30421
|
}
|
|
30092
30422
|
}
|
|
30093
30423
|
}
|
|
@@ -30172,7 +30502,7 @@ var init_jsonrpc = __esm({
|
|
|
30172
30502
|
isClosed = false;
|
|
30173
30503
|
resolveClosed;
|
|
30174
30504
|
/** 输入流结束或 `close()` 后 resolve。 */
|
|
30175
|
-
closed = new Promise((
|
|
30505
|
+
closed = new Promise((resolve39) => this.resolveClosed = resolve39);
|
|
30176
30506
|
get isOpen() {
|
|
30177
30507
|
return !this.isClosed;
|
|
30178
30508
|
}
|
|
@@ -30180,7 +30510,7 @@ var init_jsonrpc = __esm({
|
|
|
30180
30510
|
request(method, params, signal) {
|
|
30181
30511
|
if (this.isClosed) return Promise.reject(closedError(method));
|
|
30182
30512
|
const id = this.nextId++;
|
|
30183
|
-
return new Promise((
|
|
30513
|
+
return new Promise((resolve39, reject2) => {
|
|
30184
30514
|
const onAbort = () => {
|
|
30185
30515
|
this.pending.delete(id);
|
|
30186
30516
|
reject2(new RpcError(RPC_ERRORS.internalError, `${method}: aborted`));
|
|
@@ -30191,7 +30521,7 @@ var init_jsonrpc = __esm({
|
|
|
30191
30521
|
method,
|
|
30192
30522
|
resolve: (value) => {
|
|
30193
30523
|
signal?.removeEventListener("abort", onAbort);
|
|
30194
|
-
|
|
30524
|
+
resolve39(value);
|
|
30195
30525
|
},
|
|
30196
30526
|
reject: (error2) => {
|
|
30197
30527
|
signal?.removeEventListener("abort", onAbort);
|
|
@@ -30441,8 +30771,8 @@ var init_client = __esm({
|
|
|
30441
30771
|
try {
|
|
30442
30772
|
const answer = await Promise.race([
|
|
30443
30773
|
handler(request, signal),
|
|
30444
|
-
new Promise((
|
|
30445
|
-
const cancelled = () =>
|
|
30774
|
+
new Promise((resolve39) => {
|
|
30775
|
+
const cancelled = () => resolve39({ outcome: { outcome: "cancelled" } });
|
|
30446
30776
|
if (signal.aborted) cancelled();
|
|
30447
30777
|
else signal.addEventListener("abort", cancelled, { once: true });
|
|
30448
30778
|
})
|
|
@@ -30694,7 +31024,7 @@ var init_driver = __esm({
|
|
|
30694
31024
|
if (this.client !== void 0) {
|
|
30695
31025
|
if (this.running !== void 0) await this.client.cancel(this.id).catch(() => void 0);
|
|
30696
31026
|
if (this.id !== "" && this.client.isOpen && this.client.supportsClose()) {
|
|
30697
|
-
const timer = new Promise((
|
|
31027
|
+
const timer = new Promise((resolve39) => setTimeout(resolve39, 2e3).unref());
|
|
30698
31028
|
await Promise.race([this.client.closeSession(this.id).catch(() => void 0), timer]);
|
|
30699
31029
|
}
|
|
30700
31030
|
this.client.close();
|
|
@@ -30949,7 +31279,7 @@ var init_claude_stream = __esm({
|
|
|
30949
31279
|
if (signal.aborted) reject2(new Error("aborted"));
|
|
30950
31280
|
signal.addEventListener("abort", () => reject2(new Error("aborted")), { once: true });
|
|
30951
31281
|
});
|
|
30952
|
-
const timeout = new Promise((
|
|
31282
|
+
const timeout = new Promise((resolve39) => setTimeout(resolve39, 1e4).unref());
|
|
30953
31283
|
try {
|
|
30954
31284
|
await Promise.race([response, aborted, timeout]);
|
|
30955
31285
|
} catch (error2) {
|
|
@@ -30971,8 +31301,8 @@ var init_claude_stream = __esm({
|
|
|
30971
31301
|
this.hooks = hooks;
|
|
30972
31302
|
this.interrupted = false;
|
|
30973
31303
|
this.sawPartialText = false;
|
|
30974
|
-
const done = new Promise((
|
|
30975
|
-
this.finishTurn =
|
|
31304
|
+
const done = new Promise((resolve39, reject2) => {
|
|
31305
|
+
this.finishTurn = resolve39;
|
|
30976
31306
|
this.failTurn = reject2;
|
|
30977
31307
|
});
|
|
30978
31308
|
this.running = done.then((result) => this.complete(result, turn));
|
|
@@ -31055,8 +31385,8 @@ var init_claude_stream = __esm({
|
|
|
31055
31385
|
}
|
|
31056
31386
|
control(request) {
|
|
31057
31387
|
const requestId = `ama-${this.nextRequest++}`;
|
|
31058
|
-
return new Promise((
|
|
31059
|
-
this.controls.set(requestId, { resolve:
|
|
31388
|
+
return new Promise((resolve39, reject2) => {
|
|
31389
|
+
this.controls.set(requestId, { resolve: resolve39, reject: reject2 });
|
|
31060
31390
|
this.write(
|
|
31061
31391
|
`${JSON.stringify({ type: "control_request", request_id: requestId, request })}
|
|
31062
31392
|
`
|
|
@@ -31521,7 +31851,7 @@ var init_codex_app_server = __esm({
|
|
|
31521
31851
|
this.messages.clear();
|
|
31522
31852
|
this.tokensAtStart = this.tokensTotal;
|
|
31523
31853
|
this.interruptRequested = false;
|
|
31524
|
-
const completed = new Promise((
|
|
31854
|
+
const completed = new Promise((resolve39) => this.finishTurn = resolve39);
|
|
31525
31855
|
const closed = this.peer.closed.then(() => {
|
|
31526
31856
|
throw new AmaError(
|
|
31527
31857
|
"agent_exited",
|
|
@@ -31888,7 +32218,7 @@ var init_oneshot = __esm({
|
|
|
31888
32218
|
let claude;
|
|
31889
32219
|
let failure2;
|
|
31890
32220
|
const done = new Promise(
|
|
31891
|
-
(
|
|
32221
|
+
(resolve39) => createLineReader(
|
|
31892
32222
|
transport.stdout,
|
|
31893
32223
|
(line2) => {
|
|
31894
32224
|
let msg2;
|
|
@@ -31902,7 +32232,7 @@ var init_oneshot = __esm({
|
|
|
31902
32232
|
} else if (this.dialect === "codex") failure2 = this.onCodex(msg2, turn) ?? failure2;
|
|
31903
32233
|
else failure2 = this.onGemini(msg2, turn) ?? failure2;
|
|
31904
32234
|
},
|
|
31905
|
-
|
|
32235
|
+
resolve39
|
|
31906
32236
|
)
|
|
31907
32237
|
);
|
|
31908
32238
|
if (this.dialect !== "gemini") transport.stdin.write(text);
|
|
@@ -32229,7 +32559,7 @@ var init_pool = __esm({
|
|
|
32229
32559
|
if (signal?.aborted === true) return Promise.reject(abortedError());
|
|
32230
32560
|
if (this.canRun(agentId) && !this.queue.some((w) => w.agentId === agentId))
|
|
32231
32561
|
return Promise.resolve(this.take(agentId));
|
|
32232
|
-
return new Promise((
|
|
32562
|
+
return new Promise((resolve39, reject2) => {
|
|
32233
32563
|
const onAbort = () => {
|
|
32234
32564
|
const at = this.queue.indexOf(waiter);
|
|
32235
32565
|
if (at >= 0) this.queue.splice(at, 1);
|
|
@@ -32239,7 +32569,7 @@ var init_pool = __esm({
|
|
|
32239
32569
|
agentId,
|
|
32240
32570
|
grant: (release) => {
|
|
32241
32571
|
signal?.removeEventListener("abort", onAbort);
|
|
32242
|
-
|
|
32572
|
+
resolve39(release);
|
|
32243
32573
|
}
|
|
32244
32574
|
};
|
|
32245
32575
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
@@ -33011,7 +33341,6 @@ function definition(name, runner, description, source) {
|
|
|
33011
33341
|
model: "inherit",
|
|
33012
33342
|
maxTurns: 30,
|
|
33013
33343
|
isolation: "none",
|
|
33014
|
-
background: false,
|
|
33015
33344
|
// 驱动表 id(gemini 等)与宿主 id 不在 AgentRunnerSpec 的字面量里,线上照样是字符串
|
|
33016
33345
|
runner,
|
|
33017
33346
|
prompt: "",
|
|
@@ -33322,6 +33651,10 @@ function subagentEnvironment(deps, catalog) {
|
|
|
33322
33651
|
if (max !== void 0) env.maxConcurrent = max;
|
|
33323
33652
|
const pending = config.subagents?.maxPending;
|
|
33324
33653
|
if (pending !== void 0) env.maxPending = pending;
|
|
33654
|
+
const sub = config.subagents;
|
|
33655
|
+
env.background = resolveTaskBackground(sub?.background, deps.assembly.unattended === true);
|
|
33656
|
+
const after = sub?.autoBackgroundAfterMs;
|
|
33657
|
+
if (typeof after === "number" && after > 0) env.autoBackgroundAfterMs = after;
|
|
33325
33658
|
return env;
|
|
33326
33659
|
}
|
|
33327
33660
|
function externalWiring(deps) {
|
|
@@ -33371,6 +33704,7 @@ function createSubagentsFactory(deps) {
|
|
|
33371
33704
|
registerExternalAgents(catalog, wiring);
|
|
33372
33705
|
bindTaskAgents(task, catalog);
|
|
33373
33706
|
const env = subagentEnvironment(deps, catalog);
|
|
33707
|
+
bindTaskBackground(task, env.background === true);
|
|
33374
33708
|
return ({ core }) => core.depth > 0 ? void 0 : createSubagentExtension(core, env, wiring);
|
|
33375
33709
|
}
|
|
33376
33710
|
var warned;
|
|
@@ -33383,6 +33717,7 @@ var init_compose_agents = __esm({
|
|
|
33383
33717
|
init_external();
|
|
33384
33718
|
init_api_impl();
|
|
33385
33719
|
init_task();
|
|
33720
|
+
init_subagent_background();
|
|
33386
33721
|
init_i18n();
|
|
33387
33722
|
warned = /* @__PURE__ */ new WeakSet();
|
|
33388
33723
|
}
|
|
@@ -34346,7 +34681,7 @@ async function runAcpMode(runtime, context, options = {}) {
|
|
|
34346
34681
|
runtime.approvals.setUiBroker(server.broker);
|
|
34347
34682
|
runtime.notifier.set((message, level) => context.io.stderr(`ama: [${level}] ${message}
|
|
34348
34683
|
`));
|
|
34349
|
-
return new Promise((
|
|
34684
|
+
return new Promise((resolve39) => {
|
|
34350
34685
|
let finished = false;
|
|
34351
34686
|
const finish2 = async (code, abort) => {
|
|
34352
34687
|
if (finished) return;
|
|
@@ -34361,7 +34696,7 @@ async function runAcpMode(runtime, context, options = {}) {
|
|
|
34361
34696
|
server.peer.close();
|
|
34362
34697
|
server.dispose();
|
|
34363
34698
|
runtime.notifier.set(void 0);
|
|
34364
|
-
|
|
34699
|
+
resolve39(code);
|
|
34365
34700
|
};
|
|
34366
34701
|
void server.peer.closed.then(() => finish2(ExitCode.Ok, false));
|
|
34367
34702
|
const offSignals = onTerminationSignals((code) => {
|
|
@@ -34550,25 +34885,29 @@ function thinkingMapOf(levels) {
|
|
|
34550
34885
|
for (const level of EFFORT_LEVELS) map[level] = levels.includes(level) ? level : null;
|
|
34551
34886
|
return map;
|
|
34552
34887
|
}
|
|
34553
|
-
function withBackendMetadata(model, cached
|
|
34554
|
-
if (
|
|
34888
|
+
function withBackendMetadata(model, cached) {
|
|
34889
|
+
if (cached.contextWindow !== void 0) {
|
|
34555
34890
|
model.contextWindow = cached.contextWindow;
|
|
34556
|
-
|
|
34891
|
+
if (model.inputLimit !== void 0 && model.inputLimit >= cached.contextWindow)
|
|
34892
|
+
delete model.inputLimit;
|
|
34893
|
+
}
|
|
34557
34894
|
if (cached.input !== void 0) model.input = [...cached.input];
|
|
34558
|
-
|
|
34559
|
-
if (
|
|
34895
|
+
if (cached.reasoningLevels === void 0) return;
|
|
34896
|
+
if (cached.reasoningLevels.some((x) => x !== "none")) {
|
|
34560
34897
|
model.reasoning = true;
|
|
34561
|
-
model.thinkingLevelMap = thinkingMapOf(cached.reasoningLevels
|
|
34898
|
+
model.thinkingLevelMap = thinkingMapOf(cached.reasoningLevels);
|
|
34899
|
+
} else {
|
|
34900
|
+
model.reasoning = false;
|
|
34901
|
+
delete model.thinkingLevelMap;
|
|
34562
34902
|
}
|
|
34563
34903
|
}
|
|
34564
34904
|
function discoveredModels(file, provider, modelsDev) {
|
|
34565
34905
|
return file.models.map((m) => {
|
|
34566
|
-
const { entry
|
|
34567
|
-
m.name ? { id: m.id, name: m.name } : { id: m.id },
|
|
34568
|
-
modelsDev
|
|
34569
|
-
);
|
|
34906
|
+
const { entry } = enrichEntry(m.name ? { id: m.id, name: m.name } : { id: m.id }, modelsDev);
|
|
34570
34907
|
const model = withCustomDefaults(entry, provider.id, provider.api);
|
|
34571
|
-
withBackendMetadata(model, m
|
|
34908
|
+
withBackendMetadata(model, m);
|
|
34909
|
+
if (model.contextWindow === void 0 && SUBSCRIPTION_PROVIDERS.has(provider.id))
|
|
34910
|
+
model.contextWindow = SUBSCRIPTION_FALLBACK_CONTEXT_WINDOW;
|
|
34572
34911
|
const names = (provider.channels ?? []).map((c) => c.name);
|
|
34573
34912
|
if (names.length > 0) {
|
|
34574
34913
|
const own = file.flavor !== void 0 && names.includes(file.flavor) ? file.flavor : void 0;
|
|
@@ -34590,7 +34929,7 @@ function mergeDiscoveredModels(registry2, dataDir, modelsDev, loginFlavor = () =
|
|
|
34590
34929
|
}
|
|
34591
34930
|
return merged;
|
|
34592
34931
|
}
|
|
34593
|
-
var import_node_fs44, import_node_path66, DISCOVERED_CACHE_VERSION, EFFORT_LEVELS;
|
|
34932
|
+
var import_node_fs44, import_node_path66, DISCOVERED_CACHE_VERSION, EFFORT_LEVELS, SUBSCRIPTION_FALLBACK_CONTEXT_WINDOW, SUBSCRIPTION_PROVIDERS;
|
|
34594
34933
|
var init_discovered_cache = __esm({
|
|
34595
34934
|
"src/ai/providers/discovered-cache.ts"() {
|
|
34596
34935
|
"use strict";
|
|
@@ -34600,6 +34939,8 @@ var init_discovered_cache = __esm({
|
|
|
34600
34939
|
init_enrich();
|
|
34601
34940
|
DISCOVERED_CACHE_VERSION = 1;
|
|
34602
34941
|
EFFORT_LEVELS = ["minimal", "low", "medium", "high", "xhigh"];
|
|
34942
|
+
SUBSCRIPTION_FALLBACK_CONTEXT_WINDOW = 128e3;
|
|
34943
|
+
SUBSCRIPTION_PROVIDERS = /* @__PURE__ */ new Set(["chatgpt"]);
|
|
34603
34944
|
}
|
|
34604
34945
|
});
|
|
34605
34946
|
|
|
@@ -34965,7 +35306,7 @@ var init_key_docs = __esm({
|
|
|
34965
35306
|
codemode: { inlineBudget: DEFAULT_INLINE_BUDGET, requireStrict: false },
|
|
34966
35307
|
cache: { ...DEFAULT_CACHE_CONFIG },
|
|
34967
35308
|
request: { idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS },
|
|
34968
|
-
ui: { compact: false, animation: true, restoreOnCancel: true, language: "auto" },
|
|
35309
|
+
ui: { compact: false, logo: "auto", animation: true, restoreOnCancel: true, language: "auto" },
|
|
34969
35310
|
// [W6-C0] 第六波键的缺省(行为由各批次实现)
|
|
34970
35311
|
memory: {
|
|
34971
35312
|
enabled: false,
|
|
@@ -34990,7 +35331,7 @@ var init_key_docs = __esm({
|
|
|
34990
35331
|
images: { resize: "auto" },
|
|
34991
35332
|
plan: { bash: "readonly", unattended: "stop" },
|
|
34992
35333
|
agents: { maxConcurrent: 3, dirs: [] },
|
|
34993
|
-
subagents: { maxConcurrent: 4, maxPending: 16 },
|
|
35334
|
+
subagents: { maxConcurrent: 4, maxPending: 16, background: "auto", autoBackgroundAfterMs: 0 },
|
|
34994
35335
|
reminders: { todo: true, fileChanges: true, contextPressure: true, budget: true },
|
|
34995
35336
|
todo: { reminder: 10 }
|
|
34996
35337
|
};
|
|
@@ -35244,7 +35585,13 @@ function w5Sections() {
|
|
|
35244
35585
|
}
|
|
35245
35586
|
}
|
|
35246
35587
|
),
|
|
35247
|
-
subagents: object({
|
|
35588
|
+
subagents: object({
|
|
35589
|
+
maxConcurrent: num2(1, 64),
|
|
35590
|
+
maxPending: num2(0, 1024),
|
|
35591
|
+
defaultModel: str3(),
|
|
35592
|
+
background: oneOf(SUBAGENT_BACKGROUND_MODES),
|
|
35593
|
+
autoBackgroundAfterMs: num2(0)
|
|
35594
|
+
}),
|
|
35248
35595
|
models: object({ aliases: object({ fast: str3(), strong: str3() }), enabled: strings2 }),
|
|
35249
35596
|
fallbackModel: str3(),
|
|
35250
35597
|
limits: object({ maxTurns: num2(1), maxCostUsd: num2(0) }),
|
|
@@ -35359,6 +35706,7 @@ function buildBaseSchema() {
|
|
|
35359
35706
|
quietStartup: oneOf(["normal", "header", "silent"]),
|
|
35360
35707
|
ascii: bool(),
|
|
35361
35708
|
compact: bool(),
|
|
35709
|
+
logo: oneOf(["auto", "off"]),
|
|
35362
35710
|
animation: bool(),
|
|
35363
35711
|
restoreOnCancel: bool(),
|
|
35364
35712
|
statusLine: oneOf(STATUS_LINE_MODES),
|
|
@@ -38404,7 +38752,7 @@ var init_auth2 = __esm({
|
|
|
38404
38752
|
let pending = this.commandCache.get(key);
|
|
38405
38753
|
if (!pending) {
|
|
38406
38754
|
const timeout = this.options.commandTimeoutMs ?? 1e4;
|
|
38407
|
-
pending = new Promise((
|
|
38755
|
+
pending = new Promise((resolve39) => {
|
|
38408
38756
|
(0, import_node_child_process13.exec)(
|
|
38409
38757
|
command3,
|
|
38410
38758
|
{ timeout, windowsHide: true, env: { ...this.env, ...extraEnv }, maxBuffer: 1 << 20 },
|
|
@@ -38412,8 +38760,8 @@ var init_auth2 = __esm({
|
|
|
38412
38760
|
const value = String(stdout).trim();
|
|
38413
38761
|
if (error2 || value.length === 0) {
|
|
38414
38762
|
this.warn(`api key command failed or printed nothing: ${command3.split(/\s+/)[0]}`);
|
|
38415
|
-
|
|
38416
|
-
} else
|
|
38763
|
+
resolve39(void 0);
|
|
38764
|
+
} else resolve39(value);
|
|
38417
38765
|
}
|
|
38418
38766
|
);
|
|
38419
38767
|
});
|
|
@@ -39371,6 +39719,7 @@ var init_settings_registry = __esm({
|
|
|
39371
39719
|
row("ui.showThinking", "ui", "now", "any"),
|
|
39372
39720
|
row("ui.compact", "ui", "now", "any"),
|
|
39373
39721
|
row("ui.animation", "ui", "now", "any"),
|
|
39722
|
+
row("ui.logo", "ui", "restart", "any"),
|
|
39374
39723
|
row("ui.statusLine", "ui", "now", "any"),
|
|
39375
39724
|
row("ui.restoreOnCancel", "ui", "nextSession", "any"),
|
|
39376
39725
|
row("ui.quietStartup", "ui", "restart", "any"),
|
|
@@ -39432,6 +39781,9 @@ var init_settings_registry = __esm({
|
|
|
39432
39781
|
row("agents.sessionBudgetUsd", "agents", "nextSession", "deny", { kind: "optionalNumber" }),
|
|
39433
39782
|
row("subagents.maxConcurrent", "agents", "nextSession", "deny"),
|
|
39434
39783
|
row("subagents.maxPending", "agents", "nextSession", "deny"),
|
|
39784
|
+
// [W7-B2] 改 task 工具描述(缺省后台 / 前台两种文案),故 prefix
|
|
39785
|
+
row("subagents.background", "agents", "restart", "any", { prefix: true }),
|
|
39786
|
+
row("subagents.autoBackgroundAfterMs", "agents", "restart", "any"),
|
|
39435
39787
|
// [W6-M]
|
|
39436
39788
|
row("memory.enabled", "memory", "nextSession", "tighten", { envOverride: "AMA_MEMORY" }),
|
|
39437
39789
|
row("memory.subagents", "memory", "nextSession", "deny")
|
|
@@ -41134,10 +41486,15 @@ var init_keybindings = __esm({
|
|
|
41134
41486
|
/** [W5-U] 粘贴剪贴板图片(写进数据目录,输入框插入 `@路径`)。 */
|
|
41135
41487
|
"app.paste.image": ["ctrl+v"],
|
|
41136
41488
|
/**
|
|
41137
|
-
* [W6-A] 进入 Agent
|
|
41138
|
-
*
|
|
41489
|
+
* [W6-A / W7-A] 进入 Agent 栏:输入为空、补全未开、有子 Agent 任务即可(不要求栏可见);有字时 `↓` 仍是
|
|
41490
|
+
* 下移 / 历史,并给一次提示。`Ctrl+B` 不再进栏(tmux 缺省前缀会吃掉它),留给 `app.tasks.background`。
|
|
41491
|
+
*/
|
|
41492
|
+
"app.agents.focus": ["down"],
|
|
41493
|
+
/**
|
|
41494
|
+
* [W7-C] 有阻塞中的前台子 Agent 任务(或 `task_ctl wait`)时全部转后台,不看输入框;没有时落回编辑器
|
|
41495
|
+
* (`tui.editor.cursorLeft` 的 `ctrl+b`)。tmux 里按 `C-b C-b` 透传。
|
|
41139
41496
|
*/
|
|
41140
|
-
"app.
|
|
41497
|
+
"app.tasks.background": ["ctrl+b"]
|
|
41141
41498
|
};
|
|
41142
41499
|
Keybindings = class {
|
|
41143
41500
|
table;
|
|
@@ -42317,6 +42674,10 @@ var init_editor = __esm({
|
|
|
42317
42674
|
get isCompletionOpen() {
|
|
42318
42675
|
return this.completion !== null;
|
|
42319
42676
|
}
|
|
42677
|
+
/** 正在用 ↑↓ 浏览输入历史(编辑后即退出)。 */
|
|
42678
|
+
get isBrowsingHistory() {
|
|
42679
|
+
return this.historyIndex !== -1;
|
|
42680
|
+
}
|
|
42320
42681
|
getHistory() {
|
|
42321
42682
|
return this.history;
|
|
42322
42683
|
}
|
|
@@ -42819,6 +43180,9 @@ var init_spacer = __esm({
|
|
|
42819
43180
|
});
|
|
42820
43181
|
|
|
42821
43182
|
// src/tui/components/loader.ts
|
|
43183
|
+
function sameList(a, b) {
|
|
43184
|
+
return a.length === b.length && a.every((e, i) => e === b[i]);
|
|
43185
|
+
}
|
|
42822
43186
|
function formatElapsed(ms) {
|
|
42823
43187
|
const total = Math.max(0, Math.floor(ms / 1e3));
|
|
42824
43188
|
if (total < 60) return `${total}s`;
|
|
@@ -42848,6 +43212,7 @@ var init_loader = __esm({
|
|
|
42848
43212
|
startedAt;
|
|
42849
43213
|
verb;
|
|
42850
43214
|
extras = [];
|
|
43215
|
+
optional = [];
|
|
42851
43216
|
verbElapsed;
|
|
42852
43217
|
lastElapsed = "";
|
|
42853
43218
|
listeners = /* @__PURE__ */ new Set();
|
|
@@ -42873,10 +43238,11 @@ var init_loader = __esm({
|
|
|
42873
43238
|
}
|
|
42874
43239
|
/** 换动词与附加项(附加项 dim,排在已用时之后)。 */
|
|
42875
43240
|
setVerb(verb, extras = [], options = {}) {
|
|
42876
|
-
const same2 = verb === this.verb && options.elapsed === this.verbElapsed && extras
|
|
43241
|
+
const same2 = verb === this.verb && options.elapsed === this.verbElapsed && sameList(extras, this.extras) && sameList(options.optional ?? [], this.optional);
|
|
42877
43242
|
if (same2) return;
|
|
42878
43243
|
this.verb = verb;
|
|
42879
43244
|
this.extras = [...extras];
|
|
43245
|
+
this.optional = [...options.optional ?? []];
|
|
42880
43246
|
this.verbElapsed = options.elapsed;
|
|
42881
43247
|
this.requestRender();
|
|
42882
43248
|
}
|
|
@@ -42936,7 +43302,13 @@ var init_loader = __esm({
|
|
|
42936
43302
|
if (this.verbElapsed ?? this.options.showElapsed !== false) parts.push(dim(elapsed));
|
|
42937
43303
|
for (const extra of this.extras) parts.push(dim(extra));
|
|
42938
43304
|
const spinner = theme ? theme.fg("accent", this.frame) : this.frame;
|
|
42939
|
-
|
|
43305
|
+
const line2 = (items) => `${spinner} ${items.join(dim(" · "))}`;
|
|
43306
|
+
for (const extra of this.optional) {
|
|
43307
|
+
const next = [...parts, dim(extra)];
|
|
43308
|
+
if (visibleWidth(line2(next)) > width2) break;
|
|
43309
|
+
parts.push(dim(extra));
|
|
43310
|
+
}
|
|
43311
|
+
return [truncateToWidth(line2(parts), width2)];
|
|
42940
43312
|
}
|
|
42941
43313
|
invalidate() {
|
|
42942
43314
|
}
|
|
@@ -43027,13 +43399,13 @@ var init_meter = __esm({
|
|
|
43027
43399
|
render(width2) {
|
|
43028
43400
|
const { theme, label: label2, cells = 10 } = this.options;
|
|
43029
43401
|
const ratio = this.value === void 0 ? void 0 : Math.min(1, Math.max(0, this.value));
|
|
43030
|
-
const
|
|
43402
|
+
const percent3 = ratio === void 0 ? "—" : `${Math.round(ratio * 100)}%`;
|
|
43031
43403
|
const color = (c, text) => theme ? theme.fg(c, text) : text;
|
|
43032
43404
|
const head = label2 === void 0 || label2 === "" ? "" : `${label2} `;
|
|
43033
43405
|
const filled = ratio === void 0 ? 0 : Math.round(ratio * cells);
|
|
43034
43406
|
const glyphs = theme?.glyphs ?? UNICODE_GLYPHS;
|
|
43035
43407
|
const bar = color(this.level(), glyphs.meterFull.repeat(filled)) + color("dim", glyphs.meterEmpty.repeat(cells - filled));
|
|
43036
|
-
const tail = color(ratio === void 0 ? "dim" : this.level(),
|
|
43408
|
+
const tail = color(ratio === void 0 ? "dim" : this.level(), percent3);
|
|
43037
43409
|
const full = `${head}${bar} ${tail}`;
|
|
43038
43410
|
if (visibleWidth(full) <= width2) return [full];
|
|
43039
43411
|
return [truncateToWidth(`${head}${tail}`, width2)];
|
|
@@ -43229,7 +43601,7 @@ function promptChoice(options) {
|
|
|
43229
43601
|
`);
|
|
43230
43602
|
drawn = lines2.length;
|
|
43231
43603
|
};
|
|
43232
|
-
return new Promise((
|
|
43604
|
+
return new Promise((resolve39) => {
|
|
43233
43605
|
const wasRaw = input2.isRaw === true;
|
|
43234
43606
|
let done = false;
|
|
43235
43607
|
const restore = () => {
|
|
@@ -43246,7 +43618,7 @@ function promptChoice(options) {
|
|
|
43246
43618
|
draw([`${question} ${theme.fg("dim", answer)}`]);
|
|
43247
43619
|
restore();
|
|
43248
43620
|
input2.pause?.();
|
|
43249
|
-
|
|
43621
|
+
resolve39(index2);
|
|
43250
43622
|
};
|
|
43251
43623
|
const onKey = (key) => {
|
|
43252
43624
|
const letter = /^[a-z]$/i.test(key) ? key.toLowerCase() : "";
|
|
@@ -44303,12 +44675,12 @@ function cacheMissNotice(miss) {
|
|
|
44303
44675
|
}
|
|
44304
44676
|
function contextPressureNotice(event) {
|
|
44305
44677
|
const m = msg().report.cache;
|
|
44306
|
-
const
|
|
44678
|
+
const percent3 = Math.round(event.percent);
|
|
44307
44679
|
if (event.estimatedTurnsLeft !== void 0)
|
|
44308
|
-
return m.pressureTurns(
|
|
44680
|
+
return m.pressureTurns(percent3, event.estimatedTurnsLeft);
|
|
44309
44681
|
if (event.remainingTokens !== void 0)
|
|
44310
|
-
return m.pressureTokens(
|
|
44311
|
-
return m.pressure(
|
|
44682
|
+
return m.pressureTokens(percent3, formatTokenCount(event.remainingTokens));
|
|
44683
|
+
return m.pressure(percent3);
|
|
44312
44684
|
}
|
|
44313
44685
|
function cacheEventNotice(event, enabled) {
|
|
44314
44686
|
if (!enabled) return void 0;
|
|
@@ -44468,7 +44840,7 @@ function describeSession(session, now = Date.now()) {
|
|
|
44468
44840
|
const stats = session.getStats();
|
|
44469
44841
|
const model = state.model === void 0 ? "?" : `${state.model.provider}/${state.model.id}`;
|
|
44470
44842
|
const t = stats.tokens;
|
|
44471
|
-
const
|
|
44843
|
+
const percent3 = stats.contextPercent === void 0 ? "?" : `${Math.round(stats.contextPercent)}`;
|
|
44472
44844
|
const m = msg().report.session;
|
|
44473
44845
|
const rows = [
|
|
44474
44846
|
{ key: m.keySession, value: m.session(state.sessionId, state.sessionFile) },
|
|
@@ -44495,7 +44867,7 @@ function describeSession(session, now = Date.now()) {
|
|
|
44495
44867
|
value: m.context(
|
|
44496
44868
|
String(stats.contextTokens ?? "?"),
|
|
44497
44869
|
String(stats.contextWindow ?? "?"),
|
|
44498
|
-
|
|
44870
|
+
percent3
|
|
44499
44871
|
)
|
|
44500
44872
|
}
|
|
44501
44873
|
];
|
|
@@ -44541,6 +44913,115 @@ var init_session_report = __esm({
|
|
|
44541
44913
|
}
|
|
44542
44914
|
});
|
|
44543
44915
|
|
|
44916
|
+
// src/modes/interactive/status-quota.ts
|
|
44917
|
+
function formatRemaining(ms, tight = false) {
|
|
44918
|
+
const minutes = Math.max(0, Math.floor(ms / 6e4));
|
|
44919
|
+
const days = Math.floor(minutes / 1440);
|
|
44920
|
+
const hours = Math.floor(minutes % 1440 / 60);
|
|
44921
|
+
const sep5 = tight ? "" : " ";
|
|
44922
|
+
if (days > 0) return `${days}d${sep5}${hours}h`;
|
|
44923
|
+
if (hours > 0) return `${hours}h${sep5}${minutes % 60}m`;
|
|
44924
|
+
return `${minutes}m`;
|
|
44925
|
+
}
|
|
44926
|
+
function windowSpan(minutes) {
|
|
44927
|
+
if (minutes % 1440 === 0) return `${minutes / 1440}d`;
|
|
44928
|
+
if (minutes % 60 === 0) return `${minutes / 60}h`;
|
|
44929
|
+
return `${Math.round(minutes)}m`;
|
|
44930
|
+
}
|
|
44931
|
+
function labels(w, which) {
|
|
44932
|
+
const m = msg().interactive.statusLine.quota;
|
|
44933
|
+
const minutes = w.windowMinutes;
|
|
44934
|
+
const standard = minutes === void 0 || minutes === (which === "primary" ? FIVE_HOURS : WEEK);
|
|
44935
|
+
if (!standard)
|
|
44936
|
+
return { pct: m.window(windowSpan(minutes)), reset: m.windowReset(windowSpan(minutes)) };
|
|
44937
|
+
return which === "primary" ? { pct: m.session, reset: m.reset } : { pct: m.weekly, reset: m.weeklyReset };
|
|
44938
|
+
}
|
|
44939
|
+
function shortLabel(w, which) {
|
|
44940
|
+
const m = msg().interactive.statusLine.quota;
|
|
44941
|
+
const minutes = w.windowMinutes;
|
|
44942
|
+
if (minutes === FIVE_HOURS || minutes === void 0 && which === "primary") return m.short5h;
|
|
44943
|
+
if (minutes === WEEK || minutes === void 0 && which === "secondary") return m.shortWeek;
|
|
44944
|
+
return windowSpan(minutes);
|
|
44945
|
+
}
|
|
44946
|
+
function percent2(theme, used, decimal) {
|
|
44947
|
+
return theme.fg(levelColor(used / 100), decimal ? `${used.toFixed(1)}%` : `${Math.round(used)}%`);
|
|
44948
|
+
}
|
|
44949
|
+
function windows(quota) {
|
|
44950
|
+
const out = [];
|
|
44951
|
+
if (quota.primary !== void 0) out.push(["primary", quota.primary]);
|
|
44952
|
+
if (quota.secondary !== void 0) out.push(["secondary", quota.secondary]);
|
|
44953
|
+
return out;
|
|
44954
|
+
}
|
|
44955
|
+
function compactQuotaItem(quota, theme) {
|
|
44956
|
+
const dim = (text) => theme.fg("dim", text);
|
|
44957
|
+
const items = windows(quota).map(
|
|
44958
|
+
([which, w]) => `${dim(shortLabel(w, which))} ${percent2(theme, w.usedPercent, false)}`
|
|
44959
|
+
);
|
|
44960
|
+
return items.length === 0 ? void 0 : items.join(" ");
|
|
44961
|
+
}
|
|
44962
|
+
function quotaParts2(quota, width2, now, theme) {
|
|
44963
|
+
const dim = (text) => theme.fg("dim", text);
|
|
44964
|
+
const narrow = width2 < QUOTA_NARROW_WIDTH;
|
|
44965
|
+
const parts = [];
|
|
44966
|
+
windows(quota).forEach(([which, w], i) => {
|
|
44967
|
+
const first = i === 0;
|
|
44968
|
+
const group = narrow ? which : void 0;
|
|
44969
|
+
const name = narrow ? `${shortLabel(w, which)} ` : labels(w, which).pct;
|
|
44970
|
+
parts.push({
|
|
44971
|
+
text: dim(name) + percent2(theme, w.usedPercent, !narrow),
|
|
44972
|
+
priority: first ? void 0 : 2,
|
|
44973
|
+
zone: "left",
|
|
44974
|
+
...group !== void 0 ? { group } : {}
|
|
44975
|
+
});
|
|
44976
|
+
if (w.resetsAt === void 0) return;
|
|
44977
|
+
const left = formatRemaining(w.resetsAt - now, narrow);
|
|
44978
|
+
parts.push({
|
|
44979
|
+
text: narrow ? theme.fg("tool", `${theme.glyphs.retry}${left}`) : dim(labels(w, which).reset) + theme.fg("tool", left),
|
|
44980
|
+
priority: first ? 3 : 1,
|
|
44981
|
+
zone: "left",
|
|
44982
|
+
// 宽格式按最宽形状占位(`23h 59m`),数值变化不让某项时有时无
|
|
44983
|
+
reserve: narrow ? 0 : visibleWidth(labels(w, which).reset) + 7,
|
|
44984
|
+
...group !== void 0 ? { group } : {}
|
|
44985
|
+
});
|
|
44986
|
+
});
|
|
44987
|
+
return parts;
|
|
44988
|
+
}
|
|
44989
|
+
var QUOTA_NARROW_WIDTH, FIVE_HOURS, WEEK, QuotaLine;
|
|
44990
|
+
var init_status_quota = __esm({
|
|
44991
|
+
"src/modes/interactive/status-quota.ts"() {
|
|
44992
|
+
"use strict";
|
|
44993
|
+
init_i18n();
|
|
44994
|
+
init_tui2();
|
|
44995
|
+
init_status_bar();
|
|
44996
|
+
QUOTA_NARROW_WIDTH = 80;
|
|
44997
|
+
FIVE_HOURS = 300;
|
|
44998
|
+
WEEK = 10080;
|
|
44999
|
+
QuotaLine = class {
|
|
45000
|
+
constructor(source, theme) {
|
|
45001
|
+
this.source = source;
|
|
45002
|
+
this.theme = theme;
|
|
45003
|
+
}
|
|
45004
|
+
source;
|
|
45005
|
+
theme;
|
|
45006
|
+
render(width2) {
|
|
45007
|
+
if (this.source.layout() !== "full") return [];
|
|
45008
|
+
const view = this.source.quota();
|
|
45009
|
+
if (view === void 0) return [];
|
|
45010
|
+
const theme = this.theme;
|
|
45011
|
+
if (view === "pending") {
|
|
45012
|
+
return [truncateToWidth(theme.fg("dim", msg().interactive.statusLine.quota.pending), width2)];
|
|
45013
|
+
}
|
|
45014
|
+
const parts = quotaParts2(view.quota, width2, this.source.now(), theme);
|
|
45015
|
+
if (parts.length === 0) return [];
|
|
45016
|
+
const sep5 = width2 < QUOTA_NARROW_WIDTH ? " · " : " | ";
|
|
45017
|
+
return [layoutRow(parts, width2, theme, { sep: sep5 })];
|
|
45018
|
+
}
|
|
45019
|
+
invalidate() {
|
|
45020
|
+
}
|
|
45021
|
+
};
|
|
45022
|
+
}
|
|
45023
|
+
});
|
|
45024
|
+
|
|
44544
45025
|
// src/modes/interactive/status-bar.ts
|
|
44545
45026
|
function formatTokens3(count2) {
|
|
44546
45027
|
if (count2 < 1e3) return String(count2);
|
|
@@ -44672,6 +45153,7 @@ var init_status_bar = __esm({
|
|
|
44672
45153
|
init_i18n();
|
|
44673
45154
|
init_modes();
|
|
44674
45155
|
init_channels();
|
|
45156
|
+
init_status_quota();
|
|
44675
45157
|
init_tui2();
|
|
44676
45158
|
MIN_GAP = 4;
|
|
44677
45159
|
METER_WIDTH = 110;
|
|
@@ -44691,7 +45173,8 @@ var init_status_bar = __esm({
|
|
|
44691
45173
|
rebill: 13,
|
|
44692
45174
|
preset: 14,
|
|
44693
45175
|
host: 15,
|
|
44694
|
-
hint: 16
|
|
45176
|
+
hint: 16,
|
|
45177
|
+
quota: 17
|
|
44695
45178
|
};
|
|
44696
45179
|
FULL = { model: 0, ctx: 1, cost: 2, duration: 3, branch: 4, dir: 5, diff: 6, thinking: 7 };
|
|
44697
45180
|
FULL_HINT = 12;
|
|
@@ -44751,7 +45234,8 @@ var init_status_bar = __esm({
|
|
|
44751
45234
|
const modelText = fallback === void 0 ? theme.fg("accent", model) : theme.fg("accent", abbreviateModel(fallback.from, width2)) + dim(g.ascii ? " -> " : " → ") + theme.fg("warning", abbreviateModel(fallback.to, width2));
|
|
44752
45235
|
right(modelText, p.model, full ? { group: "model" } : {});
|
|
44753
45236
|
if (state.thinkingLevel !== "off") {
|
|
44754
|
-
|
|
45237
|
+
const level = full ? theme.fg("user", state.thinkingLevel) : dim(state.thinkingLevel);
|
|
45238
|
+
right(level, p.thinking, full ? { group: "model" } : {});
|
|
44755
45239
|
}
|
|
44756
45240
|
const usage = full ? {} : usageItems(stats, this.queue, this.source, theme);
|
|
44757
45241
|
if (usage.tokens !== void 0) right(usage.tokens, COMPACT.tokens);
|
|
@@ -44764,50 +45248,71 @@ var init_status_bar = __esm({
|
|
|
44764
45248
|
const cost2 = statusCost(stats);
|
|
44765
45249
|
const used = stats.tokens.input + stats.tokens.output + stats.tokens.cacheRead > 0;
|
|
44766
45250
|
if (cost2 === void 0 && used) right(dim("$?"), FULL.cost);
|
|
44767
|
-
else if (cost2 !== void 0 && cost2 > 0)
|
|
45251
|
+
else if (cost2 !== void 0 && cost2 > 0) {
|
|
45252
|
+
right(theme.fg("warning", formatCost(cost2)), FULL.cost);
|
|
45253
|
+
}
|
|
44768
45254
|
}
|
|
44769
45255
|
const started = this.source.sessionStartedAt?.() ?? stats.telemetry?.sessionStartedAt;
|
|
44770
45256
|
if (started !== void 0) {
|
|
44771
45257
|
const now = this.source.now?.() ?? Date.now();
|
|
44772
|
-
|
|
45258
|
+
const text = formatDuration4(now - started);
|
|
45259
|
+
right(full ? theme.fg("tool", text) : dim(text), p.duration, { reserve: 6 });
|
|
44773
45260
|
}
|
|
44774
45261
|
if (usage.queue !== void 0) right(usage.queue, COMPACT.queue);
|
|
44775
45262
|
if (usage.codemode !== void 0) right(usage.codemode, COMPACT.codemode);
|
|
44776
45263
|
if (usage.sandbox !== void 0) right(usage.sandbox, COMPACT.codemode);
|
|
44777
45264
|
if (usage.preset !== void 0) right(usage.preset, COMPACT.preset);
|
|
44778
45265
|
if (usage.host !== void 0) right(usage.host, COMPACT.host);
|
|
45266
|
+
const quota = full ? void 0 : this.source.quota?.();
|
|
45267
|
+
const quotaItem = typeof quota === "object" ? compactQuotaItem(quota.quota, theme) : void 0;
|
|
45268
|
+
if (quotaItem !== void 0) right(quotaItem, COMPACT.quota);
|
|
44779
45269
|
return parts;
|
|
44780
45270
|
}
|
|
44781
|
-
/** `目录 ⎇ 分支 短提交 +a −b
|
|
45271
|
+
/** `目录 ⎇ 分支 短提交 +a −b`:三项同组、各自按优先级丢弃;full 另带 `↑N ↓N` 并按参考配色。 */
|
|
44782
45272
|
gitParts(p, full) {
|
|
44783
45273
|
const git = this.source.git?.();
|
|
44784
45274
|
if (git === void 0) return [];
|
|
44785
45275
|
const theme = this.theme;
|
|
44786
45276
|
const g = theme.glyphs;
|
|
44787
45277
|
const dim = (text) => theme.fg("dim", text);
|
|
45278
|
+
const ok = (text) => full ? theme.fg("success", text) : dim(text);
|
|
44788
45279
|
const out = [];
|
|
44789
|
-
const add3 = (text, priority) => void out.push({ text
|
|
44790
|
-
if (git.dir !== "") add3(git.dir, p.dir);
|
|
45280
|
+
const add3 = (text, priority) => void out.push({ text, priority, zone: "right", group: "git" });
|
|
45281
|
+
if (git.dir !== "") add3(ok(git.dir), p.dir);
|
|
44791
45282
|
const info2 = git.info;
|
|
44792
45283
|
if (info2 === void 0) return out;
|
|
44793
|
-
const head = [
|
|
44794
|
-
if (
|
|
45284
|
+
const head = [];
|
|
45285
|
+
if (info2.branch !== void 0) head.push(ok(info2.branch));
|
|
45286
|
+
if (info2.shortHead !== void 0) head.push(dim(info2.shortHead));
|
|
45287
|
+
if (full && info2.ahead !== void 0 && info2.ahead > 0) {
|
|
45288
|
+
head.push(theme.fg("code", `${g.arrowUp}${info2.ahead}`));
|
|
45289
|
+
}
|
|
45290
|
+
if (full && info2.behind !== void 0 && info2.behind > 0) {
|
|
45291
|
+
head.push(theme.fg("error", `${g.arrowDown}${info2.behind}`));
|
|
45292
|
+
}
|
|
45293
|
+
if (!full) {
|
|
45294
|
+
const text = [info2.branch, info2.shortHead].filter((s2) => s2 !== void 0).join(" ");
|
|
45295
|
+
if (text !== "") add3(dim(`${g.branch} ${text}`), p.branch);
|
|
45296
|
+
} else if (head.length > 0) add3(`${dim(g.branch)} ${head.join(" ")}`, p.branch);
|
|
44795
45297
|
if (info2.insertions !== void 0 && info2.deletions !== void 0) {
|
|
44796
45298
|
const { insertions: a, deletions: d } = info2;
|
|
44797
|
-
add3(
|
|
45299
|
+
add3(
|
|
45300
|
+
full ? `${dim("(")}${theme.fg("success", `+${a}`)}${dim(",")}${theme.fg("error", `-${d}`)}${dim(")")}` : dim(`+${a} ${g.ascii ? "-" : "−"}${d}`),
|
|
45301
|
+
p.diff
|
|
45302
|
+
);
|
|
44798
45303
|
}
|
|
44799
45304
|
return out;
|
|
44800
45305
|
}
|
|
44801
|
-
ctxText(
|
|
45306
|
+
ctxText(percent3, width2, decimal) {
|
|
44802
45307
|
const theme = this.theme;
|
|
44803
|
-
if (
|
|
44804
|
-
const color = levelColor(
|
|
45308
|
+
if (percent3 === void 0) return theme.fg("dim", decimal ? "Ctx ?" : "ctx ?");
|
|
45309
|
+
const color = levelColor(percent3 / 100);
|
|
44805
45310
|
if (!decimal && width2 >= METER_WIDTH) {
|
|
44806
|
-
const meter = new Meter(
|
|
45311
|
+
const meter = new Meter(percent3 / 100, { label: theme.fg("dim", "ctx"), theme });
|
|
44807
45312
|
return meter.render(80)[0] ?? "";
|
|
44808
45313
|
}
|
|
44809
|
-
if (decimal) return theme.fg("dim", "Ctx ") + theme.fg(color, `${
|
|
44810
|
-
return theme.fg("dim", "ctx ") + theme.fg(color, `${Math.round(
|
|
45314
|
+
if (decimal) return theme.fg("dim", "Ctx ") + theme.fg(color, `${percent3.toFixed(1)}%`);
|
|
45315
|
+
return theme.fg("dim", "ctx ") + theme.fg(color, `${Math.round(percent3)}%`);
|
|
44811
45316
|
}
|
|
44812
45317
|
render(width2) {
|
|
44813
45318
|
const style = this.layout() === "full" ? FULL_STYLE : {};
|
|
@@ -46358,7 +46863,7 @@ async function runSandbox(request) {
|
|
|
46358
46863
|
let stderr = "";
|
|
46359
46864
|
let settled = false;
|
|
46360
46865
|
let finish2;
|
|
46361
|
-
const finished = new Promise((
|
|
46866
|
+
const finished = new Promise((resolve39) => finish2 = resolve39);
|
|
46362
46867
|
const write2 = (message) => {
|
|
46363
46868
|
if (child.stdin.destroyed || !child.stdin.writable) return;
|
|
46364
46869
|
child.stdin.write(encodeLine(message));
|
|
@@ -47246,7 +47751,8 @@ __export(print_mode_exports, {
|
|
|
47246
47751
|
joinPrompt: () => joinPrompt,
|
|
47247
47752
|
readPromptStdin: () => readPromptStdin,
|
|
47248
47753
|
runPrintMode: () => runPrintMode,
|
|
47249
|
-
stdinWaitMs: () => stdinWaitMs
|
|
47754
|
+
stdinWaitMs: () => stdinWaitMs,
|
|
47755
|
+
waitBackgroundTasks: () => waitBackgroundTasks
|
|
47250
47756
|
});
|
|
47251
47757
|
function joinPrompt(argument, piped) {
|
|
47252
47758
|
const parts = [argument ?? "", piped.replace(/\s+$/, "")].filter((p) => p.trim() !== "");
|
|
@@ -47260,12 +47766,12 @@ function stdinWaitMs(env) {
|
|
|
47260
47766
|
}
|
|
47261
47767
|
function readWithin(io, ms) {
|
|
47262
47768
|
if (io.readStdinFirstByte !== void 0) return io.readStdinFirstByte(ms);
|
|
47263
|
-
return new Promise((
|
|
47264
|
-
const timer = setTimeout(() =>
|
|
47769
|
+
return new Promise((resolve39, reject2) => {
|
|
47770
|
+
const timer = setTimeout(() => resolve39(void 0), ms);
|
|
47265
47771
|
io.readStdin().then(
|
|
47266
47772
|
(text) => {
|
|
47267
47773
|
clearTimeout(timer);
|
|
47268
|
-
|
|
47774
|
+
resolve39(text);
|
|
47269
47775
|
},
|
|
47270
47776
|
(error2) => {
|
|
47271
47777
|
clearTimeout(timer);
|
|
@@ -47328,9 +47834,15 @@ async function runPrintMode(runtime, context) {
|
|
|
47328
47834
|
const denied = [];
|
|
47329
47835
|
let limit;
|
|
47330
47836
|
let plan2;
|
|
47837
|
+
let stopWaiting = () => void 0;
|
|
47838
|
+
const stopped = new Promise((resolve39) => {
|
|
47839
|
+
stopWaiting = resolve39;
|
|
47840
|
+
});
|
|
47331
47841
|
const unsubscribe = session.subscribe((event) => {
|
|
47332
|
-
if (event.type === "limit_reached")
|
|
47333
|
-
|
|
47842
|
+
if (event.type === "limit_reached") {
|
|
47843
|
+
limit ??= event;
|
|
47844
|
+
stopWaiting();
|
|
47845
|
+
} else if (event.type === "plan_proposed") plan2 = event;
|
|
47334
47846
|
else if (event.type === "plan_resolved" && event.planId === plan2?.planId) plan2 = void 0;
|
|
47335
47847
|
if (event.type === "tool_execution_end" && event.denied === true)
|
|
47336
47848
|
denied.push({
|
|
@@ -47353,16 +47865,21 @@ async function runPrintMode(runtime, context) {
|
|
|
47353
47865
|
let signalled;
|
|
47354
47866
|
const offSignals = onTerminationSignals((code) => {
|
|
47355
47867
|
signalled ??= code;
|
|
47868
|
+
stopWaiting();
|
|
47356
47869
|
void session.abort();
|
|
47357
47870
|
});
|
|
47358
47871
|
let stdoutClosed = false;
|
|
47359
47872
|
const offEpipe = onStdoutClosed(() => {
|
|
47360
47873
|
stdoutClosed = true;
|
|
47874
|
+
stopWaiting();
|
|
47361
47875
|
void session.abort();
|
|
47362
47876
|
});
|
|
47363
47877
|
let failure2;
|
|
47364
47878
|
try {
|
|
47365
47879
|
await session.prompt(prompt, images.length > 0 ? { images } : {});
|
|
47880
|
+
const ended = lastAssistant(session)?.stopReason;
|
|
47881
|
+
if (signalled === void 0 && !stdoutClosed && limit === void 0 && ended !== "error" && ended !== "aborted")
|
|
47882
|
+
await waitBackgroundTasks(session, stopped, io);
|
|
47366
47883
|
} catch (error2) {
|
|
47367
47884
|
failure2 = errorText3(error2);
|
|
47368
47885
|
} finally {
|
|
@@ -47393,6 +47910,7 @@ async function runPrintMode(runtime, context) {
|
|
|
47393
47910
|
cost: stats.cost,
|
|
47394
47911
|
cacheHitRate: stats.cacheHitRate,
|
|
47395
47912
|
...stats.cache !== void 0 ? { cache: stats.cache } : {},
|
|
47913
|
+
...stats.tasks !== void 0 ? { tasks: stats.tasks } : {},
|
|
47396
47914
|
...denied.length > 0 ? { deniedTools: denied } : {},
|
|
47397
47915
|
...plan2 !== void 0 ? {
|
|
47398
47916
|
planPending: {
|
|
@@ -47439,6 +47957,13 @@ async function runPrintMode(runtime, context) {
|
|
|
47439
47957
|
if (denied.length > 0) return ExitCode.ToolDenied;
|
|
47440
47958
|
return ExitCode.Ok;
|
|
47441
47959
|
}
|
|
47960
|
+
async function waitBackgroundTasks(session, stopped, io) {
|
|
47961
|
+
const registry2 = registryOf(session.state.sessionId);
|
|
47962
|
+
if (registry2 === void 0) return;
|
|
47963
|
+
const running = registry2.list().filter((task) => task.status === "running").length;
|
|
47964
|
+
if (running > 0) io.stderr(msg().print.print.waitingTasks(running));
|
|
47965
|
+
await Promise.race([registry2.settled(), stopped]);
|
|
47966
|
+
}
|
|
47442
47967
|
function describePlanPending(plan2) {
|
|
47443
47968
|
const where = plan2.filePath ?? plan2.planId;
|
|
47444
47969
|
return msg().print.print.planPending(plan2.version, where);
|
|
@@ -47467,6 +47992,7 @@ var init_print_mode = __esm({
|
|
|
47467
47992
|
init_shared2();
|
|
47468
47993
|
init_json_event();
|
|
47469
47994
|
init_limits();
|
|
47995
|
+
init_subagent_registry();
|
|
47470
47996
|
init_image_input();
|
|
47471
47997
|
init_i18n();
|
|
47472
47998
|
STDIN_WAIT_HINT_MS = 3e3;
|
|
@@ -48266,6 +48792,59 @@ var init_tasks_report = __esm({
|
|
|
48266
48792
|
}
|
|
48267
48793
|
});
|
|
48268
48794
|
|
|
48795
|
+
// src/modes/interactive/task-background.ts
|
|
48796
|
+
function blockingTasks2(session) {
|
|
48797
|
+
return registryOf(session.state.sessionId)?.blocking() ?? [];
|
|
48798
|
+
}
|
|
48799
|
+
function backgroundTasks(session, taskId) {
|
|
48800
|
+
if (taskId === void 0 && blockingTasks2(session).length === 0) return [];
|
|
48801
|
+
return session.backgroundTask(taskId, "user");
|
|
48802
|
+
}
|
|
48803
|
+
function runningBackground(session) {
|
|
48804
|
+
const registry2 = registryOf(session.state.sessionId);
|
|
48805
|
+
if (registry2 === void 0) return [];
|
|
48806
|
+
return registry2.list().filter((task) => task.status === "running" && task.background).map((task) => task.taskId);
|
|
48807
|
+
}
|
|
48808
|
+
function backgroundedText2(ids) {
|
|
48809
|
+
const m = msg().agents.background;
|
|
48810
|
+
return ids.length === 0 ? m.none : m.done(ids.join(", "));
|
|
48811
|
+
}
|
|
48812
|
+
function keyLabel(keys, action) {
|
|
48813
|
+
const id = keys.keys(action)[0];
|
|
48814
|
+
if (id === void 0) return void 0;
|
|
48815
|
+
return id.split("+").map(
|
|
48816
|
+
(part) => part.length === 1 ? part.toUpperCase() : part[0].toUpperCase() + part.slice(1)
|
|
48817
|
+
).join("+");
|
|
48818
|
+
}
|
|
48819
|
+
var STOP_CONFIRM_MS, StopArm;
|
|
48820
|
+
var init_task_background = __esm({
|
|
48821
|
+
"src/modes/interactive/task-background.ts"() {
|
|
48822
|
+
"use strict";
|
|
48823
|
+
init_subagent_registry();
|
|
48824
|
+
init_i18n();
|
|
48825
|
+
STOP_CONFIRM_MS = 1500;
|
|
48826
|
+
StopArm = class {
|
|
48827
|
+
constructor(windowMs = STOP_CONFIRM_MS) {
|
|
48828
|
+
this.windowMs = windowMs;
|
|
48829
|
+
}
|
|
48830
|
+
windowMs;
|
|
48831
|
+
armed;
|
|
48832
|
+
press(taskId, now) {
|
|
48833
|
+
const armed = this.armed;
|
|
48834
|
+
if (armed !== void 0 && armed.taskId === taskId && now - armed.at < this.windowMs) {
|
|
48835
|
+
this.armed = void 0;
|
|
48836
|
+
return "stop";
|
|
48837
|
+
}
|
|
48838
|
+
this.armed = { taskId, at: now };
|
|
48839
|
+
return "arm";
|
|
48840
|
+
}
|
|
48841
|
+
reset() {
|
|
48842
|
+
this.armed = void 0;
|
|
48843
|
+
}
|
|
48844
|
+
};
|
|
48845
|
+
}
|
|
48846
|
+
});
|
|
48847
|
+
|
|
48269
48848
|
// src/modes/commands-core.ts
|
|
48270
48849
|
function command(name, key, args) {
|
|
48271
48850
|
const info2 = {
|
|
@@ -48313,10 +48892,13 @@ function cacheCommand(session, args) {
|
|
|
48313
48892
|
}
|
|
48314
48893
|
throw new AmaError("invalid_arguments", msg().report.command.cacheUsage);
|
|
48315
48894
|
}
|
|
48316
|
-
async function tasksCommand(
|
|
48895
|
+
async function tasksCommand(session, args) {
|
|
48896
|
+
const sessionId = session.state.sessionId;
|
|
48317
48897
|
const [first, second, extra] = args.split(/\s+/).filter((s2) => s2 !== "");
|
|
48318
48898
|
const now = Date.now();
|
|
48319
48899
|
if (first === void 0) return describeTasks(sessionId, now);
|
|
48900
|
+
if (first === "bg" && extra === void 0)
|
|
48901
|
+
return backgroundedText2(backgroundTasks(session, second));
|
|
48320
48902
|
if (first === "stop" && second !== void 0 && extra === void 0) {
|
|
48321
48903
|
await stopTask(sessionId, second);
|
|
48322
48904
|
return msg().report.command.taskStopped(second);
|
|
@@ -48441,7 +49023,7 @@ async function runSlashCommand(line2, ctx) {
|
|
|
48441
49023
|
case "plan":
|
|
48442
49024
|
return planCommand(session, args, ctx);
|
|
48443
49025
|
case "tasks":
|
|
48444
|
-
return { kind: "handled", message: await tasksCommand(session
|
|
49026
|
+
return { kind: "handled", message: await tasksCommand(session, args) };
|
|
48445
49027
|
case "agents":
|
|
48446
49028
|
return { kind: "handled", message: describeAgents(session.state.sessionId) };
|
|
48447
49029
|
case "paste": {
|
|
@@ -48475,6 +49057,7 @@ var init_commands_core = __esm({
|
|
|
48475
49057
|
init_plan_command();
|
|
48476
49058
|
init_rewind_command();
|
|
48477
49059
|
init_tasks_report();
|
|
49060
|
+
init_task_background();
|
|
48478
49061
|
init_session_report();
|
|
48479
49062
|
init_i18n();
|
|
48480
49063
|
BUILTIN_COMMANDS = [
|
|
@@ -48493,7 +49076,7 @@ var init_commands_core = __esm({
|
|
|
48493
49076
|
command("cache", "cache", "[warm off|streaming|idle | fingerprint]"),
|
|
48494
49077
|
command("statusline", "statusline", "[full|compact]"),
|
|
48495
49078
|
command("plan", "plan", { key: "planArgs" }),
|
|
48496
|
-
command("tasks", "tasks", "[id] | stop <id>"),
|
|
49079
|
+
command("tasks", "tasks", "[id] | stop <id> | bg [id]"),
|
|
48497
49080
|
command("agents", "agents"),
|
|
48498
49081
|
command("paste", "paste"),
|
|
48499
49082
|
command("exit", "exit"),
|
|
@@ -48550,9 +49133,9 @@ async function startRun(ctx, run7) {
|
|
|
48550
49133
|
const session = ctx.session();
|
|
48551
49134
|
let settled = false;
|
|
48552
49135
|
let off = () => void 0;
|
|
48553
|
-
const started = new Promise((
|
|
49136
|
+
const started = new Promise((resolve39) => {
|
|
48554
49137
|
off = session.subscribe((event) => {
|
|
48555
|
-
if (event.type === "before_agent_start" || event.type === "agent_start")
|
|
49138
|
+
if (event.type === "before_agent_start" || event.type === "agent_start") resolve39("started");
|
|
48556
49139
|
});
|
|
48557
49140
|
});
|
|
48558
49141
|
const running = run7().finally(() => {
|
|
@@ -48635,11 +49218,11 @@ var init_commands = __esm({
|
|
|
48635
49218
|
this.early.delete(request.requestId);
|
|
48636
49219
|
return Promise.resolve(ready);
|
|
48637
49220
|
}
|
|
48638
|
-
return new Promise((
|
|
49221
|
+
return new Promise((resolve39) => {
|
|
48639
49222
|
const done = (decision) => {
|
|
48640
49223
|
this.pending.delete(request.requestId);
|
|
48641
49224
|
signal.removeEventListener("abort", onAbort);
|
|
48642
|
-
|
|
49225
|
+
resolve39(decision);
|
|
48643
49226
|
};
|
|
48644
49227
|
const onAbort = () => done(void 0);
|
|
48645
49228
|
if (signal.aborted) return done(void 0);
|
|
@@ -48649,9 +49232,9 @@ var init_commands = __esm({
|
|
|
48649
49232
|
}
|
|
48650
49233
|
/** 返回 false = 当前没有在等这个 requestId(已暂存,稍后被问到时生效)。 */
|
|
48651
49234
|
respond(requestId, decision) {
|
|
48652
|
-
const
|
|
48653
|
-
if (
|
|
48654
|
-
|
|
49235
|
+
const resolve39 = this.pending.get(requestId);
|
|
49236
|
+
if (resolve39 !== void 0) {
|
|
49237
|
+
resolve39(decision);
|
|
48655
49238
|
return true;
|
|
48656
49239
|
}
|
|
48657
49240
|
this.early.set(requestId, decision);
|
|
@@ -48659,7 +49242,7 @@ var init_commands = __esm({
|
|
|
48659
49242
|
}
|
|
48660
49243
|
/** 关 stdin / 撤下时:全部弃权(会话按无人作答 deny)。 */
|
|
48661
49244
|
cancelAll() {
|
|
48662
|
-
for (const
|
|
49245
|
+
for (const resolve39 of [...this.pending.values()]) resolve39(void 0);
|
|
48663
49246
|
this.early.clear();
|
|
48664
49247
|
}
|
|
48665
49248
|
};
|
|
@@ -48818,7 +49401,14 @@ var init_commands = __esm({
|
|
|
48818
49401
|
get_tasks: async (_p, ctx) => ({ tasks: [...ctx.tasks?.()?.list() ?? []] }),
|
|
48819
49402
|
get_agents: async (_p, ctx) => ({ agents: [...ctx.agents?.() ?? []] }),
|
|
48820
49403
|
// [W6-T2] 轨迹(docs/wave6-plan.md §2.6;分页 / 增量 / 脱敏见 trace/query.ts)
|
|
48821
|
-
get_trace: async (p, ctx) => sessionTrace(ctx.session(), p ?? {})
|
|
49404
|
+
get_trace: async (p, ctx) => sessionTrace(ctx.session(), p ?? {}),
|
|
49405
|
+
// [W7-B2] 前台任务转后台:工具调用立即返回、任务继续,完成后照常通知
|
|
49406
|
+
background_task: async (p, ctx) => {
|
|
49407
|
+
const taskId = p?.taskId;
|
|
49408
|
+
if (taskId !== void 0 && typeof taskId !== "string")
|
|
49409
|
+
throw new AmaError("invalid_arguments", msg().print.rpc.badTaskId);
|
|
49410
|
+
return { backgrounded: ctx.session().backgroundTask(taskId) };
|
|
49411
|
+
}
|
|
48822
49412
|
};
|
|
48823
49413
|
RPC_COMMAND_TYPES = Object.keys(handlers);
|
|
48824
49414
|
}
|
|
@@ -48937,7 +49527,7 @@ async function runRpcMode(runtime, context, options = {}) {
|
|
|
48937
49527
|
const task = respond(command3).finally(() => inflight2.delete(task));
|
|
48938
49528
|
inflight2.add(task);
|
|
48939
49529
|
};
|
|
48940
|
-
return new Promise((
|
|
49530
|
+
return new Promise((resolve39) => {
|
|
48941
49531
|
let finished = false;
|
|
48942
49532
|
const finish2 = async (code, abort) => {
|
|
48943
49533
|
if (finished) return;
|
|
@@ -48953,7 +49543,7 @@ async function runRpcMode(runtime, context, options = {}) {
|
|
|
48953
49543
|
unsubscribe();
|
|
48954
49544
|
runtime.notifier.set(void 0);
|
|
48955
49545
|
await writing;
|
|
48956
|
-
|
|
49546
|
+
resolve39(code);
|
|
48957
49547
|
};
|
|
48958
49548
|
const reader = createLineReader(stdin, onLine, () => void finish2(ExitCode.Ok, false));
|
|
48959
49549
|
const offSignals = onTerminationSignals((code) => {
|
|
@@ -49023,8 +49613,8 @@ function startupScreenLevel(runtime) {
|
|
|
49023
49613
|
return runtime.config.ui?.quietStartup ?? "normal";
|
|
49024
49614
|
}
|
|
49025
49615
|
function trustSourceLabel(source) {
|
|
49026
|
-
const
|
|
49027
|
-
return source === "trust-file" ?
|
|
49616
|
+
const labels2 = msg().cli.startupScreen.trustSource;
|
|
49617
|
+
return source === "trust-file" ? labels2.trustFile : labels2[source];
|
|
49028
49618
|
}
|
|
49029
49619
|
function tildePath(path, home) {
|
|
49030
49620
|
if (home === void 0 || home === "") return path;
|
|
@@ -49092,7 +49682,7 @@ function blockedReason(spec2, value, scope) {
|
|
|
49092
49682
|
}
|
|
49093
49683
|
function settingRows(snapshot2, scope, theme) {
|
|
49094
49684
|
const s2 = msg().settings;
|
|
49095
|
-
const
|
|
49685
|
+
const labels2 = s2.labels;
|
|
49096
49686
|
const rows = settingsRegistry().map((spec2) => {
|
|
49097
49687
|
const value = getConfigValue(snapshot2, spec2.key);
|
|
49098
49688
|
const locked = overriddenFor(value, scope) !== void 0;
|
|
@@ -49107,7 +49697,7 @@ function settingRows(snapshot2, scope, theme) {
|
|
|
49107
49697
|
const row3 = {
|
|
49108
49698
|
id: spec2.key,
|
|
49109
49699
|
group: s2.groups[spec2.group],
|
|
49110
|
-
label:
|
|
49700
|
+
label: labels2[spec2.key] ?? spec2.key,
|
|
49111
49701
|
value: settingValueText(spec2, value, theme),
|
|
49112
49702
|
tag,
|
|
49113
49703
|
search: [...spec2.options ?? [], settingDoc(spec2.key) ?? ""].join(" ")
|
|
@@ -49342,14 +49932,14 @@ var init_config_panel = __esm({
|
|
|
49342
49932
|
|
|
49343
49933
|
// src/modes/interactive/confirm-dialog.ts
|
|
49344
49934
|
function openChoice(host, spec2) {
|
|
49345
|
-
return new Promise((
|
|
49935
|
+
return new Promise((resolve39) => {
|
|
49346
49936
|
let handle;
|
|
49347
49937
|
let settled = false;
|
|
49348
49938
|
const dialog = new ChoiceDialog(spec2, host, (index2) => {
|
|
49349
49939
|
if (settled) return;
|
|
49350
49940
|
settled = true;
|
|
49351
49941
|
handle?.hide();
|
|
49352
|
-
|
|
49942
|
+
resolve39(index2);
|
|
49353
49943
|
});
|
|
49354
49944
|
handle = host.showOverlay(
|
|
49355
49945
|
new Box(dialog, {
|
|
@@ -49541,6 +50131,12 @@ var init_subagent_view = __esm({
|
|
|
49541
50131
|
}
|
|
49542
50132
|
return state;
|
|
49543
50133
|
}
|
|
50134
|
+
case "subagent_background": {
|
|
50135
|
+
const state = this.tasks.get(event.taskId);
|
|
50136
|
+
if (state === void 0) return void 0;
|
|
50137
|
+
state.background = true;
|
|
50138
|
+
return state;
|
|
50139
|
+
}
|
|
49544
50140
|
case "subagent_end": {
|
|
49545
50141
|
const state = this.tasks.get(event.taskId);
|
|
49546
50142
|
if (state === void 0) return void 0;
|
|
@@ -49613,8 +50209,8 @@ function exitSummaryLines(stats, elapsedMs, theme) {
|
|
|
49613
50209
|
return lines2;
|
|
49614
50210
|
}
|
|
49615
50211
|
function originLabel(origin) {
|
|
49616
|
-
const
|
|
49617
|
-
return
|
|
50212
|
+
const labels2 = msg().interactive.view.message.origin;
|
|
50213
|
+
return labels2[origin] ?? origin;
|
|
49618
50214
|
}
|
|
49619
50215
|
function displayText(text) {
|
|
49620
50216
|
return text.includes("proposed_plan>") ? text.replace(PLAN_TAG_LINE, "") : text;
|
|
@@ -50027,11 +50623,11 @@ function pickerFooter(arrows = "↑↓") {
|
|
|
50027
50623
|
return msg().panels.picker.footer(arrows);
|
|
50028
50624
|
}
|
|
50029
50625
|
function openPicker(host, spec2) {
|
|
50030
|
-
return new Promise((
|
|
50626
|
+
return new Promise((resolve39) => {
|
|
50031
50627
|
let handle;
|
|
50032
50628
|
const close = (item) => {
|
|
50033
50629
|
handle?.hide();
|
|
50034
|
-
|
|
50630
|
+
resolve39(item);
|
|
50035
50631
|
};
|
|
50036
50632
|
const list5 = new SelectList(spec2.items, {
|
|
50037
50633
|
theme: host.theme,
|
|
@@ -51003,8 +51599,8 @@ var init_line_editor = __esm({
|
|
|
51003
51599
|
ask(question, fallback) {
|
|
51004
51600
|
this.hide();
|
|
51005
51601
|
this.options.write(question);
|
|
51006
|
-
return new Promise((
|
|
51007
|
-
this.question = { resolve:
|
|
51602
|
+
return new Promise((resolve39) => {
|
|
51603
|
+
this.question = { resolve: resolve39, fallback };
|
|
51008
51604
|
});
|
|
51009
51605
|
}
|
|
51010
51606
|
feed(data2) {
|
|
@@ -51323,6 +51919,12 @@ var init_tool_view = __esm({
|
|
|
51323
51919
|
);
|
|
51324
51920
|
}
|
|
51325
51921
|
const result = this.result;
|
|
51922
|
+
const moved = this.backgrounded();
|
|
51923
|
+
if (moved !== void 0) {
|
|
51924
|
+
const m = msg().agents.background;
|
|
51925
|
+
const text2 = moved ? m.moved(formatElapsed(this.elapsedMs)) : m.started;
|
|
51926
|
+
return truncateToWidth(lead + theme.fg("muted", text2), width2);
|
|
51927
|
+
}
|
|
51326
51928
|
const text = resultSummary(
|
|
51327
51929
|
{
|
|
51328
51930
|
name: this.toolName,
|
|
@@ -51337,6 +51939,17 @@ var init_tool_view = __esm({
|
|
|
51337
51939
|
);
|
|
51338
51940
|
return truncateToWidth(lead + text, width2);
|
|
51339
51941
|
}
|
|
51942
|
+
/**
|
|
51943
|
+
* [W7-C] task 已返回、任务仍在后台跑:true = 前台转后台(固定英文结果文本),false = 直接后台;
|
|
51944
|
+
* 其它情况 undefined。
|
|
51945
|
+
*/
|
|
51946
|
+
backgrounded() {
|
|
51947
|
+
const result = this.result;
|
|
51948
|
+
if (this.toolName !== "task" || this.state !== "done" || result === void 0) return void 0;
|
|
51949
|
+
const details = result.details;
|
|
51950
|
+
if (details?.status !== "running") return void 0;
|
|
51951
|
+
return /moved to the background/i.test(contentText3(result.content));
|
|
51952
|
+
}
|
|
51340
51953
|
/** 后台子 Agent:结果摘要下一行跟随状态 ` ↳ t2 explore · 完成 2m · 7 轮 …`。 */
|
|
51341
51954
|
followLine(width2) {
|
|
51342
51955
|
const sub = this.subagentState();
|
|
@@ -51429,6 +52042,7 @@ var init_tool_view = __esm({
|
|
|
51429
52042
|
}
|
|
51430
52043
|
return out;
|
|
51431
52044
|
}
|
|
52045
|
+
if (!this.expanded && this.backgrounded() !== void 0) return out;
|
|
51432
52046
|
const custom = this.customResult(width2);
|
|
51433
52047
|
if (custom !== void 0) return [...out, ...custom];
|
|
51434
52048
|
const diff = this.state === "done" ? diffOf(this.result) : void 0;
|
|
@@ -51808,7 +52422,7 @@ var init_approval_dialog = __esm({
|
|
|
51808
52422
|
}
|
|
51809
52423
|
ask(request, signal) {
|
|
51810
52424
|
if (signal.aborted) return Promise.resolve(void 0);
|
|
51811
|
-
return new Promise((
|
|
52425
|
+
return new Promise((resolve39) => {
|
|
51812
52426
|
let handle;
|
|
51813
52427
|
let settled = false;
|
|
51814
52428
|
const settle = (decision) => {
|
|
@@ -51819,7 +52433,7 @@ var init_approval_dialog = __esm({
|
|
|
51819
52433
|
this.open--;
|
|
51820
52434
|
this.host.onClose?.();
|
|
51821
52435
|
this.host.report?.(request, decision ?? "cancelled");
|
|
51822
|
-
|
|
52436
|
+
resolve39(decision);
|
|
51823
52437
|
};
|
|
51824
52438
|
const onAbort = () => settle(void 0);
|
|
51825
52439
|
const dialog = new ApprovalDialog(request, this.host, settle);
|
|
@@ -51874,6 +52488,10 @@ function backgroundJobText(event) {
|
|
|
51874
52488
|
return m.backgroundStopped(event.jobId, short2);
|
|
51875
52489
|
}
|
|
51876
52490
|
}
|
|
52491
|
+
function subagentBackgroundText(event, agent) {
|
|
52492
|
+
const m = msg().agents.background;
|
|
52493
|
+
return event.reason === "timeout" ? m.timeout(event.taskId, agent) : m.host(event.taskId, agent);
|
|
52494
|
+
}
|
|
51877
52495
|
var ImageBudgetNotices, LIMIT_WARNING;
|
|
51878
52496
|
var init_event_notices = __esm({
|
|
51879
52497
|
"src/modes/interactive/event-notices.ts"() {
|
|
@@ -52249,9 +52867,9 @@ ${bypassRiskLines().map((l) => ` ${l}
|
|
|
52249
52867
|
return ed.ask(bypassLineQuestion(), "n").then((answer) => answer === "y");
|
|
52250
52868
|
}, session.state.permissionMode === BYPASS_MODE);
|
|
52251
52869
|
runtime.approvals.setUiBroker({
|
|
52252
|
-
ask: (request, signal) => new Promise((
|
|
52253
|
-
if (signal.aborted) return
|
|
52254
|
-
signal.addEventListener("abort", () =>
|
|
52870
|
+
ask: (request, signal) => new Promise((resolve39) => {
|
|
52871
|
+
if (signal.aborted) return resolve39(void 0);
|
|
52872
|
+
signal.addEventListener("abort", () => resolve39(void 0), { once: true });
|
|
52255
52873
|
const preview = previewDisplayLines(request.preview).map((l) => ` ${l}
|
|
52256
52874
|
`);
|
|
52257
52875
|
const question = approvalQuestion(
|
|
@@ -52260,7 +52878,7 @@ ${bypassRiskLines().map((l) => ` ${l}
|
|
|
52260
52878
|
);
|
|
52261
52879
|
void ed.ask(`
|
|
52262
52880
|
${preview.join("")}${question}`, "n").then((answer) => {
|
|
52263
|
-
|
|
52881
|
+
resolve39(answer === "y" ? "allow" : answer === "a" ? "allow_session" : "deny");
|
|
52264
52882
|
if (!busy) ed.render();
|
|
52265
52883
|
});
|
|
52266
52884
|
})
|
|
@@ -52269,7 +52887,7 @@ ${preview.join("")}${question}`, "n").then((answer) => {
|
|
|
52269
52887
|
`));
|
|
52270
52888
|
let busy = false;
|
|
52271
52889
|
let lastInterrupt = 0;
|
|
52272
|
-
return new Promise((
|
|
52890
|
+
return new Promise((resolve39) => {
|
|
52273
52891
|
let finished = false;
|
|
52274
52892
|
const finish2 = (code) => {
|
|
52275
52893
|
if (finished) return;
|
|
@@ -52283,7 +52901,7 @@ ${preview.join("")}${question}`, "n").then((answer) => {
|
|
|
52283
52901
|
runtime.notifier.set(void 0);
|
|
52284
52902
|
void session.abort().catch(() => void 0).finally(() => {
|
|
52285
52903
|
unsubscribe();
|
|
52286
|
-
|
|
52904
|
+
resolve39(code);
|
|
52287
52905
|
});
|
|
52288
52906
|
};
|
|
52289
52907
|
const run7 = (text) => {
|
|
@@ -52315,6 +52933,10 @@ ${msg().interactive.line.ctrlCAgain}
|
|
|
52315
52933
|
continue;
|
|
52316
52934
|
}
|
|
52317
52935
|
if (busy) {
|
|
52936
|
+
if (/^\/tasks\s+bg(\s+\S+)?\s*$/.test(action.text.trim())) {
|
|
52937
|
+
void handle(action.text.trim());
|
|
52938
|
+
continue;
|
|
52939
|
+
}
|
|
52318
52940
|
if (action.text.trim() !== "") {
|
|
52319
52941
|
void session.steer(action.text).catch(() => void 0);
|
|
52320
52942
|
out(`${msg().interactive.line.steer(action.text)}
|
|
@@ -52342,7 +52964,7 @@ ${msg().interactive.line.ctrlCAgain}
|
|
|
52342
52964
|
});
|
|
52343
52965
|
}
|
|
52344
52966
|
function runPiped(stdin, context, handle, session, unsubscribe, failed4) {
|
|
52345
|
-
return new Promise((
|
|
52967
|
+
return new Promise((resolve39) => {
|
|
52346
52968
|
let chain = Promise.resolve(void 0);
|
|
52347
52969
|
let finished = false;
|
|
52348
52970
|
const finish2 = (code) => {
|
|
@@ -52352,7 +52974,7 @@ function runPiped(stdin, context, handle, session, unsubscribe, failed4) {
|
|
|
52352
52974
|
offSignals();
|
|
52353
52975
|
stdin.pause?.();
|
|
52354
52976
|
unsubscribe();
|
|
52355
|
-
|
|
52977
|
+
resolve39(code);
|
|
52356
52978
|
};
|
|
52357
52979
|
const enqueue = (line2) => {
|
|
52358
52980
|
chain = chain.then((state) => state === "exit" ? state : handle(line2));
|
|
@@ -52573,7 +53195,11 @@ var init_agent_bar = __esm({
|
|
|
52573
53195
|
const hidden = rows.length - shown2.length;
|
|
52574
53196
|
const tail = [];
|
|
52575
53197
|
if (hidden > 0) tail.push(m.bar.more(hidden));
|
|
52576
|
-
if (focused)
|
|
53198
|
+
if (focused) {
|
|
53199
|
+
const [up, down] = [t.glyphs.arrowUp, t.glyphs.arrowDown];
|
|
53200
|
+
const full = [...tail, m.bar.keysFull(up, down)].join(" · ");
|
|
53201
|
+
tail.push(visibleWidth(full) <= width2 ? m.bar.keysFull(up, down) : m.bar.keys(up, down));
|
|
53202
|
+
}
|
|
52577
53203
|
if (tail.length > 0)
|
|
52578
53204
|
out.push(truncateToWidth(t.fg("dim", tail.join(" · ")), width2, t.glyphs.ellipsis));
|
|
52579
53205
|
return out;
|
|
@@ -52584,7 +53210,9 @@ var init_agent_bar = __esm({
|
|
|
52584
53210
|
const agent = agentLabel(row3);
|
|
52585
53211
|
const lead = focused ? (selected ? t.fg("accent", g.prompt) : " ") + " " : "";
|
|
52586
53212
|
const marker = t.fg(statusColor(row3.status), g.tool);
|
|
52587
|
-
const
|
|
53213
|
+
const approval = row3.status === "approval";
|
|
53214
|
+
const plainId = selected || approval ? t.bold(row3.taskId) : row3.taskId;
|
|
53215
|
+
const id = approval ? t.fg("warning", plainId) : plainId;
|
|
52588
53216
|
const description = row3.description.replace(/\s+/g, " ").trim();
|
|
52589
53217
|
const text = `${lead}${marker} ${id} ${t.fg("tool", agent)}` + t.fg("dim", " · ") + t.fg(row3.status === "approval" ? "warning" : "muted", rowFacts(row3)) + (description === "" ? "" : ` ${t.fg("dim", description)}`);
|
|
52590
53218
|
return truncateToWidth(text, width2, g.ellipsis);
|
|
@@ -52782,6 +53410,7 @@ var init_agent_view = __esm({
|
|
|
52782
53410
|
init_session_report();
|
|
52783
53411
|
init_agent_bar();
|
|
52784
53412
|
init_agent_transcript();
|
|
53413
|
+
init_task_background();
|
|
52785
53414
|
AgentView = class {
|
|
52786
53415
|
constructor(taskId, deps) {
|
|
52787
53416
|
this.taskId = taskId;
|
|
@@ -52897,7 +53526,10 @@ var init_agent_view = __esm({
|
|
|
52897
53526
|
const taskId = this.taskId;
|
|
52898
53527
|
if (trimmed.startsWith("/")) {
|
|
52899
53528
|
const stop = /^\/tasks\s+stop(?:\s+(\S+))?\s*$/.exec(trimmed);
|
|
52900
|
-
|
|
53529
|
+
const bg = /^\/tasks\s+bg(?:\s+(\S+))?\s*$/.exec(trimmed);
|
|
53530
|
+
if (bg !== null && this.deps.background !== void 0)
|
|
53531
|
+
this.flash = backgroundedText2(this.deps.background(bg[1] ?? taskId));
|
|
53532
|
+
else if (stop === null) this.flash = m.commandsHere;
|
|
52901
53533
|
else {
|
|
52902
53534
|
const target = stop[1] ?? taskId;
|
|
52903
53535
|
try {
|
|
@@ -52926,6 +53558,13 @@ var init_agent_view = __esm({
|
|
|
52926
53558
|
const empty = this.editor.isEmpty();
|
|
52927
53559
|
const id = parseKey(data2)?.id;
|
|
52928
53560
|
this.flash = void 0;
|
|
53561
|
+
if (keys.matches(data2, "app.tasks.background") && this.deps.background !== void 0) {
|
|
53562
|
+
const moved = this.deps.background(this.taskId);
|
|
53563
|
+
if (moved.length > 0) {
|
|
53564
|
+
this.flash = backgroundedText2(moved);
|
|
53565
|
+
return;
|
|
53566
|
+
}
|
|
53567
|
+
}
|
|
52929
53568
|
if (keys.matches(data2, "tui.select.cancel") && !this.editor.isCompletionOpen) {
|
|
52930
53569
|
if (!empty) this.editor.clear();
|
|
52931
53570
|
else this.deps.close();
|
|
@@ -53364,7 +54003,7 @@ function mainOptions(ellipsis) {
|
|
|
53364
54003
|
return [m.optionApprove, m.optionApproveFresh, m.optionRevise(ellipsis), m.optionReject];
|
|
53365
54004
|
}
|
|
53366
54005
|
function openPlanDialog(host, input2) {
|
|
53367
|
-
return new Promise((
|
|
54006
|
+
return new Promise((resolve39) => {
|
|
53368
54007
|
let handle;
|
|
53369
54008
|
let settled = false;
|
|
53370
54009
|
const dialog = new PlanDialog(input2, host, (choice3) => {
|
|
@@ -53372,7 +54011,7 @@ function openPlanDialog(host, input2) {
|
|
|
53372
54011
|
settled = true;
|
|
53373
54012
|
handle?.hide();
|
|
53374
54013
|
host.onClose?.();
|
|
53375
|
-
|
|
54014
|
+
resolve39(choice3);
|
|
53376
54015
|
});
|
|
53377
54016
|
host.onOpen?.();
|
|
53378
54017
|
handle = host.showOverlay(
|
|
@@ -53579,10 +54218,10 @@ var init_plan_dialog = __esm({
|
|
|
53579
54218
|
if (hidden > 0) out.push(theme.fg("dim", m.moreSteps(theme.glyphs.ellipsis, hidden)));
|
|
53580
54219
|
return out;
|
|
53581
54220
|
}
|
|
53582
|
-
optionLines(
|
|
54221
|
+
optionLines(labels2, selected, width2) {
|
|
53583
54222
|
const { theme } = this.host;
|
|
53584
54223
|
const g = theme.glyphs;
|
|
53585
|
-
return
|
|
54224
|
+
return labels2.map((label2, i) => {
|
|
53586
54225
|
const on = i === selected;
|
|
53587
54226
|
const text = `${on ? g.prompt : " "} ${i + 1}. ${label2}`;
|
|
53588
54227
|
const line2 = padToWidth(
|
|
@@ -53754,6 +54393,7 @@ var init_agent_ui = __esm({
|
|
|
53754
54393
|
init_external_editor();
|
|
53755
54394
|
init_plan_flow();
|
|
53756
54395
|
init_subagent_view();
|
|
54396
|
+
init_task_background();
|
|
53757
54397
|
init_tasks_report();
|
|
53758
54398
|
TASK_NOTICE = /^\[task (t\d+)\] ([\s\S]*)$/;
|
|
53759
54399
|
AgentUi = class {
|
|
@@ -53796,7 +54436,7 @@ var init_agent_ui = __esm({
|
|
|
53796
54436
|
/** [W6-A] key-dispatch.ts 的 Agent 栏入口。 */
|
|
53797
54437
|
keys = {
|
|
53798
54438
|
handleKey: (data2) => this.barKey(data2),
|
|
53799
|
-
focus: (
|
|
54439
|
+
focus: () => this.focusFromKey()
|
|
53800
54440
|
};
|
|
53801
54441
|
view;
|
|
53802
54442
|
/** 等审批的请求 → 任务。 */
|
|
@@ -53804,6 +54444,10 @@ var init_agent_ui = __esm({
|
|
|
53804
54444
|
restoreLog;
|
|
53805
54445
|
/** 后台子 Agent 运行中:每秒重画跟随行的耗时(主会话空闲时 Loader 不转)。 */
|
|
53806
54446
|
ticker;
|
|
54447
|
+
/** [W7-C] 后台任务的审批停靠(approval-ui.ts 建好后接上)。 */
|
|
54448
|
+
dock;
|
|
54449
|
+
/** [W7-C] 栏内 `x` 的双击确认。 */
|
|
54450
|
+
stopArm = new StopArm();
|
|
53807
54451
|
keybindings() {
|
|
53808
54452
|
return this.deps.dialog.keybindings ?? defaultKeybindings;
|
|
53809
54453
|
}
|
|
@@ -53820,6 +54464,7 @@ var init_agent_ui = __esm({
|
|
|
53820
54464
|
if (viewing !== void 0) this.deps.notice("info", msg().agents.view.removed(viewing));
|
|
53821
54465
|
this.bar.reset();
|
|
53822
54466
|
this.approvals.clear();
|
|
54467
|
+
this.dock?.reset();
|
|
53823
54468
|
this.deps.subagents.clear();
|
|
53824
54469
|
this.stopTicker();
|
|
53825
54470
|
this.plan.attach(session);
|
|
@@ -53875,9 +54520,12 @@ var init_agent_ui = __esm({
|
|
|
53875
54520
|
switch (event.type) {
|
|
53876
54521
|
case "subagent_start":
|
|
53877
54522
|
case "subagent_update":
|
|
54523
|
+
case "subagent_background":
|
|
53878
54524
|
case "subagent_end": {
|
|
53879
54525
|
const state = this.deps.subagents.onEvent(event);
|
|
53880
54526
|
if (state === void 0) return true;
|
|
54527
|
+
if (event.type === "subagent_background" && event.reason !== "user")
|
|
54528
|
+
this.deps.notice("info", subagentBackgroundText(event, state.agent));
|
|
53881
54529
|
this.deps.tools().get(state.parentToolCallId)?.refresh();
|
|
53882
54530
|
if (event.type === "subagent_start" && this.view?.component.task === event.taskId)
|
|
53883
54531
|
this.view.component.attach();
|
|
@@ -53898,11 +54546,18 @@ var init_agent_ui = __esm({
|
|
|
53898
54546
|
case "permission_request": {
|
|
53899
54547
|
const taskId = event.context?.taskId;
|
|
53900
54548
|
if (taskId !== void 0) this.approvals.set(event.requestId, taskId);
|
|
54549
|
+
this.dock?.observe(event);
|
|
53901
54550
|
return false;
|
|
53902
54551
|
}
|
|
53903
54552
|
case "permission_resolved":
|
|
53904
54553
|
this.approvals.delete(event.requestId);
|
|
54554
|
+
this.dock?.observe(event);
|
|
54555
|
+
return false;
|
|
54556
|
+
case "agent_settled": {
|
|
54557
|
+
const dock = this.dock;
|
|
54558
|
+
if (dock !== void 0 && dock.size > 0) setTimeout(() => dock.poke(), 0);
|
|
53905
54559
|
return false;
|
|
54560
|
+
}
|
|
53906
54561
|
default:
|
|
53907
54562
|
return false;
|
|
53908
54563
|
}
|
|
@@ -53947,19 +54602,31 @@ var init_agent_ui = __esm({
|
|
|
53947
54602
|
}
|
|
53948
54603
|
this.deps.render();
|
|
53949
54604
|
}
|
|
53950
|
-
/**
|
|
53951
|
-
|
|
53952
|
-
|
|
53953
|
-
|
|
53954
|
-
|
|
54605
|
+
/**
|
|
54606
|
+
* `app.agents.focus`:输入为空且有任务即进栏(与 `/tasks` 一致,不要求栏可见)[W7-A];
|
|
54607
|
+
* 否则返回落空原因——有字(有任务时)、栏关闭(有任务时)、没有任务(栏开着时)。
|
|
54608
|
+
*/
|
|
54609
|
+
focusFromKey() {
|
|
54610
|
+
if (this.view !== void 0) return false;
|
|
54611
|
+
const hasTasks = this.bar.all().length > 0;
|
|
54612
|
+
if (!this.barEnabled()) return hasTasks && this.deps.editor.isEmpty() ? "disabled" : false;
|
|
54613
|
+
if (!this.deps.editor.isEmpty()) return hasTasks ? "busy-input" : false;
|
|
54614
|
+
if (!this.bar.focus()) return "empty";
|
|
53955
54615
|
this.deps.render();
|
|
53956
54616
|
return true;
|
|
53957
54617
|
}
|
|
54618
|
+
/** [W7-A] 运行提示行要不要带「↓ Agent 栏」:栏开着、有该显示的任务、没在栏里或视图里。 */
|
|
54619
|
+
get reachable() {
|
|
54620
|
+
return this.view === void 0 && !this.bar.focused && this.bar.visible;
|
|
54621
|
+
}
|
|
53958
54622
|
/** 栏聚焦时的按键;不在栏里返回 false。 */
|
|
53959
54623
|
barKey(data2) {
|
|
53960
54624
|
if (!this.bar.focused) return false;
|
|
53961
54625
|
const keys = this.keybindings();
|
|
53962
|
-
if (
|
|
54626
|
+
if (data2 !== "x") this.stopArm.reset();
|
|
54627
|
+
if (data2 === "b" || keys.matches(data2, "app.tasks.background")) this.backgroundSelected();
|
|
54628
|
+
else if (data2 === "x") void this.stopSelected();
|
|
54629
|
+
else if (keys.matches(data2, "tui.select.up")) {
|
|
53963
54630
|
if (!this.bar.move(-1)) this.bar.blur();
|
|
53964
54631
|
} else if (keys.matches(data2, "tui.select.down")) this.bar.move(1);
|
|
53965
54632
|
else if (keys.matches(data2, "tui.editor.submit")) {
|
|
@@ -53975,6 +54642,33 @@ var init_agent_ui = __esm({
|
|
|
53975
54642
|
this.deps.render();
|
|
53976
54643
|
return true;
|
|
53977
54644
|
}
|
|
54645
|
+
/** [W7-C] 栏内 `b` / `Ctrl+B`:转后台选中的任务(只对前台运行中的有效)。 */
|
|
54646
|
+
backgroundSelected() {
|
|
54647
|
+
const taskId = this.bar.selected();
|
|
54648
|
+
if (taskId === void 0) return;
|
|
54649
|
+
const moved = this.deps.session().backgroundTask(taskId, "user");
|
|
54650
|
+
this.deps.hint(
|
|
54651
|
+
moved.length > 0 ? backgroundedText2(moved) : msg().agents.background.notForeground(taskId)
|
|
54652
|
+
);
|
|
54653
|
+
}
|
|
54654
|
+
/** [W7-C] 栏内 `x`:第一次提示「再按 x 停止」,1.5 s 内再按停止。 */
|
|
54655
|
+
async stopSelected() {
|
|
54656
|
+
const taskId = this.bar.selected();
|
|
54657
|
+
if (taskId === void 0) return;
|
|
54658
|
+
const sessionId = this.deps.session().state.sessionId;
|
|
54659
|
+
if (taskRegistryView(sessionId)?.get(taskId)?.status !== "running") {
|
|
54660
|
+
this.stopArm.reset();
|
|
54661
|
+
this.deps.hint(msg().agents.stop.ended(taskId));
|
|
54662
|
+
return;
|
|
54663
|
+
}
|
|
54664
|
+
if (this.stopArm.press(taskId, this.deps.now()) === "arm") {
|
|
54665
|
+
this.deps.hint(msg().agents.stop.confirm(taskId));
|
|
54666
|
+
return;
|
|
54667
|
+
}
|
|
54668
|
+
this.deps.hint(msg().agents.view.stopped(taskId));
|
|
54669
|
+
await stopTask(sessionId, taskId);
|
|
54670
|
+
this.deps.render();
|
|
54671
|
+
}
|
|
53978
54672
|
/** `/tasks <id>` 与栏里 Enter:打开子 Agent 视图。 */
|
|
53979
54673
|
openView(taskId) {
|
|
53980
54674
|
const sessionId = this.deps.session().state.sessionId;
|
|
@@ -53996,6 +54690,7 @@ var init_agent_ui = __esm({
|
|
|
53996
54690
|
siblings: () => this.bar.all().map((row3) => row3.taskId),
|
|
53997
54691
|
close: () => this.closeView(),
|
|
53998
54692
|
stop: (id) => stopTask(this.deps.session().state.sessionId, id),
|
|
54693
|
+
background: (id) => this.deps.session().backgroundTask(id, "user"),
|
|
53999
54694
|
messages: {
|
|
54000
54695
|
...ui.showThinking !== void 0 ? { showThinking: ui.showThinking } : {},
|
|
54001
54696
|
...ui.markdown !== void 0 ? { markdown: ui.markdown } : {},
|
|
@@ -54005,6 +54700,7 @@ var init_agent_ui = __esm({
|
|
|
54005
54700
|
this.bar.blur();
|
|
54006
54701
|
const handle = this.deps.tui.showOverlay(component, { anchor: "bottom" });
|
|
54007
54702
|
this.view = { component, handle };
|
|
54703
|
+
this.dock?.poke();
|
|
54008
54704
|
this.deps.render();
|
|
54009
54705
|
}
|
|
54010
54706
|
get viewing() {
|
|
@@ -54080,6 +54776,169 @@ var init_agent_ui = __esm({
|
|
|
54080
54776
|
}
|
|
54081
54777
|
});
|
|
54082
54778
|
|
|
54779
|
+
// src/modes/interactive/approval-dock.ts
|
|
54780
|
+
var DOCK_POLL_MS, ApprovalDock;
|
|
54781
|
+
var init_approval_dock = __esm({
|
|
54782
|
+
"src/modes/interactive/approval-dock.ts"() {
|
|
54783
|
+
"use strict";
|
|
54784
|
+
DOCK_POLL_MS = 250;
|
|
54785
|
+
ApprovalDock = class {
|
|
54786
|
+
constructor(inner, host) {
|
|
54787
|
+
this.inner = inner;
|
|
54788
|
+
this.host = host;
|
|
54789
|
+
}
|
|
54790
|
+
inner;
|
|
54791
|
+
host;
|
|
54792
|
+
docked = [];
|
|
54793
|
+
/** 已发出、还没答复的不可停靠请求(主会话 / 前台任务)。 */
|
|
54794
|
+
others = /* @__PURE__ */ new Set();
|
|
54795
|
+
timer;
|
|
54796
|
+
ask(request, signal) {
|
|
54797
|
+
const taskId = request.context?.taskId;
|
|
54798
|
+
if (taskId === void 0 || signal.aborted || !this.host.dockable(taskId) || this.others.size > 0 || this.host.ready(taskId))
|
|
54799
|
+
return this.inner.ask(request, signal);
|
|
54800
|
+
return new Promise((resolve39) => {
|
|
54801
|
+
const entry = {
|
|
54802
|
+
taskId,
|
|
54803
|
+
request,
|
|
54804
|
+
signal,
|
|
54805
|
+
resolve: resolve39,
|
|
54806
|
+
onAbort: () => {
|
|
54807
|
+
this.remove(entry);
|
|
54808
|
+
resolve39(void 0);
|
|
54809
|
+
}
|
|
54810
|
+
};
|
|
54811
|
+
signal.addEventListener("abort", entry.onAbort, { once: true });
|
|
54812
|
+
this.docked.push(entry);
|
|
54813
|
+
this.startPolling();
|
|
54814
|
+
this.host.changed();
|
|
54815
|
+
});
|
|
54816
|
+
}
|
|
54817
|
+
/** 停靠中的任务。 */
|
|
54818
|
+
tasks() {
|
|
54819
|
+
return new Set(this.docked.map((entry) => entry.taskId));
|
|
54820
|
+
}
|
|
54821
|
+
get size() {
|
|
54822
|
+
return this.docked.length;
|
|
54823
|
+
}
|
|
54824
|
+
/** 会话事件:记下不可停靠的请求;停靠期间来了这种请求就放出停靠的(见文件头)。 */
|
|
54825
|
+
observe(event) {
|
|
54826
|
+
if (event.type === "permission_request") {
|
|
54827
|
+
const taskId = event.context?.taskId;
|
|
54828
|
+
if (taskId !== void 0 && this.host.dockable(taskId)) return;
|
|
54829
|
+
this.others.add(event.requestId);
|
|
54830
|
+
this.poke();
|
|
54831
|
+
} else if (event.type === "permission_resolved") this.others.delete(event.requestId);
|
|
54832
|
+
}
|
|
54833
|
+
/** 对一次弹出条件(定时器、视图打开、回合结束)。 */
|
|
54834
|
+
poke() {
|
|
54835
|
+
for (const entry of [...this.docked])
|
|
54836
|
+
if (this.others.size > 0 || this.host.ready(entry.taskId)) this.release(entry);
|
|
54837
|
+
}
|
|
54838
|
+
/** 换会话:旧会话的未答复请求不再有 `permission_resolved` 到这里。 */
|
|
54839
|
+
reset() {
|
|
54840
|
+
this.others.clear();
|
|
54841
|
+
}
|
|
54842
|
+
/** 退出:停靠的请求按 undefined 交回链(链按拒绝处理)。 */
|
|
54843
|
+
dispose() {
|
|
54844
|
+
for (const entry of [...this.docked]) entry.onAbort();
|
|
54845
|
+
this.others.clear();
|
|
54846
|
+
}
|
|
54847
|
+
release(entry) {
|
|
54848
|
+
this.remove(entry);
|
|
54849
|
+
entry.resolve(this.inner.ask(entry.request, entry.signal));
|
|
54850
|
+
}
|
|
54851
|
+
remove(entry) {
|
|
54852
|
+
const at = this.docked.indexOf(entry);
|
|
54853
|
+
if (at < 0) return;
|
|
54854
|
+
this.docked.splice(at, 1);
|
|
54855
|
+
entry.signal.removeEventListener("abort", entry.onAbort);
|
|
54856
|
+
if (this.docked.length === 0) this.stopPolling();
|
|
54857
|
+
this.host.changed();
|
|
54858
|
+
}
|
|
54859
|
+
startPolling() {
|
|
54860
|
+
if (this.timer !== void 0) return;
|
|
54861
|
+
this.timer = setInterval(() => this.poke(), this.host.pollMs ?? DOCK_POLL_MS);
|
|
54862
|
+
this.timer.unref?.();
|
|
54863
|
+
}
|
|
54864
|
+
stopPolling() {
|
|
54865
|
+
if (this.timer !== void 0) clearInterval(this.timer);
|
|
54866
|
+
this.timer = void 0;
|
|
54867
|
+
}
|
|
54868
|
+
};
|
|
54869
|
+
}
|
|
54870
|
+
});
|
|
54871
|
+
|
|
54872
|
+
// src/modes/interactive/approval-ui.ts
|
|
54873
|
+
function approvalOverlayHooks(deps) {
|
|
54874
|
+
const { tui, editor, indicator } = deps;
|
|
54875
|
+
return {
|
|
54876
|
+
showOverlay: (component) => tui.showOverlay(component, { anchor: "bottom" }),
|
|
54877
|
+
onOpen: () => {
|
|
54878
|
+
editor.disableSubmit = true;
|
|
54879
|
+
deps.tools().setAwaiting(true);
|
|
54880
|
+
indicator.setApproval(true);
|
|
54881
|
+
},
|
|
54882
|
+
onClose: () => {
|
|
54883
|
+
editor.disableSubmit = false;
|
|
54884
|
+
deps.tools().setAwaiting(false);
|
|
54885
|
+
indicator.setApproval(false);
|
|
54886
|
+
}
|
|
54887
|
+
};
|
|
54888
|
+
}
|
|
54889
|
+
function createApprovalUi(deps) {
|
|
54890
|
+
const { theme, keys, tui, editor, indicator, agentUi, hooks, notice } = deps;
|
|
54891
|
+
const taskInfo = (taskId) => taskRegistryView(deps.session().state.sessionId)?.get(taskId);
|
|
54892
|
+
const taskAgent = (taskId) => taskInfo(taskId)?.agent;
|
|
54893
|
+
const dialog = new ApprovalDialogBroker({
|
|
54894
|
+
theme,
|
|
54895
|
+
keybindings: keys,
|
|
54896
|
+
cwd: deps.session().state.cwd,
|
|
54897
|
+
permissionMode: () => deps.session().state.permissionMode,
|
|
54898
|
+
taskAgent,
|
|
54899
|
+
externalRunner: (agent) => agentUi.merge.externalRunner(agent),
|
|
54900
|
+
...hooks,
|
|
54901
|
+
report: (request, outcome) => {
|
|
54902
|
+
if (outcome === "deny" || outcome === "cancelled") {
|
|
54903
|
+
const text = approvalOutcomeText(request, outcome, taskAgent);
|
|
54904
|
+
notice(outcome === "deny" ? "info" : "warn", text);
|
|
54905
|
+
}
|
|
54906
|
+
}
|
|
54907
|
+
});
|
|
54908
|
+
const dock = new ApprovalDock(dialog, {
|
|
54909
|
+
dockable: (taskId) => {
|
|
54910
|
+
const info2 = taskInfo(taskId);
|
|
54911
|
+
return info2?.status === "running" && info2.background === true;
|
|
54912
|
+
},
|
|
54913
|
+
ready: (taskId) => agentUi.viewing === taskId || !tui.hasOverlay && !indicator.busy && editor.isEmpty(),
|
|
54914
|
+
changed: () => {
|
|
54915
|
+
indicator.sync();
|
|
54916
|
+
deps.render();
|
|
54917
|
+
}
|
|
54918
|
+
});
|
|
54919
|
+
agentUi.dock = dock;
|
|
54920
|
+
indicator.docked = () => dock.size > 0;
|
|
54921
|
+
const broker = mergingBroker(
|
|
54922
|
+
dock,
|
|
54923
|
+
agentUi.merge,
|
|
54924
|
+
(request) => notice(
|
|
54925
|
+
"info",
|
|
54926
|
+
msg().interactive.app.followed(approvalOutcomeText(request, "allow", taskAgent))
|
|
54927
|
+
)
|
|
54928
|
+
);
|
|
54929
|
+
return { broker, dock };
|
|
54930
|
+
}
|
|
54931
|
+
var init_approval_ui = __esm({
|
|
54932
|
+
"src/modes/interactive/approval-ui.ts"() {
|
|
54933
|
+
"use strict";
|
|
54934
|
+
init_subagent_registry();
|
|
54935
|
+
init_i18n();
|
|
54936
|
+
init_approval_dialog();
|
|
54937
|
+
init_approval_dock();
|
|
54938
|
+
init_approval_merge();
|
|
54939
|
+
}
|
|
54940
|
+
});
|
|
54941
|
+
|
|
54083
54942
|
// src/modes/interactive/commands.ts
|
|
54084
54943
|
function command2(name, key) {
|
|
54085
54944
|
return {
|
|
@@ -54355,7 +55214,7 @@ var init_commands2 = __esm({
|
|
|
54355
55214
|
await ui.agentBar();
|
|
54356
55215
|
return true;
|
|
54357
55216
|
}
|
|
54358
|
-
if (parts.length === 1 && parts[0] !== "stop" && ui.agentView !== void 0) {
|
|
55217
|
+
if (parts.length === 1 && parts[0] !== "stop" && parts[0] !== "bg" && ui.agentView !== void 0) {
|
|
54359
55218
|
await ui.agentView(parts[0]);
|
|
54360
55219
|
return true;
|
|
54361
55220
|
}
|
|
@@ -54552,6 +55411,28 @@ function parseNumstat(text) {
|
|
|
54552
55411
|
}
|
|
54553
55412
|
return { insertions, deletions };
|
|
54554
55413
|
}
|
|
55414
|
+
function parseLeftRight(text) {
|
|
55415
|
+
const match = /^\s*(\d+)\s+(\d+)\s*$/.exec(text);
|
|
55416
|
+
return match === null ? void 0 : { behind: Number(match[1]), ahead: Number(match[2]) };
|
|
55417
|
+
}
|
|
55418
|
+
async function hasUpstream(cwd, branch) {
|
|
55419
|
+
const gitDir = await findGitDir(cwd);
|
|
55420
|
+
if (gitDir === void 0) return false;
|
|
55421
|
+
const common = (await (0, import_promises24.readFile)((0, import_node_path94.join)(gitDir, "commondir"), "utf8").catch(() => void 0))?.trim();
|
|
55422
|
+
const dir = common === void 0 ? gitDir : (0, import_node_path94.isAbsolute)(common) ? common : (0, import_node_path94.resolve)(gitDir, common);
|
|
55423
|
+
const text = await (0, import_promises24.readFile)((0, import_node_path94.join)(dir, "config"), "utf8").catch(() => "");
|
|
55424
|
+
let inBranch = false;
|
|
55425
|
+
for (const raw of text.split("\n")) {
|
|
55426
|
+
const line2 = raw.trim();
|
|
55427
|
+
const section = /^\[\s*([^\]\s"]+)(?:\s+"((?:[^"\\]|\\.)*)")?\s*\]/.exec(line2);
|
|
55428
|
+
if (section !== null) {
|
|
55429
|
+
inBranch = section[1]?.toLowerCase() === "branch" && section[2] === branch;
|
|
55430
|
+
continue;
|
|
55431
|
+
}
|
|
55432
|
+
if (inBranch && /^merge\s*=\s*\S/i.test(line2)) return true;
|
|
55433
|
+
}
|
|
55434
|
+
return false;
|
|
55435
|
+
}
|
|
54555
55436
|
async function readHead2(cwd) {
|
|
54556
55437
|
const head = await readGitHead(cwd);
|
|
54557
55438
|
if (head !== void 0) {
|
|
@@ -54576,7 +55457,7 @@ var init_info = __esm({
|
|
|
54576
55457
|
init_git_head();
|
|
54577
55458
|
GIT_NUMSTAT_INTERVAL_MS = 1e4;
|
|
54578
55459
|
GIT_NUMSTAT_TIMEOUT_MS = 2e3;
|
|
54579
|
-
sameInfo = (a, b) => a?.branch === b?.branch && a?.shortHead === b?.shortHead && a?.insertions === b?.insertions && a?.deletions === b?.deletions && a === void 0 === (b === void 0);
|
|
55460
|
+
sameInfo = (a, b) => a?.branch === b?.branch && a?.shortHead === b?.shortHead && a?.insertions === b?.insertions && a?.deletions === b?.deletions && a?.ahead === b?.ahead && a?.behind === b?.behind && a === void 0 === (b === void 0);
|
|
54580
55461
|
GitInfoWatcher = class {
|
|
54581
55462
|
constructor(cwd, deps = {}) {
|
|
54582
55463
|
this.cwd = cwd;
|
|
@@ -54586,6 +55467,7 @@ var init_info = __esm({
|
|
|
54586
55467
|
this.timeoutMs = deps.timeoutMs ?? GIT_NUMSTAT_TIMEOUT_MS;
|
|
54587
55468
|
this.env = deps.env ?? process.env;
|
|
54588
55469
|
this.numstatDisabled = this.env["AMA_STATUS_GIT"] === "0";
|
|
55470
|
+
this.upstreamDisabled = this.numstatDisabled;
|
|
54589
55471
|
}
|
|
54590
55472
|
cwd;
|
|
54591
55473
|
info;
|
|
@@ -54602,6 +55484,8 @@ var init_info = __esm({
|
|
|
54602
55484
|
headAgain = false;
|
|
54603
55485
|
disposed = false;
|
|
54604
55486
|
diff;
|
|
55487
|
+
upstream;
|
|
55488
|
+
upstreamDisabled;
|
|
54605
55489
|
current() {
|
|
54606
55490
|
return this.info;
|
|
54607
55491
|
}
|
|
@@ -54639,7 +55523,8 @@ var init_info = __esm({
|
|
|
54639
55523
|
update(head) {
|
|
54640
55524
|
const next = head === void 0 ? void 0 : {
|
|
54641
55525
|
...head,
|
|
54642
|
-
...this.diff !== void 0 && head.shortHead !== void 0 ? this.diff : {}
|
|
55526
|
+
...this.diff !== void 0 && head.shortHead !== void 0 ? this.diff : {},
|
|
55527
|
+
...this.upstream !== void 0 && head.branch !== void 0 ? this.upstream : {}
|
|
54643
55528
|
};
|
|
54644
55529
|
if (sameInfo(this.info, next)) return;
|
|
54645
55530
|
this.info = next;
|
|
@@ -54652,42 +55537,60 @@ var init_info = __esm({
|
|
|
54652
55537
|
if (at - this.lastNumstatAt < this.minIntervalMs) return Promise.resolve();
|
|
54653
55538
|
this.lastNumstatAt = at;
|
|
54654
55539
|
this.numstatRunning = true;
|
|
54655
|
-
return this.numstat().then((diff) => {
|
|
54656
|
-
this.numstatRunning = false;
|
|
55540
|
+
return this.numstat().then(async (diff) => {
|
|
54657
55541
|
if (this.disposed) return;
|
|
54658
55542
|
if (diff === void 0) {
|
|
54659
55543
|
this.numstatDisabled = true;
|
|
54660
55544
|
this.diff = void 0;
|
|
54661
55545
|
} else this.diff = diff;
|
|
55546
|
+
await this.leftRight();
|
|
55547
|
+
this.numstatRunning = false;
|
|
55548
|
+
if (this.disposed) return;
|
|
54662
55549
|
const info2 = this.info;
|
|
54663
55550
|
if (info2 === void 0) return;
|
|
54664
|
-
const { insertions: _i, deletions: _d, ...head } = info2;
|
|
55551
|
+
const { insertions: _i, deletions: _d, ahead: _a, behind: _b, ...head } = info2;
|
|
54665
55552
|
this.update(head);
|
|
54666
55553
|
});
|
|
54667
55554
|
}
|
|
54668
|
-
|
|
54669
|
-
|
|
55555
|
+
/** 领先 / 落后上游:只在配置里有上游时起进程;超时本会话停用,非零退出只省略这一次。 */
|
|
55556
|
+
async leftRight() {
|
|
55557
|
+
const branch = this.info?.branch;
|
|
55558
|
+
if (this.upstreamDisabled || branch === void 0 || !await hasUpstream(this.cwd, branch)) {
|
|
55559
|
+
this.upstream = void 0;
|
|
55560
|
+
return;
|
|
55561
|
+
}
|
|
55562
|
+
const result = await this.run(["rev-list", "--left-right", "--count", "@{upstream}...HEAD"]);
|
|
55563
|
+
if (result === "timeout") this.upstreamDisabled = true;
|
|
55564
|
+
this.upstream = typeof result === "object" && result.code === 0 ? parseLeftRight(result.out) : void 0;
|
|
55565
|
+
}
|
|
55566
|
+
async numstat() {
|
|
55567
|
+
const result = await this.run(["diff", "--numstat", "HEAD"]);
|
|
55568
|
+
return typeof result === "object" && result.code === 0 ? parseNumstat(result.out) : void 0;
|
|
55569
|
+
}
|
|
55570
|
+
/** 后台起一次 git;起不来为 undefined,超时杀掉并返回 `"timeout"`。 */
|
|
55571
|
+
run(args) {
|
|
55572
|
+
return new Promise((resolve39) => {
|
|
54670
55573
|
let settled = false;
|
|
54671
55574
|
let timer;
|
|
54672
55575
|
const done = (value) => {
|
|
54673
55576
|
if (settled) return;
|
|
54674
55577
|
settled = true;
|
|
54675
55578
|
clearTimeout(timer);
|
|
54676
|
-
|
|
55579
|
+
resolve39(value);
|
|
54677
55580
|
};
|
|
54678
55581
|
let child;
|
|
54679
55582
|
try {
|
|
54680
|
-
child = this.spawn("git",
|
|
55583
|
+
child = this.spawn("git", args, {
|
|
54681
55584
|
cwd: this.cwd,
|
|
54682
55585
|
env: { ...this.env, GIT_OPTIONAL_LOCKS: "0" }
|
|
54683
55586
|
});
|
|
54684
55587
|
} catch {
|
|
54685
|
-
|
|
55588
|
+
resolve39(void 0);
|
|
54686
55589
|
return;
|
|
54687
55590
|
}
|
|
54688
55591
|
timer = setTimeout(() => {
|
|
54689
55592
|
child.kill("SIGKILL");
|
|
54690
|
-
done(
|
|
55593
|
+
done("timeout");
|
|
54691
55594
|
}, this.timeoutMs);
|
|
54692
55595
|
timer.unref?.();
|
|
54693
55596
|
let out = "";
|
|
@@ -54696,7 +55599,7 @@ var init_info = __esm({
|
|
|
54696
55599
|
out += String(chunk);
|
|
54697
55600
|
});
|
|
54698
55601
|
child.on("error", () => done(void 0));
|
|
54699
|
-
child.on("close", (code) => done(code
|
|
55602
|
+
child.on("close", (code) => done({ code, out }));
|
|
54700
55603
|
});
|
|
54701
55604
|
}
|
|
54702
55605
|
};
|
|
@@ -54755,32 +55658,40 @@ var init_status_line = __esm({
|
|
|
54755
55658
|
const right = (text, priority) => {
|
|
54756
55659
|
if (text !== void 0) parts.push({ text, priority, zone: "right" });
|
|
54757
55660
|
};
|
|
55661
|
+
const blue = (text) => theme.fg("accent", text);
|
|
55662
|
+
const purple = (text) => theme.fg("tool", text);
|
|
55663
|
+
const amountText = (tokens, ms) => `${blue(formatTokens3(tokens))}${dim(" tok / ")}${blue(formatSeconds2(ms))}`;
|
|
54758
55664
|
let tps;
|
|
54759
55665
|
let amount;
|
|
54760
55666
|
if (live2 !== void 0) {
|
|
54761
55667
|
tps = live2.tps;
|
|
54762
|
-
amount =
|
|
55668
|
+
amount = amountText(live2.outputTokens, live2.elapsedMs);
|
|
54763
55669
|
} else if (last?.doneAt !== void 0) {
|
|
54764
55670
|
tps = last.tps;
|
|
54765
55671
|
if (last.outputTokens !== void 0 && last.firstTokenAt !== void 0) {
|
|
54766
|
-
amount =
|
|
55672
|
+
amount = amountText(last.outputTokens, last.doneAt - last.firstTokenAt);
|
|
54767
55673
|
}
|
|
54768
55674
|
}
|
|
54769
55675
|
const label2 = live2 !== void 0 ? theme.fg("accent", "tps:") : dim("tps:");
|
|
54770
55676
|
left(
|
|
54771
|
-
`${label2} ${
|
|
55677
|
+
`${label2} ${tps === void 0 ? dim("—") : `${purple(formatRate(tps))}${dim(" tok/s")}`}`,
|
|
54772
55678
|
void 0,
|
|
54773
55679
|
RESERVE.tps
|
|
54774
55680
|
);
|
|
54775
55681
|
if (amount !== void 0) {
|
|
54776
|
-
left(
|
|
55682
|
+
left(amount, PRIORITY.amount, RESERVE.amount, { lead: ` ${theme.glyphs.dot} ` });
|
|
54777
55683
|
}
|
|
54778
55684
|
const stat16 = { group: "stats", lead: " " };
|
|
54779
55685
|
if (telemetry?.avgTps !== void 0) {
|
|
54780
|
-
left(dim(
|
|
55686
|
+
left(`${dim("avg ")}${blue(formatRate(telemetry.avgTps))}`, PRIORITY.avg, RESERVE.avg, stat16);
|
|
54781
55687
|
}
|
|
54782
55688
|
if (last?.ttftMs !== void 0) {
|
|
54783
|
-
left(
|
|
55689
|
+
left(
|
|
55690
|
+
`${dim("ttft ")}${purple(formatSeconds2(last.ttftMs))}`,
|
|
55691
|
+
PRIORITY.ttft,
|
|
55692
|
+
RESERVE.ttft,
|
|
55693
|
+
stat16
|
|
55694
|
+
);
|
|
54784
55695
|
}
|
|
54785
55696
|
const usage = usageItems(stats, this.bar.queued(), this.source, theme);
|
|
54786
55697
|
right(usage.tokens, PRIORITY.tokens);
|
|
@@ -54822,7 +55733,7 @@ function statusLineText(mode) {
|
|
|
54822
55733
|
const m = msg().interactive.statusLine;
|
|
54823
55734
|
return mode === "full" ? m.full : m.compact;
|
|
54824
55735
|
}
|
|
54825
|
-
var import_node_path95, WRITE_TOOLS3, HintLine, StatusArea;
|
|
55736
|
+
var import_node_path95, WRITE_TOOLS3, QUOTA_TICK_MS, HintLine, StatusArea;
|
|
54826
55737
|
var init_status_area = __esm({
|
|
54827
55738
|
"src/modes/interactive/status-area.ts"() {
|
|
54828
55739
|
"use strict";
|
|
@@ -54837,7 +55748,9 @@ var init_status_area = __esm({
|
|
|
54837
55748
|
init_tui2();
|
|
54838
55749
|
init_status_bar();
|
|
54839
55750
|
init_status_line();
|
|
55751
|
+
init_status_quota();
|
|
54840
55752
|
WRITE_TOOLS3 = /* @__PURE__ */ new Set(["write", "edit", "bash", "task"]);
|
|
55753
|
+
QUOTA_TICK_MS = 6e4;
|
|
54841
55754
|
HintLine = class {
|
|
54842
55755
|
text = "";
|
|
54843
55756
|
setText(text) {
|
|
@@ -54874,16 +55787,26 @@ var init_status_area = __esm({
|
|
|
54874
55787
|
// S2:bash 沙箱生效(配置 + 本机能力,与 compose 同一结论)且 bash 工具活动
|
|
54875
55788
|
bashSandbox: () => (this.bashSandbox ??= resolveBashSandbox(runtime.config.sandbox, {
|
|
54876
55789
|
status: osSandboxStatus()
|
|
54877
|
-
}).active) && deps.session().getTools().some((tool) => tool.name === "bash")
|
|
55790
|
+
}).active) && deps.session().getTools().some((tool) => tool.name === "bash"),
|
|
55791
|
+
quota: () => this.quotaView()
|
|
54878
55792
|
};
|
|
54879
55793
|
this.bar = new StatusBar(source, deps.theme);
|
|
54880
55794
|
this.rate = new StatusLine(this.bar, source, deps.theme);
|
|
55795
|
+
this.quota = new QuotaLine(
|
|
55796
|
+
{ layout: () => this.mode, quota: () => this.quotaView(), now: () => deps.now() },
|
|
55797
|
+
deps.theme
|
|
55798
|
+
);
|
|
54881
55799
|
this.watchGit();
|
|
55800
|
+
this.syncTicker();
|
|
54882
55801
|
}
|
|
54883
55802
|
deps;
|
|
54884
55803
|
hint = new HintLine();
|
|
54885
55804
|
bar;
|
|
54886
55805
|
rate;
|
|
55806
|
+
/** [W6] 订阅配额行(full 第三行)。 */
|
|
55807
|
+
quota;
|
|
55808
|
+
lastQuota;
|
|
55809
|
+
ticker;
|
|
54887
55810
|
mode;
|
|
54888
55811
|
startedAt;
|
|
54889
55812
|
git;
|
|
@@ -54893,6 +55816,38 @@ var init_status_area = __esm({
|
|
|
54893
55816
|
/** [W5-U] 模型回退中(`model_fallback` 到切回主模型)。 */
|
|
54894
55817
|
fallback;
|
|
54895
55818
|
bashSandbox;
|
|
55819
|
+
/** [W6] 当前模型走 ChatGPT 订阅时的配额;codex 还没数据为 pending,SIWC 没数据或非订阅模型不显示。 */
|
|
55820
|
+
quotaView() {
|
|
55821
|
+
const model = this.deps.session().state.model;
|
|
55822
|
+
if (model === void 0) return void 0;
|
|
55823
|
+
const backend = this.backendOf(formatModelRef(model));
|
|
55824
|
+
if (backend === void 0) return void 0;
|
|
55825
|
+
const quota = this.lastQuota ?? this.deps.session().getStats().subscription?.quota;
|
|
55826
|
+
if (quota !== void 0 && quota.provider === model.provider) return { quota };
|
|
55827
|
+
return backend === "codex" ? "pending" : void 0;
|
|
55828
|
+
}
|
|
55829
|
+
backendMemo;
|
|
55830
|
+
/** 模型的 ChatGPT 订阅后端(渠道 compat `chatgptBackend`);按引用记住上次结果。 */
|
|
55831
|
+
backendOf(ref) {
|
|
55832
|
+
if (this.backendMemo?.ref === ref) return this.backendMemo.backend;
|
|
55833
|
+
const found = this.deps.runtime.providers.findModel(ref);
|
|
55834
|
+
const value = found.ok ? found.model.compat?.chatgptBackend : void 0;
|
|
55835
|
+
const backend = value === "codex" || value === "siwc" ? value : void 0;
|
|
55836
|
+
this.backendMemo = { ref, backend };
|
|
55837
|
+
return backend;
|
|
55838
|
+
}
|
|
55839
|
+
/** 第三行显示且有重置时间时每分钟重画;否则不挂计时器。 */
|
|
55840
|
+
syncTicker() {
|
|
55841
|
+
const view = this.mode === "full" ? this.quotaView() : void 0;
|
|
55842
|
+
const ticking = typeof view === "object" && (view.quota.primary?.resetsAt !== void 0 || view.quota.secondary?.resetsAt !== void 0);
|
|
55843
|
+
if (ticking && this.ticker === void 0) {
|
|
55844
|
+
this.ticker = setInterval(() => this.deps.render(), QUOTA_TICK_MS);
|
|
55845
|
+
this.ticker.unref?.();
|
|
55846
|
+
} else if (!ticking && this.ticker !== void 0) {
|
|
55847
|
+
clearInterval(this.ticker);
|
|
55848
|
+
this.ticker = void 0;
|
|
55849
|
+
}
|
|
55850
|
+
}
|
|
54896
55851
|
layout() {
|
|
54897
55852
|
return this.mode;
|
|
54898
55853
|
}
|
|
@@ -54903,6 +55858,7 @@ var init_status_area = __esm({
|
|
|
54903
55858
|
setLayout(mode) {
|
|
54904
55859
|
if (mode === this.mode) return;
|
|
54905
55860
|
this.mode = mode;
|
|
55861
|
+
this.syncTicker();
|
|
54906
55862
|
(this.deps.redraw ?? this.deps.render)();
|
|
54907
55863
|
}
|
|
54908
55864
|
toggle() {
|
|
@@ -54918,6 +55874,7 @@ var init_status_area = __esm({
|
|
|
54918
55874
|
this.fallback = void 0;
|
|
54919
55875
|
this.watchGit();
|
|
54920
55876
|
this.bar.refresh();
|
|
55877
|
+
this.syncTicker();
|
|
54921
55878
|
}
|
|
54922
55879
|
refreshGit() {
|
|
54923
55880
|
void this.git?.refresh();
|
|
@@ -54928,6 +55885,10 @@ var init_status_area = __esm({
|
|
|
54928
55885
|
case "telemetry_tick":
|
|
54929
55886
|
this.bar.refresh();
|
|
54930
55887
|
return true;
|
|
55888
|
+
case "quota_update":
|
|
55889
|
+
this.lastQuota = event;
|
|
55890
|
+
this.syncTicker();
|
|
55891
|
+
return true;
|
|
54931
55892
|
case "agent_settled":
|
|
54932
55893
|
case "session_rewound":
|
|
54933
55894
|
this.refreshGit();
|
|
@@ -54947,6 +55908,7 @@ var init_status_area = __esm({
|
|
|
54947
55908
|
if (this.fallback !== void 0 && model !== void 0) {
|
|
54948
55909
|
if (formatModelRef(model) === this.fallback.from) this.fallback = void 0;
|
|
54949
55910
|
}
|
|
55911
|
+
this.syncTicker();
|
|
54950
55912
|
return false;
|
|
54951
55913
|
}
|
|
54952
55914
|
default:
|
|
@@ -54954,6 +55916,11 @@ var init_status_area = __esm({
|
|
|
54954
55916
|
}
|
|
54955
55917
|
}
|
|
54956
55918
|
dispose() {
|
|
55919
|
+
this.disposeGit();
|
|
55920
|
+
if (this.ticker !== void 0) clearInterval(this.ticker);
|
|
55921
|
+
this.ticker = void 0;
|
|
55922
|
+
}
|
|
55923
|
+
disposeGit() {
|
|
54957
55924
|
this.offGit();
|
|
54958
55925
|
this.git?.dispose();
|
|
54959
55926
|
this.git = void 0;
|
|
@@ -54966,7 +55933,7 @@ var init_status_area = __esm({
|
|
|
54966
55933
|
watchGit() {
|
|
54967
55934
|
const cwd = this.deps.session().state.cwd;
|
|
54968
55935
|
if (cwd === this.gitCwd && this.git !== void 0) return;
|
|
54969
|
-
this.
|
|
55936
|
+
this.disposeGit();
|
|
54970
55937
|
this.gitCwd = cwd;
|
|
54971
55938
|
const git = new GitInfoWatcher(cwd, this.deps.env !== void 0 ? { env: this.deps.env } : {});
|
|
54972
55939
|
this.git = git;
|
|
@@ -54982,6 +55949,8 @@ function createKeyDispatch(deps) {
|
|
|
54982
55949
|
const { keys, editor, tools, status } = deps;
|
|
54983
55950
|
let ctrlCArmedAt = Number.NEGATIVE_INFINITY;
|
|
54984
55951
|
const esc = new DoubleEscape(deps.doubleEscMs);
|
|
55952
|
+
let busyInputHinted = false;
|
|
55953
|
+
let focusHintShown = false;
|
|
54985
55954
|
const doubleEscape = () => {
|
|
54986
55955
|
switch (esc.press(deps.now(), editor.isEmpty())) {
|
|
54987
55956
|
case "arm-rewind":
|
|
@@ -55039,8 +56008,32 @@ ${current3}`);
|
|
|
55039
56008
|
if (typeof answer === "boolean") settle(answer);
|
|
55040
56009
|
else void answer.then(settle);
|
|
55041
56010
|
};
|
|
56011
|
+
const atLastLine = () => editor.cursor.line >= editor.getText().split("\n").length - 1;
|
|
56012
|
+
const focusAgents = (agents, data2) => {
|
|
56013
|
+
if (editor.isCompletionOpen || editor.isBrowsingHistory) return false;
|
|
56014
|
+
const result = agents.focus(data2);
|
|
56015
|
+
if (result === true) {
|
|
56016
|
+
if (focusHintShown) deps.showHint("");
|
|
56017
|
+
focusHintShown = false;
|
|
56018
|
+
return true;
|
|
56019
|
+
}
|
|
56020
|
+
const m = msg().agents;
|
|
56021
|
+
let text;
|
|
56022
|
+
if (result === "busy-input") {
|
|
56023
|
+
if (busyInputHinted || !atLastLine()) return false;
|
|
56024
|
+
busyInputHinted = true;
|
|
56025
|
+
text = m.focus.busyInput(deps.downGlyph ?? "↓");
|
|
56026
|
+
} else if (result === "disabled") text = m.focus.disabled;
|
|
56027
|
+
else if (result === "empty") text = m.bar.empty;
|
|
56028
|
+
if (text !== void 0) {
|
|
56029
|
+
deps.showHint(text, FOCUS_HINT_MS);
|
|
56030
|
+
focusHintShown = true;
|
|
56031
|
+
}
|
|
56032
|
+
return false;
|
|
56033
|
+
};
|
|
55042
56034
|
return (data2) => {
|
|
55043
56035
|
if (deps.inactive()) return false;
|
|
56036
|
+
if (editor.isEmpty()) busyInputHinted = false;
|
|
55044
56037
|
const is = (action) => keys.matches(data2, action);
|
|
55045
56038
|
if (!is("app.rewind")) esc.reset();
|
|
55046
56039
|
const agents = deps.agents?.();
|
|
@@ -55048,8 +56041,15 @@ ${current3}`);
|
|
|
55048
56041
|
esc.reset();
|
|
55049
56042
|
return true;
|
|
55050
56043
|
}
|
|
55051
|
-
if (agents !== void 0 && is("app.agents.focus") &&
|
|
55052
|
-
|
|
56044
|
+
if (agents !== void 0 && is("app.agents.focus") && focusAgents(agents, data2)) return true;
|
|
56045
|
+
if (is("app.tasks.background") && deps.backgroundTasks !== void 0) {
|
|
56046
|
+
const moved = deps.backgroundTasks();
|
|
56047
|
+
if (moved.length > 0) {
|
|
56048
|
+
esc.reset();
|
|
56049
|
+
deps.showHint(backgroundedText2(moved), FOCUS_HINT_MS);
|
|
56050
|
+
return true;
|
|
56051
|
+
}
|
|
56052
|
+
}
|
|
55053
56053
|
if (is("app.clear")) {
|
|
55054
56054
|
if (!editor.isEmpty()) {
|
|
55055
56055
|
editor.clear();
|
|
@@ -55067,7 +56067,10 @@ ${current3}`);
|
|
|
55067
56067
|
if (is("app.interrupt") && !editor.isCompletionOpen && deps.busy()) {
|
|
55068
56068
|
esc.reset();
|
|
55069
56069
|
interrupt();
|
|
55070
|
-
deps.
|
|
56070
|
+
const left = deps.runningBackground?.() ?? [];
|
|
56071
|
+
deps.showHint(
|
|
56072
|
+
left.length > 0 ? msg().agents.background.interrupted(left.join(", ")) : msg().interactive.keys.interrupted
|
|
56073
|
+
);
|
|
55071
56074
|
deps.onInterrupted?.(editor.isEmpty());
|
|
55072
56075
|
return true;
|
|
55073
56076
|
}
|
|
@@ -55120,7 +56123,7 @@ ${current3}`);
|
|
|
55120
56123
|
return false;
|
|
55121
56124
|
};
|
|
55122
56125
|
}
|
|
55123
|
-
var DOUBLE_CTRL_C_MS;
|
|
56126
|
+
var DOUBLE_CTRL_C_MS, FOCUS_HINT_MS;
|
|
55124
56127
|
var init_key_dispatch = __esm({
|
|
55125
56128
|
"src/modes/interactive/key-dispatch.ts"() {
|
|
55126
56129
|
"use strict";
|
|
@@ -55128,19 +56131,21 @@ var init_key_dispatch = __esm({
|
|
|
55128
56131
|
init_exit_codes();
|
|
55129
56132
|
init_modes();
|
|
55130
56133
|
init_double_esc();
|
|
56134
|
+
init_task_background();
|
|
55131
56135
|
init_status_area();
|
|
55132
56136
|
DOUBLE_CTRL_C_MS = 1500;
|
|
56137
|
+
FOCUS_HINT_MS = 3e3;
|
|
55133
56138
|
}
|
|
55134
56139
|
});
|
|
55135
56140
|
|
|
55136
56141
|
// src/modes/interactive/model-picker.ts
|
|
55137
56142
|
async function openModelPicker(host, options) {
|
|
55138
56143
|
const catalog = await loadModelCatalog(options.providers);
|
|
55139
|
-
return new Promise((
|
|
56144
|
+
return new Promise((resolve39) => {
|
|
55140
56145
|
let handle;
|
|
55141
56146
|
const view = new ModelPickerView(host, catalog, options, (ref) => {
|
|
55142
56147
|
handle?.hide();
|
|
55143
|
-
|
|
56148
|
+
resolve39(ref);
|
|
55144
56149
|
});
|
|
55145
56150
|
const width2 = Math.max(20, Math.min(host.columns() - 2, 72));
|
|
55146
56151
|
handle = host.showOverlay(new Box(view, { title: options.title, theme: host.theme }), {
|
|
@@ -55341,7 +56346,7 @@ function rewindListItems(points, cache3, highlighted, now, ascii = false) {
|
|
|
55341
56346
|
});
|
|
55342
56347
|
}
|
|
55343
56348
|
function openRewindList(host, points, cache3) {
|
|
55344
|
-
return new Promise((
|
|
56349
|
+
return new Promise((resolve39) => {
|
|
55345
56350
|
const ascii = host.theme.glyphs.ascii;
|
|
55346
56351
|
let highlighted = points.at(-1)?.entryId;
|
|
55347
56352
|
let refreshing = false;
|
|
@@ -55357,7 +56362,7 @@ function openRewindList(host, points, cache3) {
|
|
|
55357
56362
|
const close = (point) => {
|
|
55358
56363
|
closed = true;
|
|
55359
56364
|
handle.hide();
|
|
55360
|
-
|
|
56365
|
+
resolve39(point);
|
|
55361
56366
|
};
|
|
55362
56367
|
const highlight2 = (entryId) => {
|
|
55363
56368
|
highlighted = entryId;
|
|
@@ -55474,8 +56479,8 @@ function rewindOptions(model, ascii = false) {
|
|
|
55474
56479
|
}
|
|
55475
56480
|
function conflictOptions() {
|
|
55476
56481
|
const m = msg().rewind.panel;
|
|
55477
|
-
const
|
|
55478
|
-
return CONFLICT_VALUES.map((value) => ({ value, label:
|
|
56482
|
+
const labels2 = { skip: m.conflictSkip, overwrite: m.conflictOverwrite, back: m.conflictBack };
|
|
56483
|
+
return CONFLICT_VALUES.map((value) => ({ value, label: labels2[value] }));
|
|
55479
56484
|
}
|
|
55480
56485
|
var COMPACT_WIDTH4, MESSAGE_LINES, CONFLICT_VALUES, Lines4, RewindPanel;
|
|
55481
56486
|
var init_rewind_panel = __esm({
|
|
@@ -55729,7 +56734,7 @@ var init_rewind_panel = __esm({
|
|
|
55729
56734
|
|
|
55730
56735
|
// src/modes/interactive/rewind-flow.ts
|
|
55731
56736
|
function openRewindPanel(host, model) {
|
|
55732
|
-
return new Promise((
|
|
56737
|
+
return new Promise((resolve39) => {
|
|
55733
56738
|
let handle;
|
|
55734
56739
|
const panel = new RewindPanel(
|
|
55735
56740
|
model,
|
|
@@ -55740,7 +56745,7 @@ function openRewindPanel(host, model) {
|
|
|
55740
56745
|
},
|
|
55741
56746
|
(choice3) => {
|
|
55742
56747
|
handle?.hide();
|
|
55743
|
-
|
|
56748
|
+
resolve39(choice3);
|
|
55744
56749
|
}
|
|
55745
56750
|
);
|
|
55746
56751
|
handle = host.showOverlay(panel, { anchor: "bottom" });
|
|
@@ -55869,7 +56874,7 @@ var init_rewind_flow = __esm({
|
|
|
55869
56874
|
|
|
55870
56875
|
// src/modes/interactive/trace-view.ts
|
|
55871
56876
|
function openTraceView(host, taskId) {
|
|
55872
|
-
return new Promise((
|
|
56877
|
+
return new Promise((resolve39) => {
|
|
55873
56878
|
let handle;
|
|
55874
56879
|
let timer;
|
|
55875
56880
|
let unsubscribe;
|
|
@@ -55879,12 +56884,12 @@ function openTraceView(host, taskId) {
|
|
|
55879
56884
|
unsubscribe?.();
|
|
55880
56885
|
handle?.hide();
|
|
55881
56886
|
host.render?.();
|
|
55882
|
-
|
|
56887
|
+
resolve39();
|
|
55883
56888
|
};
|
|
55884
56889
|
const view = new TraceView(host, taskId, finish2);
|
|
55885
56890
|
if (!view.found) {
|
|
55886
56891
|
host.notice("warn", msg().trace.taskNotFound(taskId));
|
|
55887
|
-
|
|
56892
|
+
resolve39();
|
|
55888
56893
|
return;
|
|
55889
56894
|
}
|
|
55890
56895
|
const throttle = host.refreshMs ?? TRACE_REFRESH_MS;
|
|
@@ -56149,6 +57154,153 @@ var init_trace_view = __esm({
|
|
|
56149
57154
|
}
|
|
56150
57155
|
});
|
|
56151
57156
|
|
|
57157
|
+
// src/modes/interactive/startup-logo.ts
|
|
57158
|
+
function logoRows(theme) {
|
|
57159
|
+
return theme.glyphs.ascii ? LOGO_ASCII : LOGO_BLOCK;
|
|
57160
|
+
}
|
|
57161
|
+
function letterColor(col, ascii) {
|
|
57162
|
+
const starts = LETTER_STARTS[ascii ? "ascii" : "block"];
|
|
57163
|
+
let index2 = 0;
|
|
57164
|
+
for (let i = 0; i < starts.length; i++) if (col >= starts[i]) index2 = i;
|
|
57165
|
+
return GRADIENT[index2];
|
|
57166
|
+
}
|
|
57167
|
+
function logoWidth(rows) {
|
|
57168
|
+
return Math.max(...rows.map((row3) => [...row3].length));
|
|
57169
|
+
}
|
|
57170
|
+
function sweepFrames(theme) {
|
|
57171
|
+
return logoWidth(logoRows(theme)) + SWEEP_BAND;
|
|
57172
|
+
}
|
|
57173
|
+
function styleAt(col, ascii, sweep) {
|
|
57174
|
+
const settled = { color: letterColor(col, ascii), bold: true };
|
|
57175
|
+
if (sweep === void 0 || col <= sweep - SWEEP_BAND) return settled;
|
|
57176
|
+
if (col <= sweep) return { color: "text", bold: true };
|
|
57177
|
+
return { color: "dim", bold: false };
|
|
57178
|
+
}
|
|
57179
|
+
function paintLogo(theme, sweep) {
|
|
57180
|
+
const rows = logoRows(theme);
|
|
57181
|
+
const width2 = logoWidth(rows);
|
|
57182
|
+
return rows.map((row3) => {
|
|
57183
|
+
const chars = [...row3.padEnd(width2)];
|
|
57184
|
+
let out = "";
|
|
57185
|
+
let run7 = "";
|
|
57186
|
+
let runStyle;
|
|
57187
|
+
const flush = () => {
|
|
57188
|
+
if (run7 === "") return;
|
|
57189
|
+
if (runStyle === void 0) out += run7;
|
|
57190
|
+
else {
|
|
57191
|
+
const colored = theme.fg(runStyle.color, run7);
|
|
57192
|
+
out += runStyle.bold ? theme.bold(colored) : colored;
|
|
57193
|
+
}
|
|
57194
|
+
run7 = "";
|
|
57195
|
+
};
|
|
57196
|
+
chars.forEach((ch2, col) => {
|
|
57197
|
+
const style = ch2 === " " ? void 0 : styleAt(col, theme.glyphs.ascii, sweep);
|
|
57198
|
+
if (style?.color !== runStyle?.color || style?.bold !== runStyle?.bold) {
|
|
57199
|
+
flush();
|
|
57200
|
+
runStyle = style;
|
|
57201
|
+
}
|
|
57202
|
+
run7 += ch2;
|
|
57203
|
+
});
|
|
57204
|
+
flush();
|
|
57205
|
+
return out;
|
|
57206
|
+
});
|
|
57207
|
+
}
|
|
57208
|
+
function shouldAnimate(gate) {
|
|
57209
|
+
const ci = gate.env["CI"];
|
|
57210
|
+
return gate.animation !== false && gate.hasLogo && gate.colors > 0 && gate.io.stdoutIsTTY && !gate.host && (gate.prompt ?? "").trim() === "" && (ci === void 0 || ci === "" || ci === "0" || ci === "false") && gate.rows >= MIN_ANIMATION_ROWS;
|
|
57211
|
+
}
|
|
57212
|
+
function playStartupAnimation(tui, header, theme, conditions) {
|
|
57213
|
+
const term = tui.terminal;
|
|
57214
|
+
const columns = term.columns;
|
|
57215
|
+
if (header === void 0) return void 0;
|
|
57216
|
+
const gate = {
|
|
57217
|
+
...conditions,
|
|
57218
|
+
hasLogo: header.hasLogo(term.columns),
|
|
57219
|
+
colors: theme.caps.colors,
|
|
57220
|
+
rows: term.rows
|
|
57221
|
+
};
|
|
57222
|
+
const fits = () => tui.render(term.columns).length <= term.rows;
|
|
57223
|
+
if (!shouldAnimate(gate) || !fits()) return void 0;
|
|
57224
|
+
let offInput = () => void 0;
|
|
57225
|
+
const animation = new LogoAnimation(header, {
|
|
57226
|
+
frames: sweepFrames(theme),
|
|
57227
|
+
render: () => tui.requestRender(),
|
|
57228
|
+
// 改了尺寸(差分渲染要整屏重画)也立即定格
|
|
57229
|
+
canContinue: () => term.columns === columns && fits(),
|
|
57230
|
+
onDone: () => offInput()
|
|
57231
|
+
});
|
|
57232
|
+
offInput = tui.addInputListener(() => {
|
|
57233
|
+
animation.finish();
|
|
57234
|
+
return false;
|
|
57235
|
+
});
|
|
57236
|
+
animation.start();
|
|
57237
|
+
return animation;
|
|
57238
|
+
}
|
|
57239
|
+
var LOGO_BLOCK, LOGO_ASCII, SWEEP_BAND, FRAME_MS, GRADIENT, LETTER_STARTS, LogoAnimation, MIN_ANIMATION_ROWS;
|
|
57240
|
+
var init_startup_logo = __esm({
|
|
57241
|
+
"src/modes/interactive/startup-logo.ts"() {
|
|
57242
|
+
"use strict";
|
|
57243
|
+
LOGO_BLOCK = [
|
|
57244
|
+
" ▄███▄ ██▄ ▄██ ▄███▄",
|
|
57245
|
+
"██▀ ▀██ ███▄ ▄███ ██▀ ▀██",
|
|
57246
|
+
"███████ ██ ▀█▀ ██ ███████",
|
|
57247
|
+
"██ ██ ██ ██ ██ ██",
|
|
57248
|
+
"▀▀ ▀▀ ▀▀ ▀▀ ▀▀ ▀▀"
|
|
57249
|
+
];
|
|
57250
|
+
LOGO_ASCII = [
|
|
57251
|
+
" _ __ __ _",
|
|
57252
|
+
" / \\ | \\/ | / \\",
|
|
57253
|
+
" / _ \\ | |\\/| | / _ \\",
|
|
57254
|
+
" / ___ \\| | | |/ ___ \\",
|
|
57255
|
+
"/_/ \\_\\_| |_/_/ \\_\\"
|
|
57256
|
+
];
|
|
57257
|
+
SWEEP_BAND = 3;
|
|
57258
|
+
FRAME_MS = 32;
|
|
57259
|
+
GRADIENT = ["accent", "user", "tool"];
|
|
57260
|
+
LETTER_STARTS = { block: [0, 8, 18], ascii: [0, 8, 16] };
|
|
57261
|
+
LogoAnimation = class {
|
|
57262
|
+
constructor(target, options) {
|
|
57263
|
+
this.target = target;
|
|
57264
|
+
this.options = options;
|
|
57265
|
+
}
|
|
57266
|
+
target;
|
|
57267
|
+
options;
|
|
57268
|
+
frame = 0;
|
|
57269
|
+
timer;
|
|
57270
|
+
done = false;
|
|
57271
|
+
get running() {
|
|
57272
|
+
return !this.done && this.timer !== void 0;
|
|
57273
|
+
}
|
|
57274
|
+
start() {
|
|
57275
|
+
if (this.done || this.timer !== void 0) return;
|
|
57276
|
+
this.step();
|
|
57277
|
+
}
|
|
57278
|
+
step() {
|
|
57279
|
+
this.timer = void 0;
|
|
57280
|
+
if (this.frame >= this.options.frames || this.options.canContinue?.() === false) {
|
|
57281
|
+
this.finish();
|
|
57282
|
+
return;
|
|
57283
|
+
}
|
|
57284
|
+
this.target.setSweep(this.frame++);
|
|
57285
|
+
this.options.render();
|
|
57286
|
+
this.timer = setTimeout(() => this.step(), this.options.intervalMs ?? FRAME_MS);
|
|
57287
|
+
this.timer.unref?.();
|
|
57288
|
+
}
|
|
57289
|
+
/** 立即定格(按键、退出、走完);重复调用无副作用。 */
|
|
57290
|
+
finish() {
|
|
57291
|
+
if (this.done) return;
|
|
57292
|
+
this.done = true;
|
|
57293
|
+
if (this.timer !== void 0) clearTimeout(this.timer);
|
|
57294
|
+
this.timer = void 0;
|
|
57295
|
+
this.target.setSweep(void 0);
|
|
57296
|
+
this.options.render();
|
|
57297
|
+
this.options.onDone?.();
|
|
57298
|
+
}
|
|
57299
|
+
};
|
|
57300
|
+
MIN_ANIMATION_ROWS = 16;
|
|
57301
|
+
}
|
|
57302
|
+
});
|
|
57303
|
+
|
|
56152
57304
|
// src/modes/interactive/startup-header.ts
|
|
56153
57305
|
function truncateLeft(text, width2, ellipsis = "…") {
|
|
56154
57306
|
if (visibleWidth(text) <= width2) return text;
|
|
@@ -56165,19 +57317,26 @@ function truncateLeft(text, width2, ellipsis = "…") {
|
|
|
56165
57317
|
}
|
|
56166
57318
|
return ellipsis + out;
|
|
56167
57319
|
}
|
|
57320
|
+
function fitSegments(text, width2) {
|
|
57321
|
+
const parts = text.split(" · ");
|
|
57322
|
+
while (parts.length > 1 && visibleWidth(parts.join(" · ")) > width2) parts.pop();
|
|
57323
|
+
return parts.join(" · ");
|
|
57324
|
+
}
|
|
56168
57325
|
function withoutChannel(model) {
|
|
56169
57326
|
const at = model.indexOf("@");
|
|
56170
57327
|
return at === -1 ? model : model.slice(0, at);
|
|
56171
57328
|
}
|
|
56172
|
-
var
|
|
57329
|
+
var HEADER_SIDE_MIN_WIDTH, HEADER_LOGO_MIN_WIDTH, GAP, StartupHeader;
|
|
56173
57330
|
var init_startup_header = __esm({
|
|
56174
57331
|
"src/modes/interactive/startup-header.ts"() {
|
|
56175
57332
|
"use strict";
|
|
56176
57333
|
init_i18n();
|
|
56177
57334
|
init_modes();
|
|
56178
57335
|
init_tui2();
|
|
56179
|
-
|
|
56180
|
-
|
|
57336
|
+
init_startup_logo();
|
|
57337
|
+
HEADER_SIDE_MIN_WIDTH = 72;
|
|
57338
|
+
HEADER_LOGO_MIN_WIDTH = 48;
|
|
57339
|
+
GAP = 3;
|
|
56181
57340
|
StartupHeader = class {
|
|
56182
57341
|
constructor(info2, options) {
|
|
56183
57342
|
this.info = info2;
|
|
@@ -56186,9 +57345,19 @@ var init_startup_header = __esm({
|
|
|
56186
57345
|
info;
|
|
56187
57346
|
options;
|
|
56188
57347
|
cache = null;
|
|
57348
|
+
sweep;
|
|
56189
57349
|
get theme() {
|
|
56190
57350
|
return this.options.theme;
|
|
56191
57351
|
}
|
|
57352
|
+
/** 这个宽度下是否画字符画(动画只在画了时播放)。 */
|
|
57353
|
+
hasLogo(width2) {
|
|
57354
|
+
return this.options.level === "normal" && this.options.logo !== "off" && this.options.compact !== true && width2 >= HEADER_LOGO_MIN_WIDTH;
|
|
57355
|
+
}
|
|
57356
|
+
setSweep(sweep) {
|
|
57357
|
+
if (sweep === this.sweep) return;
|
|
57358
|
+
this.sweep = sweep;
|
|
57359
|
+
this.cache = null;
|
|
57360
|
+
}
|
|
56192
57361
|
title() {
|
|
56193
57362
|
const t = this.theme;
|
|
56194
57363
|
return `${t.fg("accent", t.glyphs.thinking)} ${t.bold(`ama ${this.info.version}`)}`;
|
|
@@ -56217,7 +57386,11 @@ var init_startup_header = __esm({
|
|
|
56217
57386
|
}
|
|
56218
57387
|
render(width2) {
|
|
56219
57388
|
if (this.cache?.width === width2) return this.cache.lines;
|
|
56220
|
-
|
|
57389
|
+
let lines2;
|
|
57390
|
+
if (this.options.level === "header") lines2 = [this.headerLine(width2)];
|
|
57391
|
+
else if (width2 < HEADER_LOGO_MIN_WIDTH) lines2 = this.narrowLines(width2);
|
|
57392
|
+
else if (!this.hasLogo(width2)) lines2 = this.infoLines(width2, this.title());
|
|
57393
|
+
else lines2 = this.logoLines(width2);
|
|
56221
57394
|
this.cache = { width: width2, lines: lines2 };
|
|
56222
57395
|
return lines2;
|
|
56223
57396
|
}
|
|
@@ -56232,64 +57405,63 @@ var init_startup_header = __esm({
|
|
|
56232
57405
|
];
|
|
56233
57406
|
return truncateToWidth(parts.join(sep5), width2);
|
|
56234
57407
|
}
|
|
56235
|
-
|
|
57408
|
+
/** < 48 列:两行(版本 · 模型 · 思考 / 模式 · 目录 · 信任),有警告再加一行。 */
|
|
57409
|
+
narrowLines(width2) {
|
|
56236
57410
|
const t = this.theme;
|
|
56237
57411
|
const sep5 = t.fg("dim", " · ");
|
|
56238
|
-
const ellipsis = t.glyphs.ellipsis;
|
|
56239
57412
|
const { info: info2 } = this;
|
|
56240
|
-
const lines2 = [
|
|
56241
|
-
|
|
57413
|
+
const lines2 = [
|
|
57414
|
+
[this.title(), t.fg("accent", withoutChannel(info2.model)), info2.thinking].join(sep5)
|
|
57415
|
+
];
|
|
57416
|
+
const mode = this.modeText();
|
|
56242
57417
|
const trust = this.trustText(false);
|
|
56243
|
-
const room = Math.max(4, width2 - visibleWidth(trust) -
|
|
56244
|
-
lines2.push(truncateLeft(info2.cwd, room, ellipsis)
|
|
56245
|
-
|
|
56246
|
-
(
|
|
56247
|
-
|
|
56248
|
-
lines2.push(mode.join(sep5));
|
|
56249
|
-
const loaded = this.loadedText();
|
|
56250
|
-
if (loaded !== void 0) lines2.push(loaded);
|
|
56251
|
-
const m = msg().interactive.startup.header;
|
|
56252
|
-
if (info2.host !== void 0) lines2.push(m.host(info2.host));
|
|
56253
|
-
if (info2.warnings > 0) lines2.push(t.fg("warning", m.warnings(info2.warnings)));
|
|
56254
|
-
lines2.push(t.fg("dim", m.hintCompact));
|
|
57418
|
+
const room = Math.max(4, width2 - visibleWidth(mode) - visibleWidth(trust) - 6);
|
|
57419
|
+
lines2.push([mode, truncateLeft(info2.cwd, room, t.glyphs.ellipsis), trust].join(sep5));
|
|
57420
|
+
if (info2.warnings > 0) {
|
|
57421
|
+
lines2.push(t.fg("warning", msg().interactive.startup.header.warnings(info2.warnings)));
|
|
57422
|
+
}
|
|
56255
57423
|
return lines2.map((line2) => truncateToWidth(line2, width2));
|
|
56256
57424
|
}
|
|
56257
|
-
|
|
57425
|
+
/** 信息列:首行 `title`,其后模型、目录、模式、可选行、按键提示;每行截到 `width`。 */
|
|
57426
|
+
infoLines(width2, title) {
|
|
56258
57427
|
const t = this.theme;
|
|
56259
57428
|
const sep5 = t.fg("dim", " · ");
|
|
56260
57429
|
const { info: info2 } = this;
|
|
56261
57430
|
const m = msg().interactive.startup.header;
|
|
56262
|
-
const boxWidth = Math.min(width2, HEADER_BOX_MAX_WIDTH);
|
|
56263
|
-
const keyWidth = Math.max(
|
|
56264
|
-
6,
|
|
56265
|
-
...[m.keyModel, m.keyDir, m.keyMode, m.keyLoaded, m.keyHost, m.keyWarnings].map(
|
|
56266
|
-
(k) => visibleWidth(k)
|
|
56267
|
-
)
|
|
56268
|
-
);
|
|
56269
|
-
const valueWidth = boxWidth - 4 - keyWidth - 1;
|
|
56270
57431
|
const trust = this.trustText(true);
|
|
56271
|
-
const cwdRoom = Math.max(4,
|
|
56272
|
-
const
|
|
56273
|
-
|
|
56274
|
-
|
|
56275
|
-
|
|
56276
|
-
|
|
56277
|
-
value: [this.modeText(), m.preset(info2.preset), this.codemodeText()].filter((p) => p !== void 0).join(sep5)
|
|
56278
|
-
}
|
|
57432
|
+
const cwdRoom = Math.max(4, width2 - visibleWidth(trust) - 3);
|
|
57433
|
+
const lines2 = [
|
|
57434
|
+
title,
|
|
57435
|
+
t.fg("accent", info2.model) + sep5 + m.thinking(info2.thinking),
|
|
57436
|
+
truncateLeft(info2.cwd, cwdRoom, t.glyphs.ellipsis) + sep5 + trust,
|
|
57437
|
+
[this.modeText(), m.preset(info2.preset), this.codemodeText()].filter((p) => p !== void 0).join(sep5)
|
|
56279
57438
|
];
|
|
56280
57439
|
const loaded = this.loadedText();
|
|
56281
|
-
if (loaded !== void 0)
|
|
56282
|
-
if (info2.host !== void 0)
|
|
56283
|
-
if (info2.warnings > 0)
|
|
56284
|
-
|
|
57440
|
+
if (loaded !== void 0) lines2.push(loaded);
|
|
57441
|
+
if (info2.host !== void 0) lines2.push(m.host(info2.host));
|
|
57442
|
+
if (info2.warnings > 0) lines2.push(t.fg("warning", m.warnings(info2.warnings)));
|
|
57443
|
+
lines2.push(t.fg("dim", fitSegments(m.hint, width2)));
|
|
57444
|
+
return lines2.map((line2) => truncateToWidth(line2, width2));
|
|
57445
|
+
}
|
|
57446
|
+
/** 字符画 + 信息列:够宽并排(顶端对齐),否则上下叠放。 */
|
|
57447
|
+
logoLines(width2) {
|
|
57448
|
+
const t = this.theme;
|
|
57449
|
+
const logo = paintLogo(t, this.sweep);
|
|
57450
|
+
const logoCols = logoWidth(logoRows(t));
|
|
57451
|
+
const title = `${t.bold("ama")} ${t.fg("dim", this.info.version)}`;
|
|
57452
|
+
if (width2 < HEADER_SIDE_MIN_WIDTH) {
|
|
57453
|
+
return [...logo, "", ...this.infoLines(width2, title)];
|
|
57454
|
+
}
|
|
57455
|
+
const info2 = this.infoLines(width2 - logoCols - GAP, title);
|
|
57456
|
+
const rows = Math.max(logo.length, info2.length);
|
|
57457
|
+
const blank = " ".repeat(logoCols);
|
|
57458
|
+
const gap = " ".repeat(GAP);
|
|
57459
|
+
const lines2 = [];
|
|
57460
|
+
for (let i = 0; i < rows; i++) {
|
|
57461
|
+
const right = info2[i];
|
|
57462
|
+
lines2.push(right === void 0 ? logo[i] ?? "" : (logo[i] ?? blank) + gap + right);
|
|
56285
57463
|
}
|
|
56286
|
-
|
|
56287
|
-
const kv = new KeyValue(padded, { theme: t, gap: 1, maxKeyRatio: 1 });
|
|
56288
|
-
const body = {
|
|
56289
|
-
render: (inner) => [this.title(), "", ...kv.render(inner), "", t.fg("dim", m.hint)],
|
|
56290
|
-
invalidate: () => kv.invalidate()
|
|
56291
|
-
};
|
|
56292
|
-
return new Box(body, { theme: t }).render(boxWidth);
|
|
57464
|
+
return lines2;
|
|
56293
57465
|
}
|
|
56294
57466
|
invalidate() {
|
|
56295
57467
|
this.cache = null;
|
|
@@ -56328,6 +57500,10 @@ var init_run_indicator = __esm({
|
|
|
56328
57500
|
RunIndicator = class {
|
|
56329
57501
|
constructor(deps) {
|
|
56330
57502
|
this.deps = deps;
|
|
57503
|
+
deps.loader.onFrame(() => {
|
|
57504
|
+
if (this.busy && !this.approval && this.optionalHints().join("\n") !== this.hintKey)
|
|
57505
|
+
this.applyVerb();
|
|
57506
|
+
});
|
|
56331
57507
|
}
|
|
56332
57508
|
deps;
|
|
56333
57509
|
running = false;
|
|
@@ -56335,6 +57511,23 @@ var init_run_indicator = __esm({
|
|
|
56335
57511
|
approval = false;
|
|
56336
57512
|
retry;
|
|
56337
57513
|
stream;
|
|
57514
|
+
/** [W7-A] 有该显示的子 Agent 任务(interactive-mode 在 AgentUi 建好后接上)。 */
|
|
57515
|
+
agents = () => false;
|
|
57516
|
+
/** [W7-C] 有阻塞中的前台任务(Ctrl+B 可转后台)。 */
|
|
57517
|
+
background = () => false;
|
|
57518
|
+
/** [W7-C] 有停靠在 Agent 栏的审批。 */
|
|
57519
|
+
docked = () => false;
|
|
57520
|
+
hintKey = "";
|
|
57521
|
+
/** 可丢弃的按键提示(按丢弃的逆序排列)。 */
|
|
57522
|
+
optionalHints() {
|
|
57523
|
+
const down = this.deps.theme.glyphs.arrowDown;
|
|
57524
|
+
const key = this.deps.backgroundKey;
|
|
57525
|
+
const out = [];
|
|
57526
|
+
if (key !== void 0 && this.background()) out.push(msg().agents.background.runHint(key));
|
|
57527
|
+
if (this.docked()) out.push(msg().agents.approval.runHint(down));
|
|
57528
|
+
else if (this.agents()) out.push(msg().agents.bar.runHint(down));
|
|
57529
|
+
return out;
|
|
57530
|
+
}
|
|
56338
57531
|
get busy() {
|
|
56339
57532
|
return this.running || this.compacting;
|
|
56340
57533
|
}
|
|
@@ -56413,17 +57606,21 @@ var init_run_indicator = __esm({
|
|
|
56413
57606
|
const m = msg().interactive.view.run;
|
|
56414
57607
|
const esc = [m.esc];
|
|
56415
57608
|
if (this.approval) {
|
|
57609
|
+
this.hintKey = "";
|
|
56416
57610
|
loader.setVerb(m.awaitingApproval);
|
|
56417
57611
|
return;
|
|
56418
57612
|
}
|
|
57613
|
+
const hints = this.optionalHints();
|
|
57614
|
+
this.hintKey = hints.join("\n");
|
|
57615
|
+
const optional = hints.length > 0 ? { optional: hints } : {};
|
|
56419
57616
|
const running = tools.running();
|
|
56420
57617
|
const top = running.filter((view) => !running.some((p) => p.children.includes(view)));
|
|
56421
57618
|
if (top.length === 1) {
|
|
56422
|
-
loader.setVerb(m.runningTool(top[0].toolName), esc);
|
|
57619
|
+
loader.setVerb(m.runningTool(top[0].toolName), esc, optional);
|
|
56423
57620
|
return;
|
|
56424
57621
|
}
|
|
56425
57622
|
if (top.length > 1) {
|
|
56426
|
-
loader.setVerb(m.runningTools(top.length), esc);
|
|
57623
|
+
loader.setVerb(m.runningTools(top.length), esc, optional);
|
|
56427
57624
|
return;
|
|
56428
57625
|
}
|
|
56429
57626
|
if (this.retry !== void 0) {
|
|
@@ -56434,15 +57631,15 @@ var init_run_indicator = __esm({
|
|
|
56434
57631
|
return;
|
|
56435
57632
|
}
|
|
56436
57633
|
if (this.compacting) {
|
|
56437
|
-
loader.setVerb(m.compacting, esc);
|
|
57634
|
+
loader.setVerb(m.compacting, esc, optional);
|
|
56438
57635
|
return;
|
|
56439
57636
|
}
|
|
56440
57637
|
const stream5 = this.stream;
|
|
56441
57638
|
if (stream5 !== void 0 && !stream5.thinking && stream5.tokens > 0) {
|
|
56442
|
-
loader.setVerb(m.replying, [`↓≈${formatTokens3(stream5.tokens)}`, ...esc]);
|
|
57639
|
+
loader.setVerb(m.replying, [`↓≈${formatTokens3(stream5.tokens)}`, ...esc], optional);
|
|
56443
57640
|
return;
|
|
56444
57641
|
}
|
|
56445
|
-
loader.setVerb(m.thinking, esc);
|
|
57642
|
+
loader.setVerb(m.thinking, esc, optional);
|
|
56446
57643
|
}
|
|
56447
57644
|
};
|
|
56448
57645
|
QueueView = class extends Text {
|
|
@@ -56481,7 +57678,10 @@ function createSessionEventHandler(deps) {
|
|
|
56481
57678
|
const { view, tools, status, area, agentUi, indicator, session, setQueue, notice, render } = deps;
|
|
56482
57679
|
const images = new ImageBudgetNotices((text) => notice("info", text));
|
|
56483
57680
|
return (event) => {
|
|
56484
|
-
if (area.onEvent(event) || agentUi().onEvent(event))
|
|
57681
|
+
if (area.onEvent(event) || agentUi().onEvent(event)) {
|
|
57682
|
+
if (event.type === "subagent_start" || event.type === "subagent_end") indicator.sync();
|
|
57683
|
+
return render();
|
|
57684
|
+
}
|
|
56485
57685
|
images.onEvent(event);
|
|
56486
57686
|
switch (event.type) {
|
|
56487
57687
|
case "agent_settled":
|
|
@@ -56677,6 +57877,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
56677
57877
|
tui.addChild(hint);
|
|
56678
57878
|
tui.addChild(area.rate);
|
|
56679
57879
|
tui.addChild(status);
|
|
57880
|
+
tui.addChild(area.quota);
|
|
56680
57881
|
let finished = false;
|
|
56681
57882
|
let hintTimer;
|
|
56682
57883
|
let resolveExit = () => void 0;
|
|
@@ -56698,7 +57899,11 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
56698
57899
|
}
|
|
56699
57900
|
render();
|
|
56700
57901
|
};
|
|
56701
|
-
const
|
|
57902
|
+
const backgroundKey = keyLabel(keys, "app.tasks.background");
|
|
57903
|
+
const indicator = new RunIndicator({
|
|
57904
|
+
...{ theme, loader, slot: loaderSlot, tools, render },
|
|
57905
|
+
...backgroundKey !== void 0 ? { backgroundKey } : {}
|
|
57906
|
+
});
|
|
56702
57907
|
const setQueue = (steering, followUp) => {
|
|
56703
57908
|
status.setQueue(steering.length, followUp.length);
|
|
56704
57909
|
queueView.setQueue(steering, followUp);
|
|
@@ -56720,7 +57925,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
56720
57925
|
const startupLevel = startupScreenLevel(runtime);
|
|
56721
57926
|
const home = env["HOME"] ?? env["USERPROFILE"];
|
|
56722
57927
|
const info2 = startupInfo(runtime, home);
|
|
56723
|
-
const header = (level) => new StartupHeader(info2, { theme, level,
|
|
57928
|
+
const header = (level) => new StartupHeader(info2, { theme, level, logo: ui.logo, compact: ui.compact });
|
|
56724
57929
|
const resetView = () => {
|
|
56725
57930
|
view.reset();
|
|
56726
57931
|
if (startupLevel !== "silent") view.add(header("header"));
|
|
@@ -56893,22 +58098,13 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
56893
58098
|
runCommand: (line2) => void runCommand2(line2),
|
|
56894
58099
|
exit: (code) => exit(code),
|
|
56895
58100
|
onInterrupted: (empty) => void rewind.afterInterrupt(empty),
|
|
56896
|
-
agents: () => agentUi.keys
|
|
58101
|
+
agents: () => agentUi.keys,
|
|
58102
|
+
downGlyph: theme.glyphs.arrowDown,
|
|
58103
|
+
backgroundTasks: () => backgroundTasks(session),
|
|
58104
|
+
runningBackground: () => runningBackground(session)
|
|
56897
58105
|
})
|
|
56898
58106
|
);
|
|
56899
|
-
const overlayHooks = {
|
|
56900
|
-
showOverlay: (component) => tui.showOverlay(component, { anchor: "bottom" }),
|
|
56901
|
-
onOpen: () => {
|
|
56902
|
-
editor.disableSubmit = true;
|
|
56903
|
-
tools.setAwaiting(true);
|
|
56904
|
-
indicator.setApproval(true);
|
|
56905
|
-
},
|
|
56906
|
-
onClose: () => {
|
|
56907
|
-
editor.disableSubmit = false;
|
|
56908
|
-
tools.setAwaiting(false);
|
|
56909
|
-
indicator.setApproval(false);
|
|
56910
|
-
}
|
|
56911
|
-
};
|
|
58107
|
+
const overlayHooks = approvalOverlayHooks({ tui, editor, tools: () => tools, indicator });
|
|
56912
58108
|
const agentUi = new AgentUi({
|
|
56913
58109
|
theme,
|
|
56914
58110
|
tui,
|
|
@@ -56931,33 +58127,18 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
56931
58127
|
...options.clipboard !== void 0 ? { clipboard: options.clipboard } : {},
|
|
56932
58128
|
area
|
|
56933
58129
|
});
|
|
56934
|
-
|
|
56935
|
-
const broker =
|
|
56936
|
-
|
|
56937
|
-
|
|
56938
|
-
|
|
56939
|
-
|
|
56940
|
-
|
|
56941
|
-
taskAgent,
|
|
56942
|
-
externalRunner: (agent) => agentUi.merge.externalRunner(agent),
|
|
56943
|
-
...overlayHooks,
|
|
56944
|
-
report: (request, outcome) => {
|
|
56945
|
-
if (outcome === "deny" || outcome === "cancelled") {
|
|
56946
|
-
const text = approvalOutcomeText(request, outcome, taskAgent);
|
|
56947
|
-
notice(outcome === "deny" ? "info" : "warn", text);
|
|
56948
|
-
}
|
|
56949
|
-
}
|
|
56950
|
-
}),
|
|
56951
|
-
agentUi.merge,
|
|
56952
|
-
(request) => notice(
|
|
56953
|
-
"info",
|
|
56954
|
-
msg().interactive.app.followed(approvalOutcomeText(request, "allow", taskAgent))
|
|
56955
|
-
)
|
|
56956
|
-
);
|
|
58130
|
+
indicator.agents = () => agentUi.reachable;
|
|
58131
|
+
const { broker, dock } = createApprovalUi({
|
|
58132
|
+
...{ theme, keys, tui, editor, indicator, agentUi, notice, render },
|
|
58133
|
+
hooks: overlayHooks,
|
|
58134
|
+
session: () => session
|
|
58135
|
+
});
|
|
58136
|
+
indicator.background = () => blockingTasks2(session).length > 0;
|
|
56957
58137
|
let offSignals = () => void 0;
|
|
56958
58138
|
function exit(code) {
|
|
56959
58139
|
if (finished) return;
|
|
56960
58140
|
finished = true;
|
|
58141
|
+
logoAnimation?.finish();
|
|
56961
58142
|
if (hintTimer !== void 0) clearTimeout(hintTimer);
|
|
56962
58143
|
loader.stop();
|
|
56963
58144
|
area.dispose();
|
|
@@ -56966,6 +58147,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
56966
58147
|
tui.addChild(view);
|
|
56967
58148
|
offSignals();
|
|
56968
58149
|
agentUi.detach();
|
|
58150
|
+
dock.dispose();
|
|
56969
58151
|
runtime.approvals.setUiBroker(void 0);
|
|
56970
58152
|
runtime.notifier.set(void 0);
|
|
56971
58153
|
tui.stop();
|
|
@@ -56975,12 +58157,14 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
56975
58157
|
resolveExit(code);
|
|
56976
58158
|
});
|
|
56977
58159
|
}
|
|
56978
|
-
|
|
58160
|
+
const startHeader = startupLevel === "silent" ? void 0 : header(startupLevel);
|
|
58161
|
+
let logoAnimation;
|
|
58162
|
+
if (startHeader !== void 0) view.add(startHeader);
|
|
56979
58163
|
for (const warning of startupWarnings) view.addNotice("warn", warning);
|
|
56980
58164
|
replay();
|
|
56981
58165
|
status.refresh();
|
|
56982
|
-
return new Promise((
|
|
56983
|
-
resolveExit =
|
|
58166
|
+
return new Promise((resolve39, reject2) => {
|
|
58167
|
+
resolveExit = resolve39;
|
|
56984
58168
|
try {
|
|
56985
58169
|
tui.start();
|
|
56986
58170
|
} catch (error2) {
|
|
@@ -57001,6 +58185,8 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
57001
58185
|
agentUi.attach(session);
|
|
57002
58186
|
offSignals = onTerminationSignals((code) => exit(code));
|
|
57003
58187
|
tui.setFocus(editor);
|
|
58188
|
+
const gate = { animation: ui.animation, host: info2.host !== void 0, env, ...context };
|
|
58189
|
+
logoAnimation = playStartupAnimation(tui, startHeader, theme, gate);
|
|
57004
58190
|
options.onReady?.({
|
|
57005
58191
|
tui,
|
|
57006
58192
|
editor,
|
|
@@ -57024,7 +58210,6 @@ var init_interactive_mode = __esm({
|
|
|
57024
58210
|
init_image_input();
|
|
57025
58211
|
import_node_path97 = require("node:path");
|
|
57026
58212
|
init_session2();
|
|
57027
|
-
init_subagent_registry();
|
|
57028
58213
|
init_compose_session();
|
|
57029
58214
|
init_startup_screen();
|
|
57030
58215
|
init_errors();
|
|
@@ -57033,8 +58218,7 @@ var init_interactive_mode = __esm({
|
|
|
57033
58218
|
init_bypass();
|
|
57034
58219
|
init_shared2();
|
|
57035
58220
|
init_agent_ui();
|
|
57036
|
-
|
|
57037
|
-
init_approval_merge();
|
|
58221
|
+
init_approval_ui();
|
|
57038
58222
|
init_commands2();
|
|
57039
58223
|
init_memory_panel();
|
|
57040
58224
|
init_completion();
|
|
@@ -57047,12 +58231,14 @@ var init_interactive_mode = __esm({
|
|
|
57047
58231
|
init_rewind_flow();
|
|
57048
58232
|
init_trace_view();
|
|
57049
58233
|
init_startup_header();
|
|
58234
|
+
init_startup_logo();
|
|
57050
58235
|
init_run_indicator();
|
|
57051
58236
|
init_status_area();
|
|
57052
58237
|
init_session_events();
|
|
57053
58238
|
init_subagent_view();
|
|
57054
58239
|
init_terminal_setup();
|
|
57055
58240
|
init_tool_view();
|
|
58241
|
+
init_task_background();
|
|
57056
58242
|
HINT_MS = 2500;
|
|
57057
58243
|
}
|
|
57058
58244
|
});
|
|
@@ -57106,7 +58292,7 @@ function createTextStartupUi(io) {
|
|
|
57106
58292
|
io.write([...lines2, question].join("\n"));
|
|
57107
58293
|
return readOneLine(io.stdin);
|
|
57108
58294
|
};
|
|
57109
|
-
const list5 = (values,
|
|
58295
|
+
const list5 = (values, labels2) => values.map((_, i) => ` ${i + 1}. ${labels2[i]}`);
|
|
57110
58296
|
return {
|
|
57111
58297
|
async promptTrust(cwd, resources) {
|
|
57112
58298
|
const m = msg().report.startup;
|
|
@@ -57121,11 +58307,11 @@ function createTextStartupUi(io) {
|
|
|
57121
58307
|
if (items.length === 0) return void 0;
|
|
57122
58308
|
const sorted = [...items].sort((a, b) => b.modifiedAt.localeCompare(a.modifiedAt));
|
|
57123
58309
|
const ids = sorted.map((item) => item.id);
|
|
57124
|
-
const
|
|
58310
|
+
const labels2 = sorted.map(
|
|
57125
58311
|
(item) => `${item.id.slice(0, 8)} ${(item.name ?? item.firstPrompt ?? "").replace(/\s+/g, " ").slice(0, 60)}`
|
|
57126
58312
|
);
|
|
57127
58313
|
const m = msg().report.startup;
|
|
57128
|
-
return choose(await ask([m.resumeQuestion, ...list5(ids,
|
|
58314
|
+
return choose(await ask([m.resumeQuestion, ...list5(ids, labels2)], m.resumeAnswer), ids);
|
|
57129
58315
|
},
|
|
57130
58316
|
async pickModel(providers, reason) {
|
|
57131
58317
|
const refs = [];
|
|
@@ -58903,15 +60089,15 @@ function browserCommand(url, platform = process.platform) {
|
|
|
58903
60089
|
return { command: "cmd", args: ["/c", "start", '""', url.replace(/&/g, "^&")] };
|
|
58904
60090
|
return { command: "xdg-open", args: [url] };
|
|
58905
60091
|
}
|
|
58906
|
-
var openBrowser = (url) => new Promise((
|
|
60092
|
+
var openBrowser = (url) => new Promise((resolve39) => {
|
|
58907
60093
|
const { command: command3, args } = browserCommand(url);
|
|
58908
60094
|
try {
|
|
58909
60095
|
const child = (0, import_node_child_process12.spawn)(command3, args, { stdio: "ignore", detached: true, windowsHide: true });
|
|
58910
|
-
child.once("error", () =>
|
|
58911
|
-
child.once("exit", (code) =>
|
|
60096
|
+
child.once("error", () => resolve39(false));
|
|
60097
|
+
child.once("exit", (code) => resolve39(code === 0 || code === null));
|
|
58912
60098
|
child.unref();
|
|
58913
60099
|
} catch {
|
|
58914
|
-
|
|
60100
|
+
resolve39(false);
|
|
58915
60101
|
}
|
|
58916
60102
|
});
|
|
58917
60103
|
|
|
@@ -58938,7 +60124,7 @@ function listed(item) {
|
|
|
58938
60124
|
const visibility = item["visibility"];
|
|
58939
60125
|
return visibility === void 0 || visibility === "list";
|
|
58940
60126
|
}
|
|
58941
|
-
function
|
|
60127
|
+
function backendMetadata(item) {
|
|
58942
60128
|
const out = {};
|
|
58943
60129
|
const window2 = item["context_window"];
|
|
58944
60130
|
if (typeof window2 === "number" && Number.isInteger(window2) && window2 > 0)
|
|
@@ -58978,7 +60164,7 @@ async function listChatGptModels(fetchFn, baseUrl, auth) {
|
|
|
58978
60164
|
out.push({
|
|
58979
60165
|
id,
|
|
58980
60166
|
...typeof name === "string" && name !== "" ? { name } : {},
|
|
58981
|
-
...
|
|
60167
|
+
...backendMetadata(item)
|
|
58982
60168
|
});
|
|
58983
60169
|
}
|
|
58984
60170
|
return out;
|
|
@@ -59080,7 +60266,7 @@ function parseCallbackUrl(input2, state) {
|
|
|
59080
60266
|
return codeFromParams(params, state);
|
|
59081
60267
|
}
|
|
59082
60268
|
function listen(server, port) {
|
|
59083
|
-
return new Promise((
|
|
60269
|
+
return new Promise((resolve39, reject2) => {
|
|
59084
60270
|
const onError = (error2) => {
|
|
59085
60271
|
server.off("listening", onListening);
|
|
59086
60272
|
reject2(error2);
|
|
@@ -59088,7 +60274,7 @@ function listen(server, port) {
|
|
|
59088
60274
|
const onListening = () => {
|
|
59089
60275
|
server.off("error", onError);
|
|
59090
60276
|
const address = server.address();
|
|
59091
|
-
|
|
60277
|
+
resolve39(typeof address === "object" && address !== null ? address.port : port);
|
|
59092
60278
|
};
|
|
59093
60279
|
server.once("error", onError);
|
|
59094
60280
|
server.once("listening", onListening);
|
|
@@ -59099,8 +60285,8 @@ async function startCallbackServer(options) {
|
|
|
59099
60285
|
const path = options.path ?? CALLBACK_PATH;
|
|
59100
60286
|
const pages = options.pages ?? DEFAULT_PAGES;
|
|
59101
60287
|
let settle;
|
|
59102
|
-
const result = new Promise((
|
|
59103
|
-
settle = { resolve:
|
|
60288
|
+
const result = new Promise((resolve39, reject2) => {
|
|
60289
|
+
settle = { resolve: resolve39, reject: reject2 };
|
|
59104
60290
|
});
|
|
59105
60291
|
result.catch(() => {
|
|
59106
60292
|
});
|
|
@@ -59220,9 +60406,9 @@ async function loginPaste(preset, deps) {
|
|
|
59220
60406
|
}
|
|
59221
60407
|
var DEVICE_MAX_WAIT_MS = 15 * 6e4;
|
|
59222
60408
|
function defaultSleep(ms, signal) {
|
|
59223
|
-
return new Promise((
|
|
60409
|
+
return new Promise((resolve39, reject2) => {
|
|
59224
60410
|
if (signal?.aborted) return reject2(new AmaError("aborted", "login aborted"));
|
|
59225
|
-
const timer = setTimeout(
|
|
60411
|
+
const timer = setTimeout(resolve39, ms);
|
|
59226
60412
|
signal?.addEventListener(
|
|
59227
60413
|
"abort",
|
|
59228
60414
|
() => {
|
|
@@ -61053,12 +62239,12 @@ var RATE_LIMIT_RETRY_MS = 2e3;
|
|
|
61053
62239
|
var RECOVER_AFTER = 4;
|
|
61054
62240
|
var FATAL_STATUS = /^(?:HTTP )?(?:401|403|429)\b/;
|
|
61055
62241
|
var RATE_LIMITED = /^(?:HTTP )?429\b/;
|
|
61056
|
-
var sleep5 = (ms, signal) => new Promise((
|
|
62242
|
+
var sleep5 = (ms, signal) => new Promise((resolve39) => {
|
|
61057
62243
|
const timer = setTimeout(done, ms);
|
|
61058
62244
|
function done() {
|
|
61059
62245
|
clearTimeout(timer);
|
|
61060
62246
|
signal?.removeEventListener("abort", done);
|
|
61061
|
-
|
|
62247
|
+
resolve39();
|
|
61062
62248
|
}
|
|
61063
62249
|
signal?.addEventListener("abort", done, { once: true });
|
|
61064
62250
|
});
|
|
@@ -61185,7 +62371,7 @@ var ProbeScheduler = class {
|
|
|
61185
62371
|
async run(count2, task, onDone) {
|
|
61186
62372
|
const results = new Array(count2).fill(void 0);
|
|
61187
62373
|
let next = 0;
|
|
61188
|
-
await new Promise((
|
|
62374
|
+
await new Promise((resolve39, reject2) => {
|
|
61189
62375
|
const pump = () => {
|
|
61190
62376
|
while (this.stopReason === void 0 && next < count2 && this.active < this.limit) {
|
|
61191
62377
|
const index2 = next++;
|
|
@@ -61205,7 +62391,7 @@ var ProbeScheduler = class {
|
|
|
61205
62391
|
}
|
|
61206
62392
|
);
|
|
61207
62393
|
}
|
|
61208
|
-
if (this.active === 0 && (next >= count2 || this.stopReason !== void 0))
|
|
62394
|
+
if (this.active === 0 && (next >= count2 || this.stopReason !== void 0)) resolve39();
|
|
61209
62395
|
};
|
|
61210
62396
|
pump();
|
|
61211
62397
|
});
|
|
@@ -61443,10 +62629,15 @@ async function run6(ctx) {
|
|
|
61443
62629
|
const fields = match !== void 0 ? modelsDevFields(match.model) : void 0;
|
|
61444
62630
|
if (fields?.toolCall === false) noTools.add(model.id);
|
|
61445
62631
|
if (match === void 0) unmatched.add(model.id);
|
|
61446
|
-
const
|
|
62632
|
+
const backendCtx = model.contextWindow !== void 0 ? ` ctx ${compactTokens(model.contextWindow)}${m.fromBackend}` : void 0;
|
|
62633
|
+
const meta2 = fields === void 0 ? `${backendCtx ?? ""}${m.unmatched}` : `${backendCtx ?? ` ctx ${compactTokens(fields.contextWindow)}`} · out ${compactTokens(fields.maxTokens)}${fields.input?.includes("image") ? m.image : ""}${fields.reasoning ? m.reasoning : ""}${fields.toolCall === false ? m.noTools : ""} · ${matchLabel(match)}`;
|
|
61447
62634
|
io.stdout(` ${model.id}${known !== void 0 ? m.configured(known.api) : ""}${meta2}
|
|
61448
62635
|
`);
|
|
61449
62636
|
}
|
|
62637
|
+
if (provider.id === CHATGPT_PROVIDER_ID) {
|
|
62638
|
+
const missing = found.filter((x) => x.contextWindow === void 0).map((x) => x.id);
|
|
62639
|
+
if (missing.length > 0) io.stdout(m.noBackendWindow(missing.join(", ")));
|
|
62640
|
+
}
|
|
61450
62641
|
const write2 = ctx.flags.has("write");
|
|
61451
62642
|
if (!ctx.flags.has("probe") || provider.id === CHATGPT_PROVIDER_ID) {
|
|
61452
62643
|
if (write2)
|
|
@@ -61602,13 +62793,13 @@ async function disable(ctx) {
|
|
|
61602
62793
|
}
|
|
61603
62794
|
async function listEnabled(ctx) {
|
|
61604
62795
|
const m = msg().subcommands.modelsEnabled;
|
|
61605
|
-
const
|
|
62796
|
+
const labels2 = msg().panels.model;
|
|
61606
62797
|
const list5 = enabledList(ctx.level.merged.config.models?.enabled);
|
|
61607
62798
|
const status = async (providerId) => {
|
|
61608
62799
|
const provider = ctx.registry.get(providerId);
|
|
61609
62800
|
if (provider === void 0) return "?";
|
|
61610
62801
|
const access = await providerAccess(ctx.registry, provider);
|
|
61611
|
-
return access === "none" ?
|
|
62802
|
+
return access === "none" ? labels2.noKey : labels2[access];
|
|
61612
62803
|
};
|
|
61613
62804
|
if (list5 !== void 0) {
|
|
61614
62805
|
ctx.io.stdout(m.listHeader(ctx.level.userConfigPath));
|
|
@@ -61630,7 +62821,7 @@ async function listEnabled(ctx) {
|
|
|
61630
62821
|
for (const provider of ctx.registry.list()) {
|
|
61631
62822
|
const access = await providerAccess(ctx.registry, provider);
|
|
61632
62823
|
if (!accessReady(access)) continue;
|
|
61633
|
-
const label2 = access === "none" ?
|
|
62824
|
+
const label2 = access === "none" ? labels2.noKey : labels2[access];
|
|
61634
62825
|
for (const model of provider.models) {
|
|
61635
62826
|
ctx.io.stdout(` ${provider.id}/${model.id} ${label2}
|
|
61636
62827
|
`);
|
|
@@ -63887,19 +65078,19 @@ function redactedLookup(lookup) {
|
|
|
63887
65078
|
}
|
|
63888
65079
|
function axisPoints(trace) {
|
|
63889
65080
|
const t0 = trace.startedAt;
|
|
63890
|
-
const
|
|
65081
|
+
const windows2 = [];
|
|
63891
65082
|
for (const turn of trace.turns) {
|
|
63892
65083
|
const span = turnSpan(turn);
|
|
63893
|
-
if (span !== void 0)
|
|
65084
|
+
if (span !== void 0) windows2.push([span.start - t0, span.end - t0]);
|
|
63894
65085
|
}
|
|
63895
65086
|
for (const aux of trace.aux)
|
|
63896
65087
|
if (aux.startedAt !== void 0)
|
|
63897
|
-
|
|
63898
|
-
|
|
65088
|
+
windows2.push([aux.startedAt - t0, (aux.endedAt ?? aux.startedAt) - t0]);
|
|
65089
|
+
windows2.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
63899
65090
|
const points = [[0, 0]];
|
|
63900
65091
|
let raw = 0;
|
|
63901
65092
|
let mapped = 0;
|
|
63902
|
-
for (const [start, end] of
|
|
65093
|
+
for (const [start, end] of windows2) {
|
|
63903
65094
|
if (end <= raw) continue;
|
|
63904
65095
|
const from = Math.max(start, raw);
|
|
63905
65096
|
if (from > raw) {
|
|
@@ -64384,14 +65575,14 @@ var registeredDeps;
|
|
|
64384
65575
|
function readStdinDefault() {
|
|
64385
65576
|
const stdin = process.stdin;
|
|
64386
65577
|
if (!stdin.isTTY) {
|
|
64387
|
-
return new Promise((
|
|
65578
|
+
return new Promise((resolve39, reject2) => {
|
|
64388
65579
|
const chunks2 = [];
|
|
64389
65580
|
stdin.on("data", (chunk) => chunks2.push(chunk));
|
|
64390
|
-
stdin.once("end", () =>
|
|
65581
|
+
stdin.once("end", () => resolve39(Buffer.concat(chunks2).toString("utf8")));
|
|
64391
65582
|
stdin.once("error", reject2);
|
|
64392
65583
|
});
|
|
64393
65584
|
}
|
|
64394
|
-
return new Promise((
|
|
65585
|
+
return new Promise((resolve39) => {
|
|
64395
65586
|
let line2 = "";
|
|
64396
65587
|
stdin.setRawMode(true);
|
|
64397
65588
|
stdin.resume();
|
|
@@ -64401,14 +65592,14 @@ function readStdinDefault() {
|
|
|
64401
65592
|
stdin.off("data", onData);
|
|
64402
65593
|
stdin.setRawMode(false);
|
|
64403
65594
|
stdin.pause();
|
|
64404
|
-
|
|
65595
|
+
resolve39(line2);
|
|
64405
65596
|
return;
|
|
64406
65597
|
}
|
|
64407
65598
|
if (ch2 === "") {
|
|
64408
65599
|
stdin.off("data", onData);
|
|
64409
65600
|
stdin.setRawMode(false);
|
|
64410
65601
|
stdin.pause();
|
|
64411
|
-
|
|
65602
|
+
resolve39("");
|
|
64412
65603
|
return;
|
|
64413
65604
|
}
|
|
64414
65605
|
if (ch2 === "" || ch2 === "\b") line2 = line2.slice(0, -1);
|
|
@@ -64432,7 +65623,7 @@ function stdinKindDefault() {
|
|
|
64432
65623
|
}
|
|
64433
65624
|
function readStdinFirstByteDefault(timeoutMs) {
|
|
64434
65625
|
const stdin = process.stdin;
|
|
64435
|
-
return new Promise((
|
|
65626
|
+
return new Promise((resolve39, reject2) => {
|
|
64436
65627
|
const chunks2 = [];
|
|
64437
65628
|
let timer;
|
|
64438
65629
|
const cleanup = () => {
|
|
@@ -64448,7 +65639,7 @@ function readStdinFirstByteDefault(timeoutMs) {
|
|
|
64448
65639
|
};
|
|
64449
65640
|
const onEnd = () => {
|
|
64450
65641
|
cleanup();
|
|
64451
|
-
|
|
65642
|
+
resolve39(Buffer.concat(chunks2).toString("utf8"));
|
|
64452
65643
|
};
|
|
64453
65644
|
const onError = (error2) => {
|
|
64454
65645
|
cleanup();
|
|
@@ -64458,7 +65649,7 @@ function readStdinFirstByteDefault(timeoutMs) {
|
|
|
64458
65649
|
cleanup();
|
|
64459
65650
|
stdin.pause();
|
|
64460
65651
|
stdin.destroy();
|
|
64461
|
-
|
|
65652
|
+
resolve39(void 0);
|
|
64462
65653
|
}, timeoutMs);
|
|
64463
65654
|
stdin.on("data", onData);
|
|
64464
65655
|
stdin.once("end", onEnd);
|