@armadra/agent 0.7.1 → 0.7.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 +61 -0
- package/CHANGELOG.zh-CN.md +38 -0
- package/dist/agent/session-cache.d.ts +4 -2
- package/dist/agent/session-cache.js +5 -3
- package/dist/agent/session-compaction.d.ts +19 -1
- package/dist/agent/session-compaction.js +42 -0
- package/dist/agent/session-core.d.ts +2 -0
- package/dist/agent/session-state.d.ts +9 -3
- package/dist/agent/session-state.js +8 -6
- package/dist/agent/session.js +3 -3
- package/dist/agent/types-w5.d.ts +3 -0
- package/dist/agent/types.d.ts +18 -0
- package/dist/agents/task-record.d.ts +4 -0
- package/dist/agents/task-record.js +18 -0
- package/dist/ai/context.d.ts +7 -2
- package/dist/ai/context.js +45 -7
- package/dist/ai/providers/catalog-data.js +1 -1
- package/dist/bundle/ama.cjs +1663 -486
- package/dist/compaction/breakdown.d.ts +51 -0
- package/dist/compaction/breakdown.js +159 -0
- package/dist/compaction/estimate.d.ts +6 -0
- package/dist/compaction/estimate.js +1 -1
- package/dist/compaction/prefix-estimate.d.ts +25 -0
- package/dist/compaction/prefix-estimate.js +38 -0
- package/dist/config/json-schema.js +1 -0
- package/dist/config/key-docs.js +1 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/settings-registry.js +1 -0
- package/dist/config/types.d.ts +2 -0
- package/dist/drivers/native/codex-app-server.js +6 -0
- package/dist/drivers/runner.js +17 -0
- package/dist/drivers/store.d.ts +3 -0
- package/dist/drivers/store.js +4 -0
- package/dist/i18n/catalog.d.ts +55 -0
- package/dist/i18n/messages/agents.d.ts +3 -0
- package/dist/i18n/messages/agents.js +3 -0
- package/dist/i18n/messages/config-keys.d.ts +2 -0
- package/dist/i18n/messages/config-keys.js +2 -0
- package/dist/i18n/messages/config.d.ts +2 -0
- package/dist/i18n/messages/interactive.d.ts +6 -0
- package/dist/i18n/messages/interactive.js +6 -0
- package/dist/i18n/messages/panels.d.ts +3 -0
- package/dist/i18n/messages/panels.js +5 -2
- package/dist/i18n/messages/report-context.d.ts +98 -0
- package/dist/i18n/messages/report-context.js +99 -0
- package/dist/i18n/messages/report.d.ts +100 -0
- package/dist/i18n/messages/report.js +13 -2
- package/dist/i18n/messages/settings.d.ts +2 -0
- package/dist/i18n/messages/settings.js +2 -0
- package/dist/i18n/messages/subcommands.js +2 -2
- package/dist/modes/acp/acp-events.d.ts +17 -4
- package/dist/modes/acp/acp-events.js +32 -6
- package/dist/modes/commands-core.js +4 -0
- package/dist/modes/context-report.d.ts +37 -0
- package/dist/modes/context-report.js +188 -0
- package/dist/modes/interactive/agent-bar.d.ts +2 -0
- package/dist/modes/interactive/agent-bar.js +6 -0
- package/dist/modes/interactive/commands.d.ts +2 -1
- package/dist/modes/interactive/commands.js +10 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode.js +6 -1
- package/dist/modes/interactive/panels.d.ts +2 -1
- package/dist/modes/interactive/panels.js +13 -5
- package/dist/modes/interactive/program-status-ui.d.ts +72 -0
- package/dist/modes/interactive/program-status-ui.js +229 -0
- package/dist/modes/interactive/session-events.d.ts +4 -0
- package/dist/modes/interactive/session-events.js +24 -2
- package/dist/modes/interactive/status-bar.d.ts +21 -3
- package/dist/modes/interactive/status-bar.js +64 -25
- package/dist/modes/interactive/status-ctx.d.ts +55 -0
- package/dist/modes/interactive/status-ctx.js +125 -0
- package/dist/modes/interactive/status-line.d.ts +2 -1
- package/dist/modes/interactive/status-line.js +3 -2
- package/dist/modes/interactive/tasks-report.js +4 -0
- package/dist/modes/print/print-mode.js +12 -0
- package/dist/modes/session-report.d.ts +10 -2
- package/dist/modes/session-report.js +26 -2
- package/dist/sdk.d.ts +1 -1
- package/dist/tools/types.d.ts +6 -0
- package/dist/tui/components/meter.d.ts +2 -0
- package/dist/tui/components/meter.js +1 -1
- package/dist/tui/program-status.d.ts +90 -0
- package/dist/tui/program-status.js +259 -0
- package/docs/acp.md +4 -4
- package/docs/agents.md +1 -1
- package/docs/en/acp.md +4 -4
- package/docs/en/providers.md +5 -3
- package/docs/en/rpc.md +3 -0
- package/docs/en/sessions.md +23 -0
- package/docs/en/tui.md +79 -22
- package/docs/providers.md +8 -5
- package/docs/rpc.md +1 -0
- package/docs/session-format.md +3 -3
- package/docs/sessions.md +22 -0
- package/docs/tui-design.md +2 -2
- package/docs/tui.md +79 -22
- 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.7.
|
|
44
|
+
AMA_VERSION = true ? "0.7.3" : readPackageVersion();
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
@@ -1274,7 +1274,7 @@ Will write ${s2.path}: ${s2.id} new channels ${s2.channels.join(", ") || "none"}
|
|
|
1274
1274
|
cacheProbe: {
|
|
1275
1275
|
adviceSilent: (provider, cacheFieldPresent) => `Set providers.${provider}.compat.cacheReporting: "silent" in config and the status bar will show not reported` + (cacheFieldPresent ? " (the response has cache fields but they stay 0; cache writes may also be delayed, try a larger --gap-ms)" : ""),
|
|
1276
1276
|
adviceInconclusive: "The second request read only a little cache or only wrote: maybe cache granularity or TTL; retry with a larger --tokens or a shorter --gap-ms",
|
|
1277
|
-
advicePromptCache: (provider, id) => `Fill in promptCache
|
|
1277
|
+
advicePromptCache: (provider, id) => `The catalog has no cache lifetime for this model, so ama neither warms it nor prunes early. Fill in promptCache only with a lifetime the upstream documents (providers.${provider}.modelOverrides: [{ "id": "${id}", "promptCache": { "short": <seconds> } }]); a guessed short value fires warming and early pruning while the cache is still valid`,
|
|
1278
1278
|
intAtLeast: (name, min) => `--${name} must be an integer ≥ ${min}`,
|
|
1279
1279
|
yes: "yes",
|
|
1280
1280
|
no: "no",
|
|
@@ -1526,7 +1526,7 @@ Estimated cost: ${estimate} (2 × ${tokens} tokens × catalog price)
|
|
|
1526
1526
|
cacheProbe: {
|
|
1527
1527
|
adviceSilent: (provider, cacheFieldPresent) => `可在 config 里设 providers.${provider}.compat.cacheReporting: "silent",状态栏将显示未报告` + (cacheFieldPresent ? "(响应里有缓存字段但恒为 0;也可能是缓存写入有延迟,可加大 --gap-ms 再测一次)" : ""),
|
|
1528
1528
|
adviceInconclusive: "第二次只读到少量缓存或只有写入:可能是缓存粒度或 TTL 问题,可加大 --tokens 或缩短 --gap-ms 重试",
|
|
1529
|
-
advicePromptCache: (provider, id) =>
|
|
1529
|
+
advicePromptCache: (provider, id) => `目录里没有这个模型的缓存寿命,ama 不保温、也不提前裁剪。只有上游文档写明了寿命时才填 promptCache(providers.${provider}.modelOverrides: [{ "id": "${id}", "promptCache": { "short": <秒数> } }]);猜一个偏短的值会在缓存仍有效时触发保温和提前裁剪`,
|
|
1530
1530
|
intAtLeast: (name, min) => `--${name} 应为不小于 ${min} 的整数`,
|
|
1531
1531
|
yes: "有",
|
|
1532
1532
|
no: "无",
|
|
@@ -1974,6 +1974,10 @@ var init_interactive = __esm({
|
|
|
1974
1974
|
cacheSilent: "n/a",
|
|
1975
1975
|
sandbox: "sandbox",
|
|
1976
1976
|
cycleHint: "shift+tab to cycle",
|
|
1977
|
+
/** full 本行 Ctx 段末尾:自动压缩开着。 */
|
|
1978
|
+
autoCompact: "auto",
|
|
1979
|
+
/** 模型没有上下文窗口(状态栏 `ctx ?`)时提示一次。 */
|
|
1980
|
+
noWindow: (model) => `Context window unknown for ${model}: the status bar shows ctx ? and auto-compaction is off. Run \`ama models discover\` or set contextWindow for this model in the config.`,
|
|
1977
1981
|
/** [W6] 订阅配额行(full 第三行)与窄屏 / compact 短格式;标签自带分隔(英文冒号后空格)。 */
|
|
1978
1982
|
quota: {
|
|
1979
1983
|
session: "Session: ",
|
|
@@ -2105,6 +2109,8 @@ var init_interactive = __esm({
|
|
|
2105
2109
|
cacheSilent: "未报告",
|
|
2106
2110
|
sandbox: "沙箱",
|
|
2107
2111
|
cycleHint: "shift+tab 切换",
|
|
2112
|
+
autoCompact: "auto",
|
|
2113
|
+
noWindow: (model) => `${model} 没有上下文窗口信息:状态栏显示 ctx ?,自动压缩关闭。运行 \`ama models discover\`,或在配置里为该模型设置 contextWindow。`,
|
|
2108
2114
|
quota: {
|
|
2109
2115
|
session: "5 小时:",
|
|
2110
2116
|
reset: "重置:",
|
|
@@ -2604,7 +2610,7 @@ var init_panels = __esm({
|
|
|
2604
2610
|
user: (n) => `user ${n}`,
|
|
2605
2611
|
assistant: (n) => `assistant ${n}`,
|
|
2606
2612
|
toolCalls: (n) => `tool calls ${n}`,
|
|
2607
|
-
usage: "
|
|
2613
|
+
usage: "Total usage",
|
|
2608
2614
|
input: (tokens) => `input ${tokens}`,
|
|
2609
2615
|
output: (tokens) => `output ${tokens}`,
|
|
2610
2616
|
cacheRead: (tokens) => `cache read ${tokens}`,
|
|
@@ -2693,6 +2699,8 @@ var init_panels = __esm({
|
|
|
2693
2699
|
interrupted: "interrupted"
|
|
2694
2700
|
},
|
|
2695
2701
|
turns: (n) => plural(n, "turn"),
|
|
2702
|
+
/** 外部 Agent 报告的上下文占用(`34%`、`0.4%`)。 */
|
|
2703
|
+
context: (percent3) => `ctx ${percent3}`,
|
|
2696
2704
|
agentRunner: (agent, runner) => `${agent} (${runner})`,
|
|
2697
2705
|
background: "background",
|
|
2698
2706
|
none: "No subagent tasks yet",
|
|
@@ -2715,7 +2723,7 @@ var init_panels = __esm({
|
|
|
2715
2723
|
user: (n) => `用户 ${n}`,
|
|
2716
2724
|
assistant: (n) => `助手 ${n}`,
|
|
2717
2725
|
toolCalls: (n) => `工具调用 ${n}`,
|
|
2718
|
-
usage: "
|
|
2726
|
+
usage: "累计用量",
|
|
2719
2727
|
input: (tokens) => `输入 ${tokens}`,
|
|
2720
2728
|
output: (tokens) => `输出 ${tokens}`,
|
|
2721
2729
|
cacheRead: (tokens) => `缓存读 ${tokens}`,
|
|
@@ -2803,6 +2811,7 @@ var init_panels = __esm({
|
|
|
2803
2811
|
interrupted: "已中断"
|
|
2804
2812
|
},
|
|
2805
2813
|
turns: (n) => `${n} 轮`,
|
|
2814
|
+
context: (percent3) => `ctx ${percent3}`,
|
|
2806
2815
|
agentRunner: (agent, runner) => `${agent}(${runner})`,
|
|
2807
2816
|
background: "后台",
|
|
2808
2817
|
none: "还没有子 Agent 任务",
|
|
@@ -2968,13 +2977,115 @@ var init_permissions = __esm({
|
|
|
2968
2977
|
}
|
|
2969
2978
|
});
|
|
2970
2979
|
|
|
2971
|
-
// src/i18n/messages/report.ts
|
|
2980
|
+
// src/i18n/messages/report-context.ts
|
|
2972
2981
|
var en16, zh16;
|
|
2982
|
+
var init_report_context = __esm({
|
|
2983
|
+
"src/i18n/messages/report-context.ts"() {
|
|
2984
|
+
"use strict";
|
|
2985
|
+
init_format();
|
|
2986
|
+
en16 = {
|
|
2987
|
+
title: "Context",
|
|
2988
|
+
keyUsed: "Used",
|
|
2989
|
+
used: (tokens, window2, percent3) => `${tokens} / ${window2}${percent3 !== void 0 ? ` (${percent3})` : ""}`,
|
|
2990
|
+
keyLeft: "Left",
|
|
2991
|
+
left: (tokens) => `${tokens} tokens`,
|
|
2992
|
+
keySource: "Source",
|
|
2993
|
+
sourceUsage: (usage, estimate) => `reported usage ${usage} + estimated ${estimate}`,
|
|
2994
|
+
sourceEstimate: "estimated in full (no usable usage yet)",
|
|
2995
|
+
sourcePrefix: "system prompt and tools only, estimated before the first request",
|
|
2996
|
+
keyAutoCompact: "Auto-compact",
|
|
2997
|
+
autoCompact: (at, distance2) => `at ${at}, ≈ ${distance2} to go`,
|
|
2998
|
+
autoCompactReached: (at) => `at ${at}, reached`,
|
|
2999
|
+
autoCompactOff: "off",
|
|
3000
|
+
windowUnknown: "window unknown",
|
|
3001
|
+
keyPrune: "Pruning",
|
|
3002
|
+
prune: (at) => `old tool results trimmed from ${at}`,
|
|
3003
|
+
breakdown: (total) => `By category (estimated, ${total})`,
|
|
3004
|
+
prefixCounted: "System prompt and tool declarations are counted from the stored system messages; the full estimate can differ from reported usage.",
|
|
3005
|
+
prefixPending: "System prompt and tool declarations are not counted until the first request.",
|
|
3006
|
+
prefixEstimated: "System prompt and tool declarations are estimated from what the first request will send.",
|
|
3007
|
+
categories: {
|
|
3008
|
+
system: "System prompt",
|
|
3009
|
+
tools: "Tool declarations",
|
|
3010
|
+
user: "User messages",
|
|
3011
|
+
assistant: "Assistant text",
|
|
3012
|
+
reasoning: "Reasoning",
|
|
3013
|
+
toolCalls: "Tool-call arguments",
|
|
3014
|
+
toolResults: "Tool results",
|
|
3015
|
+
images: "Images",
|
|
3016
|
+
summaries: "Summaries",
|
|
3017
|
+
custom: "Custom messages"
|
|
3018
|
+
},
|
|
3019
|
+
partNames: {
|
|
3020
|
+
compaction: "compaction",
|
|
3021
|
+
branch: "branch",
|
|
3022
|
+
user: "user",
|
|
3023
|
+
toolResult: "tool result",
|
|
3024
|
+
custom: "custom"
|
|
3025
|
+
},
|
|
3026
|
+
images: (count2) => plural(count2, "image"),
|
|
3027
|
+
more: (count2) => `+${count2} more`,
|
|
3028
|
+
largest: (count2) => `Largest tool results (top ${count2})`,
|
|
3029
|
+
noToolResults: "no tool results",
|
|
3030
|
+
empty: "No messages in the context yet."
|
|
3031
|
+
};
|
|
3032
|
+
zh16 = {
|
|
3033
|
+
title: "上下文",
|
|
3034
|
+
keyUsed: "已用",
|
|
3035
|
+
used: (tokens, window2, percent3) => `${tokens} / ${window2}${percent3 !== void 0 ? `(${percent3})` : ""}`,
|
|
3036
|
+
keyLeft: "剩余",
|
|
3037
|
+
left: (tokens) => `${tokens} token`,
|
|
3038
|
+
keySource: "来源",
|
|
3039
|
+
sourceUsage: (usage, estimate) => `usage 实测 ${usage} + 估算 ${estimate}`,
|
|
3040
|
+
sourceEstimate: "全量估算(还没有可用的 usage)",
|
|
3041
|
+
sourcePrefix: "首次请求前,只有系统提示与工具声明的估算",
|
|
3042
|
+
keyAutoCompact: "自动压缩",
|
|
3043
|
+
autoCompact: (at, distance2) => `${at} 触发,还差 ≈ ${distance2}`,
|
|
3044
|
+
autoCompactReached: (at) => `${at} 触发,已达到`,
|
|
3045
|
+
autoCompactOff: "关闭",
|
|
3046
|
+
windowUnknown: "窗口未知",
|
|
3047
|
+
keyPrune: "裁剪",
|
|
3048
|
+
prune: (at) => `超过 ${at} 时清理旧工具结果`,
|
|
3049
|
+
breakdown: (total) => `按类别(估算,${total})`,
|
|
3050
|
+
prefixCounted: "系统提示与工具声明按会话里存的 system 消息计入;全量估算可能与 usage 实测不同。",
|
|
3051
|
+
prefixPending: "系统提示与工具声明在首次请求后才计入。",
|
|
3052
|
+
prefixEstimated: "系统提示与工具声明按首次请求将要发送的内容估算。",
|
|
3053
|
+
categories: {
|
|
3054
|
+
system: "系统提示",
|
|
3055
|
+
tools: "工具声明",
|
|
3056
|
+
user: "用户消息",
|
|
3057
|
+
assistant: "助手文本",
|
|
3058
|
+
reasoning: "推理",
|
|
3059
|
+
toolCalls: "工具调用参数",
|
|
3060
|
+
toolResults: "工具结果",
|
|
3061
|
+
images: "附件图片",
|
|
3062
|
+
summaries: "摘要",
|
|
3063
|
+
custom: "自定义消息"
|
|
3064
|
+
},
|
|
3065
|
+
partNames: {
|
|
3066
|
+
compaction: "压缩",
|
|
3067
|
+
branch: "分支",
|
|
3068
|
+
user: "用户",
|
|
3069
|
+
toolResult: "工具结果",
|
|
3070
|
+
custom: "自定义"
|
|
3071
|
+
},
|
|
3072
|
+
images: (count2) => `${count2} 张`,
|
|
3073
|
+
more: (count2) => `另有 ${count2} 项`,
|
|
3074
|
+
largest: (count2) => `最大的工具结果(前 ${count2})`,
|
|
3075
|
+
noToolResults: "没有工具结果",
|
|
3076
|
+
empty: "上下文里还没有消息。"
|
|
3077
|
+
};
|
|
3078
|
+
}
|
|
3079
|
+
});
|
|
3080
|
+
|
|
3081
|
+
// src/i18n/messages/report.ts
|
|
3082
|
+
var en17, zh17;
|
|
2973
3083
|
var init_report = __esm({
|
|
2974
3084
|
"src/i18n/messages/report.ts"() {
|
|
2975
3085
|
"use strict";
|
|
2976
3086
|
init_format();
|
|
2977
|
-
|
|
3087
|
+
init_report_context();
|
|
3088
|
+
en17 = {
|
|
2978
3089
|
/** 内置斜杠命令:`args` 只写需要翻译的占位,说明整句。 */
|
|
2979
3090
|
commands: {
|
|
2980
3091
|
help: "List commands",
|
|
@@ -2994,6 +3105,7 @@ var init_report = __esm({
|
|
|
2994
3105
|
tools: "List / set active tools",
|
|
2995
3106
|
hooks: "List loaded hooks",
|
|
2996
3107
|
session: "Session info, usage and cache",
|
|
3108
|
+
context: "Context breakdown by category (estimated), source, window and auto-compact threshold",
|
|
2997
3109
|
cache: "Cache stats; switch warming for this session; print the prefix fingerprint",
|
|
2998
3110
|
statusline: "Footer info two lines / one line (Ctrl+G)",
|
|
2999
3111
|
planArgs: "[goal] | approve [mode|fresh] | reject",
|
|
@@ -3053,6 +3165,8 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3053
3165
|
notDirectory: (path) => `Not a directory: ${path}
|
|
3054
3166
|
`
|
|
3055
3167
|
},
|
|
3168
|
+
/** `/context`:上下文分类明细(report-context.ts)。 */
|
|
3169
|
+
contextReport: en16,
|
|
3056
3170
|
/** `/session`、`/cache` 报告与缓存提示行。 */
|
|
3057
3171
|
cache: {
|
|
3058
3172
|
unreported: "not reported",
|
|
@@ -3153,10 +3267,13 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3153
3267
|
model: (model, thinking, permission) => `${model} · thinking ${thinking} · permission ${permission}`,
|
|
3154
3268
|
keyMessages: "Messages",
|
|
3155
3269
|
messages: (user, assistant, tools) => `user ${user} · assistant ${assistant} · tool calls ${tools}`,
|
|
3156
|
-
keyUsage: "
|
|
3270
|
+
keyUsage: "Total usage",
|
|
3157
3271
|
usage: (input2, output, cacheRead, cacheWrite, cost2) => `input ${input2} · output ${output} · cache read ${cacheRead} · cache write ${cacheWrite} · ${cost2}`,
|
|
3158
3272
|
keyContext: "Context",
|
|
3159
3273
|
context: (tokens, window2, percent3) => `${tokens} / ${window2} (${percent3}%)`,
|
|
3274
|
+
/** 上下文行末尾:距自动压缩(档二)还有多少 token;自动压缩关闭 / 熔断时换成 autoCompactOff。 */
|
|
3275
|
+
toAutoCompact: (tokens) => `≈ ${tokens} until auto-compaction`,
|
|
3276
|
+
autoCompactOff: "auto-compaction off",
|
|
3160
3277
|
keyAgents: "Sub-agents",
|
|
3161
3278
|
externalTitle: "External agents",
|
|
3162
3279
|
noFingerprint: "This session does not provide a prefix fingerprint",
|
|
@@ -3218,7 +3335,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3218
3335
|
userHooks: (path) => `User hooks.json: ${path}`
|
|
3219
3336
|
}
|
|
3220
3337
|
};
|
|
3221
|
-
|
|
3338
|
+
zh17 = {
|
|
3222
3339
|
commands: {
|
|
3223
3340
|
help: "列出命令",
|
|
3224
3341
|
new: "新建会话",
|
|
@@ -3237,6 +3354,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3237
3354
|
tools: "列出 / 设置活动工具",
|
|
3238
3355
|
hooks: "列出已加载的 Hook",
|
|
3239
3356
|
session: "会话信息、用量与缓存",
|
|
3357
|
+
context: "上下文按类别拆分(估算)、来源、窗口与自动压缩阈值",
|
|
3240
3358
|
cache: "缓存统计;切换本会话保温;打印前缀指纹",
|
|
3241
3359
|
statusline: "底部信息行两行 / 一行(Ctrl+G)",
|
|
3242
3360
|
planArgs: "[目标] | approve [模式|fresh] | reject",
|
|
@@ -3294,6 +3412,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3294
3412
|
notDirectory: (path) => `不是目录:${path}
|
|
3295
3413
|
`
|
|
3296
3414
|
},
|
|
3415
|
+
contextReport: zh16,
|
|
3297
3416
|
cache: {
|
|
3298
3417
|
unreported: "未报告",
|
|
3299
3418
|
unknown: "未知",
|
|
@@ -3389,10 +3508,12 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3389
3508
|
model: (model, thinking, permission) => `${model} · 思考 ${thinking} · 权限 ${permission}`,
|
|
3390
3509
|
keyMessages: "消息",
|
|
3391
3510
|
messages: (user, assistant, tools) => `用户 ${user} · 助手 ${assistant} · 工具调用 ${tools}`,
|
|
3392
|
-
keyUsage: "
|
|
3511
|
+
keyUsage: "累计用量",
|
|
3393
3512
|
usage: (input2, output, cacheRead, cacheWrite, cost2) => `输入 ${input2} · 输出 ${output} · 缓存读 ${cacheRead} · 缓存写 ${cacheWrite} · ${cost2}`,
|
|
3394
3513
|
keyContext: "上下文",
|
|
3395
3514
|
context: (tokens, window2, percent3) => `${tokens} / ${window2}(${percent3}%)`,
|
|
3515
|
+
toAutoCompact: (tokens) => `距自动压缩 ≈ ${tokens}`,
|
|
3516
|
+
autoCompactOff: "自动压缩关闭",
|
|
3396
3517
|
keyAgents: "子 Agent",
|
|
3397
3518
|
externalTitle: "外部 Agent",
|
|
3398
3519
|
noFingerprint: "当前会话不提供前缀指纹",
|
|
@@ -3457,12 +3578,12 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3457
3578
|
});
|
|
3458
3579
|
|
|
3459
3580
|
// src/i18n/messages/print.ts
|
|
3460
|
-
var
|
|
3581
|
+
var en18, zh18;
|
|
3461
3582
|
var init_print = __esm({
|
|
3462
3583
|
"src/i18n/messages/print.ts"() {
|
|
3463
3584
|
"use strict";
|
|
3464
3585
|
init_format();
|
|
3465
|
-
|
|
3586
|
+
en18 = {
|
|
3466
3587
|
/** `ama -p` 的 stderr。 */
|
|
3467
3588
|
print: {
|
|
3468
3589
|
stdinIgnored: (wait) => `ama: no piped input within ${wait}, ignored; to wait for it, end the arguments with -
|
|
@@ -3493,7 +3614,7 @@ var init_print = __esm({
|
|
|
3493
3614
|
badMode: (modes) => `mode must be ${modes.join(" | ")}`
|
|
3494
3615
|
}
|
|
3495
3616
|
};
|
|
3496
|
-
|
|
3617
|
+
zh18 = {
|
|
3497
3618
|
print: {
|
|
3498
3619
|
stdinIgnored: (wait) => `ama: 未在 ${wait}内收到管道输入,已忽略;需要等待请在末尾加 -
|
|
3499
3620
|
`,
|
|
@@ -3526,7 +3647,7 @@ var init_print = __esm({
|
|
|
3526
3647
|
});
|
|
3527
3648
|
|
|
3528
3649
|
// src/i18n/messages/config-keys.ts
|
|
3529
|
-
var dynamicDefaultsEn, dynamicDefaultsZh, keysEn, keysZh,
|
|
3650
|
+
var dynamicDefaultsEn, dynamicDefaultsZh, keysEn, keysZh, en19, zh19;
|
|
3530
3651
|
var init_config_keys = __esm({
|
|
3531
3652
|
"src/i18n/messages/config-keys.ts"() {
|
|
3532
3653
|
"use strict";
|
|
@@ -3626,6 +3747,7 @@ var init_config_keys = __esm({
|
|
|
3626
3747
|
"ui.animation": "false: the spinner stays still while running and redraws only when seconds change; the startup logo does not animate",
|
|
3627
3748
|
"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",
|
|
3628
3749
|
"ui.enterWhileRunning": "Enter while a run is in progress: queue (default) queues the message as a steer delivered at the next delivery point; interrupt stops the current turn and sends it at once. The app.message.interrupt key (default Ctrl+X) does the other one",
|
|
3750
|
+
"ui.programStatus": "Report run state to the terminal with OSC 7501 (idle / working / blocked / done / error): auto (default) sends only after the terminal answers the detection query (off inside tmux), on sends without detecting (inside tmux wrapped in passthrough; needs allow-passthrough on), off never sends. Interactive TUI only",
|
|
3629
3751
|
"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)",
|
|
3630
3752
|
"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",
|
|
3631
3753
|
"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)",
|
|
@@ -3749,6 +3871,7 @@ var init_config_keys = __esm({
|
|
|
3749
3871
|
"ui.animation": "false:运行中 spinner 静止,只在秒数变化时重绘;启动字符画不播放动画",
|
|
3750
3872
|
"ui.restoreOnCancel": "运行中 Esc 中断、本回合还没有任何回复或工具调用时,撤回该回合并把原消息放回输入框",
|
|
3751
3873
|
"ui.enterWhileRunning": "运行中按 Enter:queue(缺省)排队插话,等下一个投递点送达;interrupt 打断当前回合并立即发送。app.message.interrupt 键(缺省 Ctrl+X)做另一种",
|
|
3874
|
+
"ui.programStatus": "用 OSC 7501 把运行状态报告给终端(idle / working / blocked / done / error):auto(缺省)终端回应检测查询后才发(tmux 里不发),on 不检测直接发(tmux 里经 passthrough 包裹,需要 allow-passthrough on),off 不发。只用于交互界面",
|
|
3752
3875
|
"ui.statusLine": "底部信息行:full 两行(速率行 + 状态行),compact 一行;运行时 Ctrl+G 或 /statusline 切换(第五波 W5-A 起生效)",
|
|
3753
3876
|
"ui.language": "界面语言:auto 按 LC_ALL / LC_MESSAGES / LANG 判断(zh* 为中文,其余英文),zh,en;AMA_LANG、--lang 覆盖;只影响界面,发给模型的文本固定英文",
|
|
3754
3877
|
"ui.replyLanguage": "模型回复语言(如 Chinese):会话开始在 rules 节末尾追加一句英文规则;不设时零字节变化;只认用户级(第六波起生效)",
|
|
@@ -3822,8 +3945,8 @@ var init_config_keys = __esm({
|
|
|
3822
3945
|
todo: "todo 工具;只认用户级(第五波 W5-F / W5-H2 起生效)",
|
|
3823
3946
|
"todo.reminder": "连续 N 回合未更新且有未完成项时提醒复述;0 关闭"
|
|
3824
3947
|
};
|
|
3825
|
-
|
|
3826
|
-
|
|
3948
|
+
en19 = { keys: keysEn, dynamicDefaults: dynamicDefaultsEn };
|
|
3949
|
+
zh19 = {
|
|
3827
3950
|
keys: keysZh,
|
|
3828
3951
|
dynamicDefaults: dynamicDefaultsZh
|
|
3829
3952
|
};
|
|
@@ -3831,12 +3954,12 @@ var init_config_keys = __esm({
|
|
|
3831
3954
|
});
|
|
3832
3955
|
|
|
3833
3956
|
// src/i18n/messages/config.ts
|
|
3834
|
-
var
|
|
3957
|
+
var en20, zh20;
|
|
3835
3958
|
var init_config = __esm({
|
|
3836
3959
|
"src/i18n/messages/config.ts"() {
|
|
3837
3960
|
"use strict";
|
|
3838
3961
|
init_config_keys();
|
|
3839
|
-
|
|
3962
|
+
en20 = {
|
|
3840
3963
|
/** 配置校验诊断(checker.ts、schema.ts、schema-w5.ts、schema-w6.ts)。 */
|
|
3841
3964
|
schema: {
|
|
3842
3965
|
enumArray: (choices) => `should be an array of ${choices.join(" | ")}`,
|
|
@@ -3957,9 +4080,9 @@ var init_config = __esm({
|
|
|
3957
4080
|
models: "Custom models (an entry with the same id replaces the whole model)",
|
|
3958
4081
|
modelOverrides: "Only changes metadata of existing models"
|
|
3959
4082
|
},
|
|
3960
|
-
...
|
|
4083
|
+
...en19
|
|
3961
4084
|
};
|
|
3962
|
-
|
|
4085
|
+
zh20 = {
|
|
3963
4086
|
schema: {
|
|
3964
4087
|
enumArray: (choices) => `应为 ${choices.join(" | ")} 组成的数组`,
|
|
3965
4088
|
ports: "应为端口号数组(0–65535;0 = 任意空闲端口)",
|
|
@@ -4071,18 +4194,18 @@ var init_config = __esm({
|
|
|
4071
4194
|
models: "自定义模型(同 id 整条替换)",
|
|
4072
4195
|
modelOverrides: "只改已有模型的元数据"
|
|
4073
4196
|
},
|
|
4074
|
-
...
|
|
4197
|
+
...zh19
|
|
4075
4198
|
};
|
|
4076
4199
|
}
|
|
4077
4200
|
});
|
|
4078
4201
|
|
|
4079
4202
|
// src/i18n/messages/drivers.ts
|
|
4080
|
-
var
|
|
4203
|
+
var en21, zh21;
|
|
4081
4204
|
var init_drivers = __esm({
|
|
4082
4205
|
"src/i18n/messages/drivers.ts"() {
|
|
4083
4206
|
"use strict";
|
|
4084
4207
|
init_format();
|
|
4085
|
-
|
|
4208
|
+
en21 = {
|
|
4086
4209
|
/** 外部 Agent 的 notice 与日志。 */
|
|
4087
4210
|
agent: {
|
|
4088
4211
|
reapedOrphans: (pids) => `cleaned up external agent processes left over from last time: ${pids}`,
|
|
@@ -4142,7 +4265,7 @@ var init_drivers = __esm({
|
|
|
4142
4265
|
noId: (label2) => `${label2}: the adapter returned by create() has no id`
|
|
4143
4266
|
}
|
|
4144
4267
|
};
|
|
4145
|
-
|
|
4268
|
+
zh21 = {
|
|
4146
4269
|
agent: {
|
|
4147
4270
|
reapedOrphans: (pids) => `清理了上次遗留的外部 Agent 进程:${pids}`,
|
|
4148
4271
|
unverifiedVersion: (program, version, verified) => `${program} ${version} 不在已验证区间 ${verified},协议可能有变化`,
|
|
@@ -4203,12 +4326,12 @@ var init_drivers = __esm({
|
|
|
4203
4326
|
});
|
|
4204
4327
|
|
|
4205
4328
|
// src/i18n/messages/session.ts
|
|
4206
|
-
var
|
|
4329
|
+
var en22, zh22;
|
|
4207
4330
|
var init_session = __esm({
|
|
4208
4331
|
"src/i18n/messages/session.ts"() {
|
|
4209
4332
|
"use strict";
|
|
4210
4333
|
init_format();
|
|
4211
|
-
|
|
4334
|
+
en22 = {
|
|
4212
4335
|
/** `ama sessions list / show / prune`(search / export / trace 各有自己的文案)。 */
|
|
4213
4336
|
cli: {
|
|
4214
4337
|
usage: `Usage: ama sessions list [--all] [--session-dir <dir>]
|
|
@@ -4344,7 +4467,7 @@ var init_session = __esm({
|
|
|
4344
4467
|
}
|
|
4345
4468
|
}
|
|
4346
4469
|
};
|
|
4347
|
-
|
|
4470
|
+
zh22 = {
|
|
4348
4471
|
cli: {
|
|
4349
4472
|
usage: `用法:ama sessions list [--all] [--session-dir <目录>]
|
|
4350
4473
|
ama sessions show <id> [--session-dir <目录>]
|
|
@@ -4477,7 +4600,7 @@ var init_session = __esm({
|
|
|
4477
4600
|
});
|
|
4478
4601
|
|
|
4479
4602
|
// src/i18n/messages/errors.ts
|
|
4480
|
-
var EN_HINT, ZH_HINT,
|
|
4603
|
+
var EN_HINT, ZH_HINT, en23, zh23;
|
|
4481
4604
|
var init_errors2 = __esm({
|
|
4482
4605
|
"src/i18n/messages/errors.ts"() {
|
|
4483
4606
|
"use strict";
|
|
@@ -4492,7 +4615,7 @@ var init_errors2 = __esm({
|
|
|
4492
4615
|
no_tool: "(没找到缩放工具:装 ImageMagick,macOS 自带 sips)",
|
|
4493
4616
|
still_too_large: "(缩放后仍超限)"
|
|
4494
4617
|
};
|
|
4495
|
-
|
|
4618
|
+
en23 = {
|
|
4496
4619
|
/** [W6-I3] 图片附件:当前模型不收图片(`--image` / `@路径`)。 */
|
|
4497
4620
|
imageUnsupported: (model) => `${model ?? "The current model"} does not accept image input (the model's input has no image); switch to a model that supports images (marked "image" in ama models list, or give the model "input": ["text", "image"] in the config)`,
|
|
4498
4621
|
/** [W6-I3] SDK(`createRuntime` / `createAgentSession`)。 */
|
|
@@ -4564,7 +4687,7 @@ var init_errors2 = __esm({
|
|
|
4564
4687
|
}
|
|
4565
4688
|
}
|
|
4566
4689
|
};
|
|
4567
|
-
|
|
4690
|
+
zh23 = {
|
|
4568
4691
|
imageUnsupported: (model) => `${model ?? "当前模型"} 不接受图片输入(模型 input 没有 image);换一个支持图像的模型再试(ama models list 里标「图片」的,或在配置里给该模型写 "input": ["text", "image"])`,
|
|
4569
4692
|
cacheParamsStripped: (key, field2, suggestion) => `${key}:该端点不支持 ${field2},已自动去掉缓存参数重发;可在 config 里设 ${suggestion ?? "相应的 compat 开关"}`,
|
|
4570
4693
|
sdk: {
|
|
@@ -4635,12 +4758,12 @@ var init_errors2 = __esm({
|
|
|
4635
4758
|
});
|
|
4636
4759
|
|
|
4637
4760
|
// src/i18n/messages/agents.ts
|
|
4638
|
-
var
|
|
4761
|
+
var en24, zh24;
|
|
4639
4762
|
var init_agents = __esm({
|
|
4640
4763
|
"src/i18n/messages/agents.ts"() {
|
|
4641
4764
|
"use strict";
|
|
4642
4765
|
init_format();
|
|
4643
|
-
|
|
4766
|
+
en24 = {
|
|
4644
4767
|
status: {
|
|
4645
4768
|
queued: "queued",
|
|
4646
4769
|
running: "running",
|
|
@@ -4652,6 +4775,8 @@ var init_agents = __esm({
|
|
|
4652
4775
|
interrupted: "interrupted"
|
|
4653
4776
|
},
|
|
4654
4777
|
turns: (n) => plural(n, "turn"),
|
|
4778
|
+
/** 外部 Agent 报告的上下文占用(`34%`、`0.4%`)。 */
|
|
4779
|
+
context: (percent3) => `ctx ${percent3}`,
|
|
4655
4780
|
bar: {
|
|
4656
4781
|
more: (n) => `${n} more`,
|
|
4657
4782
|
keys: (up, down) => `${up}${down} select · Enter open · Esc back`,
|
|
@@ -4710,7 +4835,7 @@ var init_agents = __esm({
|
|
|
4710
4835
|
externalNoSession: (runner) => `Live output is kept only in memory; ${runner} did not report a session to resume.`
|
|
4711
4836
|
}
|
|
4712
4837
|
};
|
|
4713
|
-
|
|
4838
|
+
zh24 = {
|
|
4714
4839
|
status: {
|
|
4715
4840
|
queued: "排队",
|
|
4716
4841
|
running: "运行中",
|
|
@@ -4722,6 +4847,7 @@ var init_agents = __esm({
|
|
|
4722
4847
|
interrupted: "已中断"
|
|
4723
4848
|
},
|
|
4724
4849
|
turns: (n) => `${n} 轮`,
|
|
4850
|
+
context: (percent3) => `ctx ${percent3}`,
|
|
4725
4851
|
bar: {
|
|
4726
4852
|
more: (n) => `另 ${n} 个`,
|
|
4727
4853
|
keys: (up, down) => `${up}${down} 选择 · Enter 打开 · Esc 返回`,
|
|
@@ -4778,12 +4904,12 @@ var init_agents = __esm({
|
|
|
4778
4904
|
});
|
|
4779
4905
|
|
|
4780
4906
|
// src/i18n/messages/trace.ts
|
|
4781
|
-
var
|
|
4907
|
+
var en25, zh25;
|
|
4782
4908
|
var init_trace = __esm({
|
|
4783
4909
|
"src/i18n/messages/trace.ts"() {
|
|
4784
4910
|
"use strict";
|
|
4785
4911
|
init_format();
|
|
4786
|
-
|
|
4912
|
+
en25 = {
|
|
4787
4913
|
title: "Trace",
|
|
4788
4914
|
/** 顶部汇总行。 */
|
|
4789
4915
|
summary: (turns, requests, tools) => `${plural(turns, "turn")} · ${plural(requests, "request")} · ${plural(tools, "tool call")}`,
|
|
@@ -4902,7 +5028,7 @@ var init_trace = __esm({
|
|
|
4902
5028
|
badNow: (raw) => `--now expects epoch milliseconds (got ${raw})`
|
|
4903
5029
|
}
|
|
4904
5030
|
};
|
|
4905
|
-
|
|
5031
|
+
zh25 = {
|
|
4906
5032
|
title: "轨迹",
|
|
4907
5033
|
summary: (turns, requests, tools) => `${turns} 回合 · ${requests} 请求 · ${tools} 次工具`,
|
|
4908
5034
|
cache: (percent3) => `缓存 ${percent3}`,
|
|
@@ -5021,12 +5147,12 @@ var init_trace = __esm({
|
|
|
5021
5147
|
});
|
|
5022
5148
|
|
|
5023
5149
|
// src/i18n/messages/memory.ts
|
|
5024
|
-
var
|
|
5150
|
+
var en26, zh26;
|
|
5025
5151
|
var init_memory = __esm({
|
|
5026
5152
|
"src/i18n/messages/memory.ts"() {
|
|
5027
5153
|
"use strict";
|
|
5028
5154
|
init_format();
|
|
5029
|
-
|
|
5155
|
+
en26 = {
|
|
5030
5156
|
scope: { user: "user", project: "project", workspace: "workspace" },
|
|
5031
5157
|
panel: {
|
|
5032
5158
|
title: "Memory",
|
|
@@ -5086,7 +5212,7 @@ var init_memory = __esm({
|
|
|
5086
5212
|
untrusted: (cwd) => `Project scope skipped: ${cwd} is not trusted (run ama --trust there once).`
|
|
5087
5213
|
}
|
|
5088
5214
|
};
|
|
5089
|
-
|
|
5215
|
+
zh26 = {
|
|
5090
5216
|
scope: { user: "用户", project: "项目", workspace: "工作空间" },
|
|
5091
5217
|
panel: {
|
|
5092
5218
|
title: "记忆",
|
|
@@ -5150,11 +5276,11 @@ var init_memory = __esm({
|
|
|
5150
5276
|
});
|
|
5151
5277
|
|
|
5152
5278
|
// src/i18n/messages/auth.ts
|
|
5153
|
-
var
|
|
5279
|
+
var en27, zh27;
|
|
5154
5280
|
var init_auth = __esm({
|
|
5155
5281
|
"src/i18n/messages/auth.ts"() {
|
|
5156
5282
|
"use strict";
|
|
5157
|
-
|
|
5283
|
+
en27 = {
|
|
5158
5284
|
usage: `Usage: ama auth set [<provider>] [--auth-file <file>] read the key from stdin (no provider on a TTY: pick one)
|
|
5159
5285
|
ama auth list [--auth-file <file>]
|
|
5160
5286
|
ama auth remove <provider> [--auth-file <file>]
|
|
@@ -5262,7 +5388,7 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
|
|
|
5262
5388
|
relogin: (provider) => `${provider}: sign-in expired, run ama auth login ${provider}`
|
|
5263
5389
|
}
|
|
5264
5390
|
};
|
|
5265
|
-
|
|
5391
|
+
zh27 = {
|
|
5266
5392
|
usage: `用法:ama auth set [<provider>] [--auth-file <文件>] 从 stdin 读取 key(TTY 下不给供应商则先选)
|
|
5267
5393
|
ama auth list [--auth-file <文件>]
|
|
5268
5394
|
ama auth remove <provider> [--auth-file <文件>]
|
|
@@ -5374,11 +5500,11 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
|
|
|
5374
5500
|
});
|
|
5375
5501
|
|
|
5376
5502
|
// src/i18n/messages/settings.ts
|
|
5377
|
-
var
|
|
5503
|
+
var en28, zh28;
|
|
5378
5504
|
var init_settings = __esm({
|
|
5379
5505
|
"src/i18n/messages/settings.ts"() {
|
|
5380
5506
|
"use strict";
|
|
5381
|
-
|
|
5507
|
+
en28 = {
|
|
5382
5508
|
groups: {
|
|
5383
5509
|
ui: "Interface",
|
|
5384
5510
|
model: "Model",
|
|
@@ -5402,6 +5528,7 @@ var init_settings = __esm({
|
|
|
5402
5528
|
"ui.statusLine": "Status line",
|
|
5403
5529
|
"ui.restoreOnCancel": "Restore on cancel",
|
|
5404
5530
|
"ui.enterWhileRunning": "Enter while running",
|
|
5531
|
+
"ui.programStatus": "Terminal program status",
|
|
5405
5532
|
"ui.quietStartup": "Startup screen",
|
|
5406
5533
|
"ui.ascii": "ASCII glyphs",
|
|
5407
5534
|
"ui.language": "Interface language",
|
|
@@ -5551,7 +5678,7 @@ var init_settings = __esm({
|
|
|
5551
5678
|
missingValue: "missing <value>"
|
|
5552
5679
|
}
|
|
5553
5680
|
};
|
|
5554
|
-
|
|
5681
|
+
zh28 = {
|
|
5555
5682
|
groups: {
|
|
5556
5683
|
ui: "界面",
|
|
5557
5684
|
model: "模型",
|
|
@@ -5574,6 +5701,7 @@ var init_settings = __esm({
|
|
|
5574
5701
|
"ui.statusLine": "底部信息行",
|
|
5575
5702
|
"ui.restoreOnCancel": "中断后放回原消息",
|
|
5576
5703
|
"ui.enterWhileRunning": "运行中按 Enter",
|
|
5704
|
+
"ui.programStatus": "终端程序状态",
|
|
5577
5705
|
"ui.quietStartup": "启动画面",
|
|
5578
5706
|
"ui.ascii": "ASCII 字形",
|
|
5579
5707
|
"ui.language": "界面语言",
|
|
@@ -5726,12 +5854,12 @@ var init_settings = __esm({
|
|
|
5726
5854
|
});
|
|
5727
5855
|
|
|
5728
5856
|
// src/i18n/messages/acp.ts
|
|
5729
|
-
var
|
|
5857
|
+
var en29, zh29;
|
|
5730
5858
|
var init_acp = __esm({
|
|
5731
5859
|
"src/i18n/messages/acp.ts"() {
|
|
5732
5860
|
"use strict";
|
|
5733
5861
|
init_format();
|
|
5734
|
-
|
|
5862
|
+
en29 = {
|
|
5735
5863
|
/** ACP 服务端(`ama --mode acp`)的现有文案。 */
|
|
5736
5864
|
core: {
|
|
5737
5865
|
missingParam: (key) => `missing ${key}`,
|
|
@@ -5793,7 +5921,7 @@ var init_acp = __esm({
|
|
|
5793
5921
|
authTerminal: (name, command3) => `${name} (run in a terminal: ${command3})`
|
|
5794
5922
|
}
|
|
5795
5923
|
};
|
|
5796
|
-
|
|
5924
|
+
zh29 = {
|
|
5797
5925
|
core: {
|
|
5798
5926
|
missingParam: (key) => `缺少 ${key}`,
|
|
5799
5927
|
promptNotArray: "prompt 应为内容块数组",
|
|
@@ -5852,7 +5980,7 @@ var init_acp = __esm({
|
|
|
5852
5980
|
});
|
|
5853
5981
|
|
|
5854
5982
|
// src/i18n/catalog.ts
|
|
5855
|
-
var
|
|
5983
|
+
var en30, zh30, CATALOGS, MESSAGE_DOMAINS;
|
|
5856
5984
|
var init_catalog = __esm({
|
|
5857
5985
|
"src/i18n/catalog.ts"() {
|
|
5858
5986
|
"use strict";
|
|
@@ -5876,7 +6004,7 @@ var init_catalog = __esm({
|
|
|
5876
6004
|
init_auth();
|
|
5877
6005
|
init_settings();
|
|
5878
6006
|
init_acp();
|
|
5879
|
-
|
|
6007
|
+
en30 = {
|
|
5880
6008
|
cli: en3,
|
|
5881
6009
|
subcommands: en6,
|
|
5882
6010
|
interactive: en10,
|
|
@@ -5885,20 +6013,20 @@ var init_catalog = __esm({
|
|
|
5885
6013
|
rewind: en13,
|
|
5886
6014
|
panels: en14,
|
|
5887
6015
|
permissions: en15,
|
|
5888
|
-
report:
|
|
5889
|
-
print:
|
|
5890
|
-
config:
|
|
5891
|
-
drivers:
|
|
5892
|
-
session:
|
|
5893
|
-
errors:
|
|
5894
|
-
agents:
|
|
5895
|
-
trace:
|
|
5896
|
-
memory:
|
|
5897
|
-
auth:
|
|
5898
|
-
settings:
|
|
5899
|
-
acp:
|
|
6016
|
+
report: en17,
|
|
6017
|
+
print: en18,
|
|
6018
|
+
config: en20,
|
|
6019
|
+
drivers: en21,
|
|
6020
|
+
session: en22,
|
|
6021
|
+
errors: en23,
|
|
6022
|
+
agents: en24,
|
|
6023
|
+
trace: en25,
|
|
6024
|
+
memory: en26,
|
|
6025
|
+
auth: en27,
|
|
6026
|
+
settings: en28,
|
|
6027
|
+
acp: en29
|
|
5900
6028
|
};
|
|
5901
|
-
|
|
6029
|
+
zh30 = {
|
|
5902
6030
|
cli: zh3,
|
|
5903
6031
|
subcommands: zh6,
|
|
5904
6032
|
interactive: zh10,
|
|
@@ -5907,21 +6035,21 @@ var init_catalog = __esm({
|
|
|
5907
6035
|
rewind: zh13,
|
|
5908
6036
|
panels: zh14,
|
|
5909
6037
|
permissions: zh15,
|
|
5910
|
-
report:
|
|
5911
|
-
print:
|
|
5912
|
-
config:
|
|
5913
|
-
drivers:
|
|
5914
|
-
session:
|
|
5915
|
-
errors:
|
|
5916
|
-
agents:
|
|
5917
|
-
trace:
|
|
5918
|
-
memory:
|
|
5919
|
-
auth:
|
|
5920
|
-
settings:
|
|
5921
|
-
acp:
|
|
6038
|
+
report: zh17,
|
|
6039
|
+
print: zh18,
|
|
6040
|
+
config: zh20,
|
|
6041
|
+
drivers: zh21,
|
|
6042
|
+
session: zh22,
|
|
6043
|
+
errors: zh23,
|
|
6044
|
+
agents: zh24,
|
|
6045
|
+
trace: zh25,
|
|
6046
|
+
memory: zh26,
|
|
6047
|
+
auth: zh27,
|
|
6048
|
+
settings: zh28,
|
|
6049
|
+
acp: zh29
|
|
5922
6050
|
};
|
|
5923
|
-
CATALOGS = { en:
|
|
5924
|
-
MESSAGE_DOMAINS = Object.keys(
|
|
6051
|
+
CATALOGS = { en: en30, zh: zh30 };
|
|
6052
|
+
MESSAGE_DOMAINS = Object.keys(en30);
|
|
5925
6053
|
}
|
|
5926
6054
|
});
|
|
5927
6055
|
|
|
@@ -7300,6 +7428,7 @@ function validateConfig(value) {
|
|
|
7300
7428
|
"animation",
|
|
7301
7429
|
"restoreOnCancel",
|
|
7302
7430
|
"enterWhileRunning",
|
|
7431
|
+
"programStatus",
|
|
7303
7432
|
...W5_UI_KEYS,
|
|
7304
7433
|
...W6_UI_KEYS
|
|
7305
7434
|
],
|
|
@@ -7315,6 +7444,7 @@ function validateConfig(value) {
|
|
|
7315
7444
|
c.boolean(s2, "animation", p);
|
|
7316
7445
|
c.boolean(s2, "restoreOnCancel", p);
|
|
7317
7446
|
c.oneOf(s2, "enterWhileRunning", p, ["queue", "interrupt"]);
|
|
7447
|
+
c.oneOf(s2, "programStatus", p, ["auto", "on", "off"]);
|
|
7318
7448
|
checkUiW5(c, s2, p);
|
|
7319
7449
|
checkUiW6(c, s2, p);
|
|
7320
7450
|
}
|
|
@@ -10993,7 +11123,7 @@ var init_catalog_data = __esm({
|
|
|
10993
11123
|
anthropic: '{"version":1,"provider":"anthropic","modelsDev":"anthropic","models":[{"id":"claude-fable-5-1","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-fable-5","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5-5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-8","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-7","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":2048},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-6","promptCache":{"short":300,"long":3600,"minTokens":4096},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5-5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-6","promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-5","promptCache":{"short":300,"long":3600,"minTokens":1024}},{"id":"claude-haiku-4-5","promptCache":{"short":300,"long":3600,"minTokens":4096}},{"id":"claude-opus-4-5","promptCache":{"short":300,"long":3600,"minTokens":4096}}]}',
|
|
10994
11124
|
chatgpt: '{"version":1,"provider":"chatgpt","modelsDev":false,"models":[]}',
|
|
10995
11125
|
dashscope: '{"version":1,"provider":"dashscope","modelsDev":"alibaba-cn","models":[{"id":"qwen3.8-max","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.8-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.7-max","maxTokens":131072,"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.7-plus","maxTokens":65536,"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-plus","compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-flash","compat":{"supportsReasoningEffort":false}}]}',
|
|
10996
|
-
deepseek: '{"version":1,"provider":"deepseek","modelsDev":"deepseek","models":[{"id":"deepseek-v4-pro","maxTokens":384000,"cost":{"input":1.32,"output":3.96,"cacheRead":0.044},"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价"},{"id":"deepseek-flash","maxTokens":384000,"cost":{"input":0.3,"output":1.2,"cacheRead":0.006},"thinkingLevelMap":{"minimal":null,"low":"low","medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价"}]}',
|
|
11126
|
+
deepseek: '{"version":1,"provider":"deepseek","modelsDev":"deepseek","models":[{"id":"deepseek-v4-pro","maxTokens":384000,"cost":{"input":1.32,"output":3.96,"cacheRead":0.044},"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价","promptCache":{"short":3600,"minTokens":2048}},{"id":"deepseek-flash","maxTokens":384000,"cost":{"input":0.3,"output":1.2,"cacheRead":0.006},"thinkingLevelMap":{"minimal":null,"low":"low","medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价","promptCache":{"short":3600,"minTokens":2048}}]}',
|
|
10997
11127
|
google: '{"version":1,"provider":"google","modelsDev":"google","models":[{"id":"gemini-3.8-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.7-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash-lite","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.1-pro-preview","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3-flash-preview","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-2.5-pro","thinkingLevelMap":{"off":null,"minimal":128,"low":2048,"medium":8192,"high":32768}},{"id":"gemini-2.5-flash","thinkingLevelMap":{"minimal":128,"low":2048,"medium":8192,"high":24576}},{"id":"gemini-2.5-flash-lite","thinkingLevelMap":{"minimal":512,"low":2048,"medium":8192,"high":24576}}]}',
|
|
10998
11128
|
groq: '{"version":1,"provider":"groq","modelsDev":"groq","models":[{"id":"openai/gpt-oss-120b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-20b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-safeguard-20b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.8-27b","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.6-27b","thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"default","xhigh":null}},{"id":"llama-3.3-70b-versatile"},{"id":"llama-3.1-8b-instant"}]}',
|
|
10999
11129
|
lmstudio: '{"version":1,"provider":"lmstudio","modelsDev":false,"models":[]}',
|
|
@@ -12532,14 +12662,48 @@ function allowsImages(options) {
|
|
|
12532
12662
|
return options?.model === void 0 || options.model.input.includes("image");
|
|
12533
12663
|
}
|
|
12534
12664
|
function normalizeContext(context, options) {
|
|
12535
|
-
const
|
|
12665
|
+
const head = new SystemState();
|
|
12666
|
+
const tools = new SystemState();
|
|
12536
12667
|
const messages = [];
|
|
12537
12668
|
const allowImages = allowsImages(options);
|
|
12669
|
+
const fold = removesToolsMidway(context.messages);
|
|
12670
|
+
let pending = [];
|
|
12671
|
+
const flush = () => {
|
|
12672
|
+
if (pending.length === 0) return;
|
|
12673
|
+
messages.push({ role: "user", content: systemReminderText(pending), timestamp: 0 });
|
|
12674
|
+
pending = [];
|
|
12675
|
+
};
|
|
12538
12676
|
for (const message of context.messages) {
|
|
12539
|
-
if (message.role
|
|
12540
|
-
|
|
12677
|
+
if (message.role !== "system") {
|
|
12678
|
+
flush();
|
|
12679
|
+
messages.push(filterMessage(message, allowImages));
|
|
12680
|
+
continue;
|
|
12681
|
+
}
|
|
12682
|
+
tools.apply(message);
|
|
12683
|
+
if (fold || messages.length === 0) {
|
|
12684
|
+
head.apply(message);
|
|
12685
|
+
continue;
|
|
12686
|
+
}
|
|
12687
|
+
const text = renderSystemUpdate(message);
|
|
12688
|
+
if (text.length > 0) pending.push(text);
|
|
12541
12689
|
}
|
|
12542
|
-
|
|
12690
|
+
flush();
|
|
12691
|
+
return { ...head.snapshot(), tools: tools.snapshot().tools, messages };
|
|
12692
|
+
}
|
|
12693
|
+
function removesToolsMidway(transcript) {
|
|
12694
|
+
let started = false;
|
|
12695
|
+
for (const message of transcript) {
|
|
12696
|
+
if (message.role !== "system") started = true;
|
|
12697
|
+
else if (started && (message.toolsRemoved?.length ?? 0) > 0) return true;
|
|
12698
|
+
}
|
|
12699
|
+
return false;
|
|
12700
|
+
}
|
|
12701
|
+
function systemReminderText(updates) {
|
|
12702
|
+
return `<system-reminder>
|
|
12703
|
+
${updates.join("\n\n")}
|
|
12704
|
+
|
|
12705
|
+
These updates replace the earlier versions of those system prompt sections.
|
|
12706
|
+
</system-reminder>`;
|
|
12543
12707
|
}
|
|
12544
12708
|
function renderSystemUpdate(message) {
|
|
12545
12709
|
const parts = [];
|
|
@@ -21588,8 +21752,10 @@ var init_session_cache = __esm({
|
|
|
21588
21752
|
return stats;
|
|
21589
21753
|
}
|
|
21590
21754
|
/**
|
|
21591
|
-
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3
|
|
21592
|
-
*
|
|
21755
|
+
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3):上一次请求(含保温)距今超过目录承诺的 TTL。
|
|
21756
|
+
* 目录没有承诺 TTL 时返回 false:隐式缓存的寿命可能远长于 10 分钟,按猜测的寿命提前裁剪会改写
|
|
21757
|
+
* 仍然有效的缓存(隐式 600 s 只用于未命中归因)。只对 `reported` 端点判断;`silent` / `unknown`
|
|
21758
|
+
* 返回 false,档一退化为只按阈值。
|
|
21593
21759
|
*/
|
|
21594
21760
|
isCold() {
|
|
21595
21761
|
const prev = this.prev;
|
|
@@ -21598,7 +21764,7 @@ var init_session_cache = __esm({
|
|
|
21598
21764
|
const endpoint = endpointKey({ model, baseUrl: model.baseUrl ?? "" });
|
|
21599
21765
|
if (this.tracker.get(endpoint, model.compat?.cacheReporting) !== "reported") return false;
|
|
21600
21766
|
const ttl = cacheTtlMs(this.modelOf(prev), prev.options.cacheRetention);
|
|
21601
|
-
return this.now() - prev.at >
|
|
21767
|
+
return ttl !== void 0 && this.now() - prev.at > ttl;
|
|
21602
21768
|
}
|
|
21603
21769
|
/**
|
|
21604
21770
|
* 摘要续写的前缀(第三波 §1.8):当前转录按回合同样的方式转换,且上一次 turn 请求的消息
|
|
@@ -21888,6 +22054,29 @@ var init_breaker = __esm({
|
|
|
21888
22054
|
}
|
|
21889
22055
|
});
|
|
21890
22056
|
|
|
22057
|
+
// src/compaction/prefix-estimate.ts
|
|
22058
|
+
function prefixSystemMessage(sections, tools) {
|
|
22059
|
+
const message = { role: "system", sections: { ...sections }, timestamp: 0 };
|
|
22060
|
+
if (tools.length > 0) message.toolsAdded = [...tools];
|
|
22061
|
+
return message;
|
|
22062
|
+
}
|
|
22063
|
+
function withPrefixBaseline(estimate, hasSystemMessage, prefix) {
|
|
22064
|
+
if (estimate.usageTokens > 0) return { ...estimate, source: "usage" };
|
|
22065
|
+
if (hasSystemMessage) return { ...estimate, source: "estimate" };
|
|
22066
|
+
const base4 = prefix();
|
|
22067
|
+
return {
|
|
22068
|
+
...estimate,
|
|
22069
|
+
tokens: estimate.tokens + base4,
|
|
22070
|
+
trailingTokens: estimate.trailingTokens + base4,
|
|
22071
|
+
source: "prefix"
|
|
22072
|
+
};
|
|
22073
|
+
}
|
|
22074
|
+
var init_prefix_estimate = __esm({
|
|
22075
|
+
"src/compaction/prefix-estimate.ts"() {
|
|
22076
|
+
"use strict";
|
|
22077
|
+
}
|
|
22078
|
+
});
|
|
22079
|
+
|
|
21891
22080
|
// src/compaction/protect.ts
|
|
21892
22081
|
function unescapeXml(text) {
|
|
21893
22082
|
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
@@ -22080,7 +22269,149 @@ Keep it concise; preserve exact file paths and error messages.`;
|
|
|
22080
22269
|
}
|
|
22081
22270
|
});
|
|
22082
22271
|
|
|
22272
|
+
// src/agent/prompt-rules.ts
|
|
22273
|
+
function baseRules(tools) {
|
|
22274
|
+
if (tools.length === 0) return [];
|
|
22275
|
+
const rules = [DESTRUCTIVE_RULE];
|
|
22276
|
+
const has = (name) => tools.some((tool) => tool.name === name);
|
|
22277
|
+
if (has("read")) rules.push(PARALLEL_READS_RULE);
|
|
22278
|
+
if (has("grep") && has("glob")) rules.push(LOCATE_RULE);
|
|
22279
|
+
return rules;
|
|
22280
|
+
}
|
|
22281
|
+
var DESTRUCTIVE_RULE, PARALLEL_READS_RULE, LOCATE_RULE;
|
|
22282
|
+
var init_prompt_rules = __esm({
|
|
22283
|
+
"src/agent/prompt-rules.ts"() {
|
|
22284
|
+
"use strict";
|
|
22285
|
+
DESTRUCTIVE_RULE = "Ask before destructive commands (rm -rf, git reset --hard, force push, deleting branches) unless the user requested them.";
|
|
22286
|
+
PARALLEL_READS_RULE = "Batch independent read-only tool calls into one turn.";
|
|
22287
|
+
LOCATE_RULE = "Locate code with grep/glob before reading; do not guess file paths.";
|
|
22288
|
+
}
|
|
22289
|
+
});
|
|
22290
|
+
|
|
22291
|
+
// src/agent/system-prompt.ts
|
|
22292
|
+
function firstLine(text) {
|
|
22293
|
+
return text.split("\n", 1)[0]?.trim() ?? "";
|
|
22294
|
+
}
|
|
22295
|
+
function toolDecl(tool) {
|
|
22296
|
+
return { name: tool.name, description: tool.description, parameters: tool.parameters };
|
|
22297
|
+
}
|
|
22298
|
+
function toolDecls(tools) {
|
|
22299
|
+
return [...tools].sort((a, b) => a.name.localeCompare(b.name)).map(toolDecl);
|
|
22300
|
+
}
|
|
22301
|
+
function assembleSections(input2) {
|
|
22302
|
+
const tools = [...input2.tools].sort((a, b) => a.name.localeCompare(b.name));
|
|
22303
|
+
const toolLines = tools.map((tool) => {
|
|
22304
|
+
const snippet = tool.promptSnippet ?? firstLine(tool.description);
|
|
22305
|
+
return snippet.startsWith(`${tool.name}:`) ? `- ${snippet}` : `- ${tool.name}: ${snippet}`;
|
|
22306
|
+
});
|
|
22307
|
+
const rules = [
|
|
22308
|
+
...baseRules(tools),
|
|
22309
|
+
...tools.flatMap((tool) => tool.promptGuidelines ?? []),
|
|
22310
|
+
...input2.extraRules ?? []
|
|
22311
|
+
];
|
|
22312
|
+
const projectContext = (input2.contextFiles ?? []).map((file) => `<file path="${escapeXml(file.path)}">
|
|
22313
|
+
${file.content.trim()}
|
|
22314
|
+
</file>`).join("\n\n");
|
|
22315
|
+
let skills = input2.skillsIndex;
|
|
22316
|
+
if (skills === void 0 && input2.skills !== void 0 && input2.skills.length > 0) {
|
|
22317
|
+
skills = [
|
|
22318
|
+
"<available_skills>",
|
|
22319
|
+
...input2.skills.map(
|
|
22320
|
+
(skill) => `<skill name="${escapeXml(skill.name)}" location="${escapeXml(skill.location)}">${escapeXml(skill.description)}</skill>`
|
|
22321
|
+
),
|
|
22322
|
+
"</available_skills>"
|
|
22323
|
+
].join("\n");
|
|
22324
|
+
}
|
|
22325
|
+
const host = (input2.hostInstructions ?? []).map((text) => text.trim()).filter(Boolean);
|
|
22326
|
+
const nonEmpty3 = (text) => text === void 0 || text.trim() === "" ? void 0 : text;
|
|
22327
|
+
return {
|
|
22328
|
+
preamble: input2.preamble ?? DEFAULT_PREAMBLE,
|
|
22329
|
+
tools: toolLines.length > 0 ? `Available tools:
|
|
22330
|
+
${toolLines.join("\n")}` : void 0,
|
|
22331
|
+
rules: rules.length > 0 ? `Rules:
|
|
22332
|
+
${rules.map((rule) => `- ${rule}`).join("\n")}` : void 0,
|
|
22333
|
+
project_context: nonEmpty3(projectContext),
|
|
22334
|
+
skills: nonEmpty3(skills),
|
|
22335
|
+
memory: nonEmpty3(input2.memory),
|
|
22336
|
+
hooks: nonEmpty3(input2.hookContext),
|
|
22337
|
+
cwd: `Current working directory: ${input2.cwd}`,
|
|
22338
|
+
host: host.length > 0 ? host.join("\n\n") : void 0,
|
|
22339
|
+
role: nonEmpty3(input2.role)
|
|
22340
|
+
};
|
|
22341
|
+
}
|
|
22342
|
+
function definedSections(sections) {
|
|
22343
|
+
const out = {};
|
|
22344
|
+
for (const name of SECTION_ORDER) {
|
|
22345
|
+
const text = sections[name];
|
|
22346
|
+
if (text !== void 0) out[name] = text;
|
|
22347
|
+
}
|
|
22348
|
+
return out;
|
|
22349
|
+
}
|
|
22350
|
+
function currentSystemState(messages) {
|
|
22351
|
+
return replaySystem(messages);
|
|
22352
|
+
}
|
|
22353
|
+
function sameTool(a, b) {
|
|
22354
|
+
return a.description === b.description && JSON.stringify(a.parameters) === JSON.stringify(b.parameters);
|
|
22355
|
+
}
|
|
22356
|
+
function diffSystem(current3, sections, tools, timestamp = Date.now()) {
|
|
22357
|
+
if (current3 === void 0) {
|
|
22358
|
+
const full = { role: "system", sections: { ...sections }, timestamp };
|
|
22359
|
+
if (tools.length > 0) full.toolsAdded = tools.map((tool) => ({ ...tool }));
|
|
22360
|
+
return full;
|
|
22361
|
+
}
|
|
22362
|
+
const patch = {};
|
|
22363
|
+
for (const [name, text] of Object.entries(sections)) {
|
|
22364
|
+
if (current3.sections[name] !== text) patch[name] = text;
|
|
22365
|
+
}
|
|
22366
|
+
for (const name of Object.keys(current3.sections)) {
|
|
22367
|
+
if (!(name in sections)) patch[name] = null;
|
|
22368
|
+
}
|
|
22369
|
+
const before2 = new Map(current3.tools.map((tool) => [tool.name, tool]));
|
|
22370
|
+
const after = new Map(tools.map((tool) => [tool.name, tool]));
|
|
22371
|
+
const toolsAdded = tools.filter((tool) => {
|
|
22372
|
+
const old = before2.get(tool.name);
|
|
22373
|
+
return old === void 0 || !sameTool(old, tool);
|
|
22374
|
+
});
|
|
22375
|
+
const toolsRemoved = [...before2.keys()].filter((name) => !after.has(name));
|
|
22376
|
+
if (Object.keys(patch).length === 0 && toolsAdded.length === 0 && toolsRemoved.length === 0) {
|
|
22377
|
+
return void 0;
|
|
22378
|
+
}
|
|
22379
|
+
const message = { role: "system", sections: patch, timestamp };
|
|
22380
|
+
if (toolsAdded.length > 0) message.toolsAdded = toolsAdded.map((tool) => ({ ...tool }));
|
|
22381
|
+
if (toolsRemoved.length > 0) message.toolsRemoved = toolsRemoved;
|
|
22382
|
+
return message;
|
|
22383
|
+
}
|
|
22384
|
+
var SECTION_ORDER, DEFAULT_PREAMBLE;
|
|
22385
|
+
var init_system_prompt = __esm({
|
|
22386
|
+
"src/agent/system-prompt.ts"() {
|
|
22387
|
+
"use strict";
|
|
22388
|
+
init_projection();
|
|
22389
|
+
init_index_prompt();
|
|
22390
|
+
init_prompt_rules();
|
|
22391
|
+
SECTION_ORDER = [
|
|
22392
|
+
"preamble",
|
|
22393
|
+
"tools",
|
|
22394
|
+
"rules",
|
|
22395
|
+
"project_context",
|
|
22396
|
+
"skills",
|
|
22397
|
+
// [W6-C0] 记忆索引(W6-M,docs/wave6-plan.md §3.4);未开启时为 undefined,字节不变
|
|
22398
|
+
"memory",
|
|
22399
|
+
"hooks",
|
|
22400
|
+
"cwd",
|
|
22401
|
+
"host",
|
|
22402
|
+
"role"
|
|
22403
|
+
];
|
|
22404
|
+
DEFAULT_PREAMBLE = "You are ama, a coding agent working in the user's project through tools. Read files before changing them, make focused changes, and verify your work. Be concise.";
|
|
22405
|
+
}
|
|
22406
|
+
});
|
|
22407
|
+
|
|
22083
22408
|
// src/agent/session-compaction.ts
|
|
22409
|
+
function pendingPrefixMessage(core) {
|
|
22410
|
+
const tools = core.activeToolNames().map((name) => core.activeTool(name)).filter((tool) => tool !== void 0);
|
|
22411
|
+
const system = core.childBase?.().system ?? core.options.system ?? {};
|
|
22412
|
+
const sections = definedSections(assembleSections({ ...system, tools, cwd: core.cwd }));
|
|
22413
|
+
return prefixSystemMessage(sections, toolDecls(tools));
|
|
22414
|
+
}
|
|
22084
22415
|
var DEFAULT_COMPACTION_SETTINGS, KEEP_RECENT_MAX_RATIO, HOOK_CONTEXT_CUSTOM_TYPE, CompactionController;
|
|
22085
22416
|
var init_session_compaction = __esm({
|
|
22086
22417
|
"src/agent/session-compaction.ts"() {
|
|
@@ -22088,12 +22419,14 @@ var init_session_compaction = __esm({
|
|
|
22088
22419
|
init_errors();
|
|
22089
22420
|
init_breaker();
|
|
22090
22421
|
init_estimate();
|
|
22422
|
+
init_prefix_estimate();
|
|
22091
22423
|
init_prune_tier();
|
|
22092
22424
|
init_protect();
|
|
22093
22425
|
init_post_compact();
|
|
22094
22426
|
init_summarize_tier();
|
|
22095
22427
|
init_branch_summary();
|
|
22096
22428
|
init_projection();
|
|
22429
|
+
init_system_prompt();
|
|
22097
22430
|
DEFAULT_COMPACTION_SETTINGS = {
|
|
22098
22431
|
enabled: true,
|
|
22099
22432
|
reserveTokens: 16384,
|
|
@@ -22133,6 +22466,35 @@ var init_session_compaction = __esm({
|
|
|
22133
22466
|
const branch = this.core.manager.branch();
|
|
22134
22467
|
return estimateProjectedTokens(buildProjection(branch).items, branch);
|
|
22135
22468
|
}
|
|
22469
|
+
/**
|
|
22470
|
+
* 统计用的上下文量(`getStats`):投影估算标上来源;系统消息还没落盘时加上前缀基线(系统提示 +
|
|
22471
|
+
* 工具声明,只统计不写分支)。附自动压缩的两个阈值(自动压缩可用时)。压缩调度仍用 `estimate()`。
|
|
22472
|
+
*/
|
|
22473
|
+
contextStats() {
|
|
22474
|
+
const branch = this.core.manager.branch();
|
|
22475
|
+
const items = buildProjection(branch).items;
|
|
22476
|
+
const sourced = withPrefixBaseline(
|
|
22477
|
+
estimateProjectedTokens(items, branch),
|
|
22478
|
+
items.some((item) => item.message.role === "system"),
|
|
22479
|
+
() => this.prefixTokens()
|
|
22480
|
+
);
|
|
22481
|
+
const detail = {
|
|
22482
|
+
source: sourced.source,
|
|
22483
|
+
usageTokens: sourced.usageTokens,
|
|
22484
|
+
trailingTokens: sourced.trailingTokens
|
|
22485
|
+
};
|
|
22486
|
+
const budget = this.budget();
|
|
22487
|
+
const policy = this.prunePolicy();
|
|
22488
|
+
if (this.breaker.autoEnabled && budget !== void 0 && policy !== void 0) {
|
|
22489
|
+
detail.autoCompactAt = budget;
|
|
22490
|
+
detail.pruneAt = Math.floor(policy.triggerTokens);
|
|
22491
|
+
}
|
|
22492
|
+
return { tokens: sourced.tokens, detail };
|
|
22493
|
+
}
|
|
22494
|
+
/** 将要发送的系统提示 + 工具声明的估算(与首条 system 消息同样装配,不落盘)。 */
|
|
22495
|
+
prefixTokens() {
|
|
22496
|
+
return estimateMessageTokens(pendingPrefixMessage(this.core));
|
|
22497
|
+
}
|
|
22136
22498
|
budget() {
|
|
22137
22499
|
const window2 = this.core.model().contextWindow;
|
|
22138
22500
|
return window2 === void 0 ? void 0 : Math.max(0, window2 - this.settings.reserveTokens);
|
|
@@ -22498,7 +22860,8 @@ function computeStats(input2) {
|
|
|
22498
22860
|
addCost(entry.usage);
|
|
22499
22861
|
}
|
|
22500
22862
|
}
|
|
22501
|
-
const
|
|
22863
|
+
const contextTokens = input2.context?.tokens ?? input2.contextTokens;
|
|
22864
|
+
const contextPercent = input2.contextWindow === void 0 || contextTokens === void 0 || input2.contextWindow <= 0 ? void 0 : Math.min(100, Math.round(contextTokens / input2.contextWindow * 1e3) / 10);
|
|
22502
22865
|
const stats = {
|
|
22503
22866
|
sessionId: input2.sessionId,
|
|
22504
22867
|
sessionFile: input2.sessionFile,
|
|
@@ -22508,10 +22871,11 @@ function computeStats(input2) {
|
|
|
22508
22871
|
toolResults,
|
|
22509
22872
|
tokens,
|
|
22510
22873
|
cost: cost2,
|
|
22511
|
-
contextTokens
|
|
22874
|
+
contextTokens,
|
|
22512
22875
|
contextWindow: input2.contextWindow,
|
|
22513
22876
|
contextPercent
|
|
22514
22877
|
};
|
|
22878
|
+
if (input2.context !== void 0) stats.context = { ...input2.context.detail };
|
|
22515
22879
|
const rate = cacheHitRate(tokens);
|
|
22516
22880
|
if (rate !== void 0) stats.cacheHitRate = rate;
|
|
22517
22881
|
if (input2.cache !== void 0) stats.cache = input2.cache;
|
|
@@ -24113,6 +24477,8 @@ function applyRunnerEvent(record3, event, sink) {
|
|
|
24113
24477
|
case "usage":
|
|
24114
24478
|
if (event.usage !== void 0) record3.info.usage = event.usage;
|
|
24115
24479
|
if (event.unit === "usd" && event.amount !== void 0) record3.info.costUsd = event.amount;
|
|
24480
|
+
if (event.contextTokens !== void 0) record3.info.contextTokens = event.contextTokens;
|
|
24481
|
+
if (event.contextWindow !== void 0) record3.info.contextWindow = event.contextWindow;
|
|
24116
24482
|
return;
|
|
24117
24483
|
case "notice":
|
|
24118
24484
|
sink.log(event.level, `[task ${taskId}] ${event.text}`);
|
|
@@ -24157,6 +24523,16 @@ function recordDisplay(record3, event, now) {
|
|
|
24157
24523
|
return;
|
|
24158
24524
|
}
|
|
24159
24525
|
}
|
|
24526
|
+
function taskContextPercent(info2) {
|
|
24527
|
+
const { contextTokens: used, contextWindow: size } = info2;
|
|
24528
|
+
if (used === void 0 || size === void 0 || size <= 0) return void 0;
|
|
24529
|
+
return Math.min(100, Math.round(used / size * 1e3) / 10);
|
|
24530
|
+
}
|
|
24531
|
+
function formatTaskContext(info2) {
|
|
24532
|
+
const percent3 = taskContextPercent(info2);
|
|
24533
|
+
if (percent3 === void 0) return void 0;
|
|
24534
|
+
return `${percent3 >= 10 ? Math.round(percent3) : percent3.toFixed(1)}%`;
|
|
24535
|
+
}
|
|
24160
24536
|
function startEvent(record3, handle) {
|
|
24161
24537
|
const event = {
|
|
24162
24538
|
type: "subagent_start",
|
|
@@ -25770,142 +26146,6 @@ var init_session_subagent = __esm({
|
|
|
25770
26146
|
}
|
|
25771
26147
|
});
|
|
25772
26148
|
|
|
25773
|
-
// src/agent/prompt-rules.ts
|
|
25774
|
-
function baseRules(tools) {
|
|
25775
|
-
if (tools.length === 0) return [];
|
|
25776
|
-
const rules = [DESTRUCTIVE_RULE];
|
|
25777
|
-
const has = (name) => tools.some((tool) => tool.name === name);
|
|
25778
|
-
if (has("read")) rules.push(PARALLEL_READS_RULE);
|
|
25779
|
-
if (has("grep") && has("glob")) rules.push(LOCATE_RULE);
|
|
25780
|
-
return rules;
|
|
25781
|
-
}
|
|
25782
|
-
var DESTRUCTIVE_RULE, PARALLEL_READS_RULE, LOCATE_RULE;
|
|
25783
|
-
var init_prompt_rules = __esm({
|
|
25784
|
-
"src/agent/prompt-rules.ts"() {
|
|
25785
|
-
"use strict";
|
|
25786
|
-
DESTRUCTIVE_RULE = "Ask before destructive commands (rm -rf, git reset --hard, force push, deleting branches) unless the user requested them.";
|
|
25787
|
-
PARALLEL_READS_RULE = "Batch independent read-only tool calls into one turn.";
|
|
25788
|
-
LOCATE_RULE = "Locate code with grep/glob before reading; do not guess file paths.";
|
|
25789
|
-
}
|
|
25790
|
-
});
|
|
25791
|
-
|
|
25792
|
-
// src/agent/system-prompt.ts
|
|
25793
|
-
function firstLine(text) {
|
|
25794
|
-
return text.split("\n", 1)[0]?.trim() ?? "";
|
|
25795
|
-
}
|
|
25796
|
-
function toolDecl(tool) {
|
|
25797
|
-
return { name: tool.name, description: tool.description, parameters: tool.parameters };
|
|
25798
|
-
}
|
|
25799
|
-
function toolDecls(tools) {
|
|
25800
|
-
return [...tools].sort((a, b) => a.name.localeCompare(b.name)).map(toolDecl);
|
|
25801
|
-
}
|
|
25802
|
-
function assembleSections(input2) {
|
|
25803
|
-
const tools = [...input2.tools].sort((a, b) => a.name.localeCompare(b.name));
|
|
25804
|
-
const toolLines = tools.map((tool) => {
|
|
25805
|
-
const snippet = tool.promptSnippet ?? firstLine(tool.description);
|
|
25806
|
-
return snippet.startsWith(`${tool.name}:`) ? `- ${snippet}` : `- ${tool.name}: ${snippet}`;
|
|
25807
|
-
});
|
|
25808
|
-
const rules = [
|
|
25809
|
-
...baseRules(tools),
|
|
25810
|
-
...tools.flatMap((tool) => tool.promptGuidelines ?? []),
|
|
25811
|
-
...input2.extraRules ?? []
|
|
25812
|
-
];
|
|
25813
|
-
const projectContext = (input2.contextFiles ?? []).map((file) => `<file path="${escapeXml(file.path)}">
|
|
25814
|
-
${file.content.trim()}
|
|
25815
|
-
</file>`).join("\n\n");
|
|
25816
|
-
let skills = input2.skillsIndex;
|
|
25817
|
-
if (skills === void 0 && input2.skills !== void 0 && input2.skills.length > 0) {
|
|
25818
|
-
skills = [
|
|
25819
|
-
"<available_skills>",
|
|
25820
|
-
...input2.skills.map(
|
|
25821
|
-
(skill) => `<skill name="${escapeXml(skill.name)}" location="${escapeXml(skill.location)}">${escapeXml(skill.description)}</skill>`
|
|
25822
|
-
),
|
|
25823
|
-
"</available_skills>"
|
|
25824
|
-
].join("\n");
|
|
25825
|
-
}
|
|
25826
|
-
const host = (input2.hostInstructions ?? []).map((text) => text.trim()).filter(Boolean);
|
|
25827
|
-
const nonEmpty3 = (text) => text === void 0 || text.trim() === "" ? void 0 : text;
|
|
25828
|
-
return {
|
|
25829
|
-
preamble: input2.preamble ?? DEFAULT_PREAMBLE,
|
|
25830
|
-
tools: toolLines.length > 0 ? `Available tools:
|
|
25831
|
-
${toolLines.join("\n")}` : void 0,
|
|
25832
|
-
rules: rules.length > 0 ? `Rules:
|
|
25833
|
-
${rules.map((rule) => `- ${rule}`).join("\n")}` : void 0,
|
|
25834
|
-
project_context: nonEmpty3(projectContext),
|
|
25835
|
-
skills: nonEmpty3(skills),
|
|
25836
|
-
memory: nonEmpty3(input2.memory),
|
|
25837
|
-
hooks: nonEmpty3(input2.hookContext),
|
|
25838
|
-
cwd: `Current working directory: ${input2.cwd}`,
|
|
25839
|
-
host: host.length > 0 ? host.join("\n\n") : void 0,
|
|
25840
|
-
role: nonEmpty3(input2.role)
|
|
25841
|
-
};
|
|
25842
|
-
}
|
|
25843
|
-
function definedSections(sections) {
|
|
25844
|
-
const out = {};
|
|
25845
|
-
for (const name of SECTION_ORDER) {
|
|
25846
|
-
const text = sections[name];
|
|
25847
|
-
if (text !== void 0) out[name] = text;
|
|
25848
|
-
}
|
|
25849
|
-
return out;
|
|
25850
|
-
}
|
|
25851
|
-
function currentSystemState(messages) {
|
|
25852
|
-
return replaySystem(messages);
|
|
25853
|
-
}
|
|
25854
|
-
function sameTool(a, b) {
|
|
25855
|
-
return a.description === b.description && JSON.stringify(a.parameters) === JSON.stringify(b.parameters);
|
|
25856
|
-
}
|
|
25857
|
-
function diffSystem(current3, sections, tools, timestamp = Date.now()) {
|
|
25858
|
-
if (current3 === void 0) {
|
|
25859
|
-
const full = { role: "system", sections: { ...sections }, timestamp };
|
|
25860
|
-
if (tools.length > 0) full.toolsAdded = tools.map((tool) => ({ ...tool }));
|
|
25861
|
-
return full;
|
|
25862
|
-
}
|
|
25863
|
-
const patch = {};
|
|
25864
|
-
for (const [name, text] of Object.entries(sections)) {
|
|
25865
|
-
if (current3.sections[name] !== text) patch[name] = text;
|
|
25866
|
-
}
|
|
25867
|
-
for (const name of Object.keys(current3.sections)) {
|
|
25868
|
-
if (!(name in sections)) patch[name] = null;
|
|
25869
|
-
}
|
|
25870
|
-
const before2 = new Map(current3.tools.map((tool) => [tool.name, tool]));
|
|
25871
|
-
const after = new Map(tools.map((tool) => [tool.name, tool]));
|
|
25872
|
-
const toolsAdded = tools.filter((tool) => {
|
|
25873
|
-
const old = before2.get(tool.name);
|
|
25874
|
-
return old === void 0 || !sameTool(old, tool);
|
|
25875
|
-
});
|
|
25876
|
-
const toolsRemoved = [...before2.keys()].filter((name) => !after.has(name));
|
|
25877
|
-
if (Object.keys(patch).length === 0 && toolsAdded.length === 0 && toolsRemoved.length === 0) {
|
|
25878
|
-
return void 0;
|
|
25879
|
-
}
|
|
25880
|
-
const message = { role: "system", sections: patch, timestamp };
|
|
25881
|
-
if (toolsAdded.length > 0) message.toolsAdded = toolsAdded.map((tool) => ({ ...tool }));
|
|
25882
|
-
if (toolsRemoved.length > 0) message.toolsRemoved = toolsRemoved;
|
|
25883
|
-
return message;
|
|
25884
|
-
}
|
|
25885
|
-
var SECTION_ORDER, DEFAULT_PREAMBLE;
|
|
25886
|
-
var init_system_prompt = __esm({
|
|
25887
|
-
"src/agent/system-prompt.ts"() {
|
|
25888
|
-
"use strict";
|
|
25889
|
-
init_projection();
|
|
25890
|
-
init_index_prompt();
|
|
25891
|
-
init_prompt_rules();
|
|
25892
|
-
SECTION_ORDER = [
|
|
25893
|
-
"preamble",
|
|
25894
|
-
"tools",
|
|
25895
|
-
"rules",
|
|
25896
|
-
"project_context",
|
|
25897
|
-
"skills",
|
|
25898
|
-
// [W6-C0] 记忆索引(W6-M,docs/wave6-plan.md §3.4);未开启时为 undefined,字节不变
|
|
25899
|
-
"memory",
|
|
25900
|
-
"hooks",
|
|
25901
|
-
"cwd",
|
|
25902
|
-
"host",
|
|
25903
|
-
"role"
|
|
25904
|
-
];
|
|
25905
|
-
DEFAULT_PREAMBLE = "You are ama, a coding agent working in the user's project through tools. Read files before changing them, make focused changes, and verify your work. Be concise.";
|
|
25906
|
-
}
|
|
25907
|
-
});
|
|
25908
|
-
|
|
25909
26149
|
// src/agent/session-sync.ts
|
|
25910
26150
|
function persistMessage(core, message) {
|
|
25911
26151
|
if (message.role === "custom") {
|
|
@@ -27805,15 +28045,15 @@ var init_session2 = __esm({
|
|
|
27805
28045
|
return lastAssistantText(this.manager.branch());
|
|
27806
28046
|
}
|
|
27807
28047
|
getStats() {
|
|
27808
|
-
const
|
|
28048
|
+
const context = this.compaction.contextStats();
|
|
27809
28049
|
const contextWindow = this.settings.model.contextWindow;
|
|
27810
28050
|
const stats = computeStats({
|
|
27811
28051
|
sessionId: this.manager.id,
|
|
27812
28052
|
sessionFile: this.manager.file(),
|
|
27813
28053
|
branch: this.manager.branch(),
|
|
27814
|
-
|
|
28054
|
+
context,
|
|
27815
28055
|
contextWindow,
|
|
27816
|
-
cache: this.cache.stats({ tokens:
|
|
28056
|
+
cache: this.cache.stats({ tokens: context.tokens, window: contextWindow }),
|
|
27817
28057
|
quota: this.lastQuota
|
|
27818
28058
|
});
|
|
27819
28059
|
return this.extensions.contributeStats(stats);
|
|
@@ -33351,6 +33591,8 @@ var init_codex_app_server = __esm({
|
|
|
33351
33591
|
tokensTotal;
|
|
33352
33592
|
tokensAtStart;
|
|
33353
33593
|
contextWindow;
|
|
33594
|
+
/** 最近一次请求的总量(`tokenUsage.last.totalTokens`)= 线程当前的上下文占用。 */
|
|
33595
|
+
contextTokens;
|
|
33354
33596
|
closed = false;
|
|
33355
33597
|
interruptRequested = false;
|
|
33356
33598
|
get sessionId() {
|
|
@@ -33490,6 +33732,7 @@ var init_codex_app_server = __esm({
|
|
|
33490
33732
|
input: end.inputTokens - (start?.inputTokens ?? 0),
|
|
33491
33733
|
output: end.outputTokens - (start?.outputTokens ?? 0),
|
|
33492
33734
|
cacheRead: end.cachedInputTokens - (start?.cachedInputTokens ?? 0),
|
|
33735
|
+
...this.contextTokens !== void 0 ? { contextTokens: this.contextTokens } : {},
|
|
33493
33736
|
...this.contextWindow !== void 0 ? { contextWindow: this.contextWindow } : {}
|
|
33494
33737
|
});
|
|
33495
33738
|
}
|
|
@@ -33513,6 +33756,8 @@ var init_codex_app_server = __esm({
|
|
|
33513
33756
|
const usage = params["tokenUsage"] ?? {};
|
|
33514
33757
|
const total = readTokens(usage["total"]);
|
|
33515
33758
|
if (total !== void 0) this.tokensTotal = total;
|
|
33759
|
+
const last = readTokens(usage["last"]);
|
|
33760
|
+
if (last !== void 0 && last.totalTokens > 0) this.contextTokens = last.totalTokens;
|
|
33516
33761
|
if (typeof usage["modelContextWindow"] === "number")
|
|
33517
33762
|
this.contextWindow = usage["modelContextWindow"];
|
|
33518
33763
|
return;
|
|
@@ -34431,6 +34676,8 @@ var init_runner2 = __esm({
|
|
|
34431
34676
|
agent;
|
|
34432
34677
|
/** [W6-C0] 本回合工具的骨架(id → 种类 / 状态 / 起止),回合结束写 `turn_trace`。 */
|
|
34433
34678
|
turnTools = /* @__PURE__ */ new Map();
|
|
34679
|
+
/** 外部 Agent 最近报告的上下文占用与窗口(只记数字,跨回合保留)。 */
|
|
34680
|
+
context = {};
|
|
34434
34681
|
get id() {
|
|
34435
34682
|
return this.sessionId;
|
|
34436
34683
|
}
|
|
@@ -34538,6 +34785,7 @@ var init_runner2 = __esm({
|
|
|
34538
34785
|
this.emit({ type: "notice", level: event.level, text: event.text });
|
|
34539
34786
|
return;
|
|
34540
34787
|
case "usage":
|
|
34788
|
+
this.noteContext(event.contextTokens, event.contextWindow);
|
|
34541
34789
|
if (event.costUsd !== void 0) {
|
|
34542
34790
|
turnCost.usd = event.costUsd;
|
|
34543
34791
|
const budget = this.request.budgetUsd;
|
|
@@ -34557,6 +34805,16 @@ var init_runner2 = __esm({
|
|
|
34557
34805
|
return;
|
|
34558
34806
|
}
|
|
34559
34807
|
}
|
|
34808
|
+
/** 上下文占用或窗口变了:记下并单独发一条只带它们的 usage(任务记录 / Agent 栏即时更新)。 */
|
|
34809
|
+
noteContext(tokens, window2) {
|
|
34810
|
+
const next = { ...this.context };
|
|
34811
|
+
if (tokens !== void 0) next.contextTokens = tokens;
|
|
34812
|
+
if (window2 !== void 0) next.contextWindow = window2;
|
|
34813
|
+
if (next.contextTokens === this.context.contextTokens && next.contextWindow === this.context.contextWindow)
|
|
34814
|
+
return;
|
|
34815
|
+
this.context = next;
|
|
34816
|
+
this.emit({ type: "usage", ...next });
|
|
34817
|
+
}
|
|
34560
34818
|
now() {
|
|
34561
34819
|
return (this.deps.now ?? Date.now)();
|
|
34562
34820
|
}
|
|
@@ -34645,7 +34903,8 @@ var init_runner2 = __esm({
|
|
|
34645
34903
|
sessionId: this.sessionId,
|
|
34646
34904
|
unit,
|
|
34647
34905
|
amount,
|
|
34648
|
-
...usage.totalTokens > 0 ? { tokens: usage.totalTokens } : {}
|
|
34906
|
+
...usage.totalTokens > 0 ? { tokens: usage.totalTokens } : {},
|
|
34907
|
+
...this.context
|
|
34649
34908
|
});
|
|
34650
34909
|
this.emit({ type: "usage", usage, unit, amount });
|
|
34651
34910
|
}
|
|
@@ -34886,6 +35145,8 @@ function aggregateExternal(entries) {
|
|
|
34886
35145
|
}
|
|
34887
35146
|
row3.amount += u.amount;
|
|
34888
35147
|
if (typeof u.tokens === "number") row3.tokens = (row3.tokens ?? 0) + u.tokens;
|
|
35148
|
+
if (typeof u.contextTokens === "number") row3.contextTokens = u.contextTokens;
|
|
35149
|
+
if (typeof u.contextWindow === "number") row3.contextWindow = u.contextWindow;
|
|
34889
35150
|
}
|
|
34890
35151
|
return { byAgent };
|
|
34891
35152
|
}
|
|
@@ -35890,11 +36151,17 @@ var init_acp_events = __esm({
|
|
|
35890
36151
|
usedWireIds = /* @__PURE__ */ new Set();
|
|
35891
36152
|
/** 上次 `session_info_update` 带出的标题。 */
|
|
35892
36153
|
lastTitle = null;
|
|
35893
|
-
/**
|
|
36154
|
+
/** 上次 `usage_update` 的内容(同值不重发)。 */
|
|
36155
|
+
lastUsage;
|
|
36156
|
+
/**
|
|
36157
|
+
* 会话 new / load / resume 的响应发出后由服务端调:`available_commands_update`、`config_option_update`
|
|
36158
|
+
* 与 `usage_update`(客户端可能刚重建线程,用量不去重,照发一次)。
|
|
36159
|
+
*/
|
|
35894
36160
|
announce() {
|
|
35895
36161
|
const { configOptions, commands: commands2 } = this.extras();
|
|
35896
36162
|
this.emit({ sessionUpdate: "available_commands_update", availableCommands: commands2 });
|
|
35897
36163
|
this.emit({ sessionUpdate: "config_option_update", configOptions });
|
|
36164
|
+
this.emitUsage(true);
|
|
35898
36165
|
}
|
|
35899
36166
|
/** 回合结束后由服务端调:`session_info_update`(标题与上次不同才带 title)。 */
|
|
35900
36167
|
emitSessionInfo(title, updatedAt) {
|
|
@@ -36009,6 +36276,9 @@ var init_acp_events = __esm({
|
|
|
36009
36276
|
}))
|
|
36010
36277
|
});
|
|
36011
36278
|
return;
|
|
36279
|
+
case "message_end":
|
|
36280
|
+
if ("role" in event.message && event.message.role === "assistant") this.emitUsage();
|
|
36281
|
+
return;
|
|
36012
36282
|
case "turn_end":
|
|
36013
36283
|
this.emitUsage();
|
|
36014
36284
|
return;
|
|
@@ -36025,20 +36295,29 @@ var init_acp_events = __esm({
|
|
|
36025
36295
|
sessionUpdate: "config_option_update",
|
|
36026
36296
|
configOptions: this.extras().configOptions
|
|
36027
36297
|
});
|
|
36298
|
+
if (event.type === "model_changed") this.emitUsage(true);
|
|
36028
36299
|
return;
|
|
36029
36300
|
default:
|
|
36030
36301
|
return;
|
|
36031
36302
|
}
|
|
36032
36303
|
}
|
|
36033
|
-
|
|
36304
|
+
/**
|
|
36305
|
+
* 发一条 `usage_update`:上下文用量、窗口与会话累计美元。窗口未知时不发(`size` 必填);
|
|
36306
|
+
* 与上次内容相同时不发,`force` 时照发。
|
|
36307
|
+
*/
|
|
36308
|
+
emitUsage(force = false) {
|
|
36034
36309
|
const stats = this.session().getStats();
|
|
36035
36310
|
if (stats.contextWindow === void 0) return;
|
|
36036
|
-
|
|
36311
|
+
const update = {
|
|
36037
36312
|
sessionUpdate: "usage_update",
|
|
36038
36313
|
used: stats.contextTokens ?? 0,
|
|
36039
36314
|
size: stats.contextWindow,
|
|
36040
36315
|
...stats.cost !== void 0 ? { cost: { amount: stats.cost, currency: "USD" } } : {}
|
|
36041
|
-
}
|
|
36316
|
+
};
|
|
36317
|
+
const key = JSON.stringify(update);
|
|
36318
|
+
if (!force && key === this.lastUsage) return;
|
|
36319
|
+
this.lastUsage = key;
|
|
36320
|
+
this.emit(update);
|
|
36042
36321
|
}
|
|
36043
36322
|
/** `session/load`:按消息回放历史(工具结果带前 4 KB 文本;diff 不落盘,回放没有)。 */
|
|
36044
36323
|
replay(messages) {
|
|
@@ -41791,7 +42070,7 @@ var init_meter = __esm({
|
|
|
41791
42070
|
render(width2) {
|
|
41792
42071
|
const { theme, label: label2, cells = 10 } = this.options;
|
|
41793
42072
|
const ratio = this.value === void 0 ? void 0 : Math.min(1, Math.max(0, this.value));
|
|
41794
|
-
const percent3 = ratio === void 0 ? "—" : `${Math.round(ratio * 100)}%`;
|
|
42073
|
+
const percent3 = ratio === void 0 ? "—" : this.options.percent?.(ratio) ?? `${Math.round(ratio * 100)}%`;
|
|
41795
42074
|
const color = (c, text) => theme ? theme.fg(c, text) : text;
|
|
41796
42075
|
const head = label2 === void 0 || label2 === "" ? "" : `${label2} `;
|
|
41797
42076
|
const filled = ratio === void 0 ? 0 : Math.round(ratio * cells);
|
|
@@ -42223,6 +42502,7 @@ var init_key_docs = __esm({
|
|
|
42223
42502
|
animation: true,
|
|
42224
42503
|
restoreOnCancel: true,
|
|
42225
42504
|
enterWhileRunning: "queue",
|
|
42505
|
+
programStatus: "auto",
|
|
42226
42506
|
language: "auto"
|
|
42227
42507
|
},
|
|
42228
42508
|
// [W6-C0] 第六波键的缺省(行为由各批次实现)
|
|
@@ -42628,6 +42908,7 @@ function buildBaseSchema() {
|
|
|
42628
42908
|
animation: bool(),
|
|
42629
42909
|
restoreOnCancel: bool(),
|
|
42630
42910
|
enterWhileRunning: oneOf(["queue", "interrupt"]),
|
|
42911
|
+
programStatus: oneOf(["auto", "on", "off"]),
|
|
42631
42912
|
statusLine: oneOf(STATUS_LINE_MODES),
|
|
42632
42913
|
language: oneOf(LANGUAGE_SETTINGS),
|
|
42633
42914
|
replyLanguage: str3(),
|
|
@@ -45321,12 +45602,12 @@ function handleChunk2(chunk, state, tracker) {
|
|
|
45321
45602
|
}
|
|
45322
45603
|
const usage = obj6(chunk["usageMetadata"]);
|
|
45323
45604
|
if (usage) output.usage = parseGoogleUsage(usage);
|
|
45324
|
-
const
|
|
45605
|
+
const blocked2 = str7(obj6(chunk["promptFeedback"])?.["blockReason"]);
|
|
45325
45606
|
const candidates2 = Array.isArray(chunk["candidates"]) ? chunk["candidates"] : [];
|
|
45326
45607
|
const candidate = obj6(candidates2[0]);
|
|
45327
|
-
if (!candidate &&
|
|
45328
|
-
output.rawStopReason =
|
|
45329
|
-
throw new ProviderStopError(`Prompt blocked: ${
|
|
45608
|
+
if (!candidate && blocked2) {
|
|
45609
|
+
output.rawStopReason = blocked2;
|
|
45610
|
+
throw new ProviderStopError(`Prompt blocked: ${blocked2}`);
|
|
45330
45611
|
}
|
|
45331
45612
|
const parts = obj6(candidate?.["content"])?.["parts"];
|
|
45332
45613
|
if (Array.isArray(parts)) {
|
|
@@ -46281,6 +46562,7 @@ var init_settings_registry = __esm({
|
|
|
46281
46562
|
row2("ui.statusLine", "ui", "now", "any"),
|
|
46282
46563
|
row2("ui.restoreOnCancel", "ui", "nextSession", "any"),
|
|
46283
46564
|
row2("ui.enterWhileRunning", "ui", "now", "any"),
|
|
46565
|
+
row2("ui.programStatus", "ui", "restart", "any"),
|
|
46284
46566
|
row2("ui.quietStartup", "ui", "restart", "any"),
|
|
46285
46567
|
row2("ui.ascii", "ui", "restart", "any", { envOverride: "AMA_ASCII" }),
|
|
46286
46568
|
row2("ui.language", "ui", "restart", "any", { envOverride: "AMA_LANG" }),
|
|
@@ -47589,6 +47871,17 @@ function formatTokenCount(count2) {
|
|
|
47589
47871
|
if (count2 < 1e6) return `${Math.round(count2 / 1e3)}k`;
|
|
47590
47872
|
return `${trim((count2 / 1e6).toFixed(2))}M`;
|
|
47591
47873
|
}
|
|
47874
|
+
function contextEstimated(stats) {
|
|
47875
|
+
const source = stats.context?.source;
|
|
47876
|
+
return source !== void 0 && source !== "usage";
|
|
47877
|
+
}
|
|
47878
|
+
function autoCompactText(stats) {
|
|
47879
|
+
const m = msg().report.session;
|
|
47880
|
+
if (stats.context === void 0 || stats.contextWindow === void 0) return void 0;
|
|
47881
|
+
const at = stats.context.autoCompactAt;
|
|
47882
|
+
if (at === void 0) return m.autoCompactOff;
|
|
47883
|
+
return m.toAutoCompact(formatTokenCount(Math.max(0, at - (stats.contextTokens ?? 0))));
|
|
47884
|
+
}
|
|
47592
47885
|
function formatUsd2(cost2) {
|
|
47593
47886
|
if (cost2 === void 0) return "$?";
|
|
47594
47887
|
return cost2 >= 0.01 || cost2 === 0 ? `$${cost2.toFixed(2)}` : `$${cost2.toFixed(3)}`;
|
|
@@ -47825,11 +48118,14 @@ function describeSession(session, now = Date.now()) {
|
|
|
47825
48118
|
},
|
|
47826
48119
|
{
|
|
47827
48120
|
key: m.keyContext,
|
|
47828
|
-
value:
|
|
47829
|
-
|
|
47830
|
-
|
|
47831
|
-
|
|
47832
|
-
|
|
48121
|
+
value: [
|
|
48122
|
+
m.context(
|
|
48123
|
+
`${contextEstimated(stats) ? "≈" : ""}${stats.contextTokens ?? "?"}`,
|
|
48124
|
+
String(stats.contextWindow ?? "?"),
|
|
48125
|
+
percent3
|
|
48126
|
+
),
|
|
48127
|
+
autoCompactText(stats)
|
|
48128
|
+
].filter((part) => part !== void 0).join(" · ")
|
|
47833
48129
|
}
|
|
47834
48130
|
];
|
|
47835
48131
|
const tasks = taskStatsText(session);
|
|
@@ -47998,6 +48294,111 @@ var init_status_quota = __esm({
|
|
|
47998
48294
|
}
|
|
47999
48295
|
});
|
|
48000
48296
|
|
|
48297
|
+
// src/modes/interactive/status-ctx.ts
|
|
48298
|
+
function ctxPercentText(percent3, decimal) {
|
|
48299
|
+
return decimal || percent3 > 0 && percent3 < 1 ? `${percent3.toFixed(1)}%` : `${Math.round(percent3)}%`;
|
|
48300
|
+
}
|
|
48301
|
+
function ctxWarnAt(stats) {
|
|
48302
|
+
const at = stats.context?.pruneAt;
|
|
48303
|
+
const window2 = stats.contextWindow;
|
|
48304
|
+
return at === void 0 || window2 === void 0 || window2 <= 0 ? 0.7 : Math.min(0.9, at / window2);
|
|
48305
|
+
}
|
|
48306
|
+
function ctxApprox(stats, ascii = false) {
|
|
48307
|
+
return contextEstimated(stats) ? ascii ? "~" : "≈" : "";
|
|
48308
|
+
}
|
|
48309
|
+
function compactCtxText(ctx, width2, theme) {
|
|
48310
|
+
const { percent: percent3 } = ctx;
|
|
48311
|
+
if (percent3 === void 0) return theme.fg("dim", "ctx ?");
|
|
48312
|
+
if (width2 >= METER_WIDTH) {
|
|
48313
|
+
const meter = new Meter(percent3 / 100, {
|
|
48314
|
+
label: theme.fg("dim", "ctx"),
|
|
48315
|
+
theme,
|
|
48316
|
+
warnAt: ctx.warnAt,
|
|
48317
|
+
percent: (ratio) => ctx.approx + ctxPercentText(ratio * 100, false)
|
|
48318
|
+
});
|
|
48319
|
+
return meter.render(80)[0] ?? "";
|
|
48320
|
+
}
|
|
48321
|
+
const color = levelColor(percent3 / 100, { warnAt: ctx.warnAt });
|
|
48322
|
+
return theme.fg("dim", "ctx ") + theme.fg(color, ctx.approx + ctxPercentText(percent3, false));
|
|
48323
|
+
}
|
|
48324
|
+
function fullCtxParts(ctx, theme, p) {
|
|
48325
|
+
const dim = (text) => theme.fg("dim", text);
|
|
48326
|
+
const out = [];
|
|
48327
|
+
const add3 = (text, priority, reserve) => void out.push({
|
|
48328
|
+
text,
|
|
48329
|
+
priority,
|
|
48330
|
+
zone: "right",
|
|
48331
|
+
group: "ctx",
|
|
48332
|
+
...reserve === void 0 ? {} : { reserve }
|
|
48333
|
+
});
|
|
48334
|
+
const { percent: percent3 } = ctx;
|
|
48335
|
+
if (percent3 === void 0) add3(dim("Ctx ?"), p.ctx, 10);
|
|
48336
|
+
else {
|
|
48337
|
+
const color = levelColor(percent3 / 100, { warnAt: ctx.warnAt });
|
|
48338
|
+
add3(dim("Ctx ") + theme.fg(color, ctx.approx + ctxPercentText(percent3, true)), p.ctx, 10);
|
|
48339
|
+
}
|
|
48340
|
+
if (ctx.tokens !== void 0) add3(dim(` ${formatTokens3(ctx.tokens)}`), p.ctxUsed, 5);
|
|
48341
|
+
if (ctx.tokens !== void 0 && ctx.window !== void 0)
|
|
48342
|
+
add3(dim(`/${formatTokens3(ctx.window)}`), p.ctxWindow, 5);
|
|
48343
|
+
if (ctx.auto) add3(dim(` ${msg().interactive.statusLine.autoCompact}`), p.ctxAuto);
|
|
48344
|
+
return out;
|
|
48345
|
+
}
|
|
48346
|
+
var LIVE_CTX_INTERVAL_MS, METER_WIDTH, LiveContext;
|
|
48347
|
+
var init_status_ctx = __esm({
|
|
48348
|
+
"src/modes/interactive/status-ctx.ts"() {
|
|
48349
|
+
"use strict";
|
|
48350
|
+
init_estimate();
|
|
48351
|
+
init_i18n();
|
|
48352
|
+
init_tui2();
|
|
48353
|
+
init_session_report();
|
|
48354
|
+
init_status_bar();
|
|
48355
|
+
LIVE_CTX_INTERVAL_MS = 500;
|
|
48356
|
+
METER_WIDTH = 110;
|
|
48357
|
+
LiveContext = class {
|
|
48358
|
+
constructor(now) {
|
|
48359
|
+
this.now = now;
|
|
48360
|
+
}
|
|
48361
|
+
now;
|
|
48362
|
+
tokens;
|
|
48363
|
+
at = Number.NEGATIVE_INFINITY;
|
|
48364
|
+
/** 记下 usage 给出的上下文量;距上次采样 < 500 ms 时不更新。返回是否更新了。 */
|
|
48365
|
+
note(usage) {
|
|
48366
|
+
if (usage === void 0) return false;
|
|
48367
|
+
const tokens = calculateContextTokens(usage);
|
|
48368
|
+
if (tokens <= 0) return false;
|
|
48369
|
+
const now = this.now();
|
|
48370
|
+
if (this.tokens !== void 0 && now - this.at < LIVE_CTX_INTERVAL_MS) return false;
|
|
48371
|
+
this.tokens = tokens;
|
|
48372
|
+
this.at = now;
|
|
48373
|
+
return true;
|
|
48374
|
+
}
|
|
48375
|
+
clear() {
|
|
48376
|
+
this.tokens = void 0;
|
|
48377
|
+
this.at = Number.NEGATIVE_INFINITY;
|
|
48378
|
+
}
|
|
48379
|
+
/** 统计值 → 显示值(有在途值时以它为准,不再是估算)。 */
|
|
48380
|
+
view(stats, ascii) {
|
|
48381
|
+
const view = {
|
|
48382
|
+
tokens: stats.contextTokens,
|
|
48383
|
+
window: stats.contextWindow,
|
|
48384
|
+
percent: stats.contextPercent,
|
|
48385
|
+
approx: ctxApprox(stats, ascii),
|
|
48386
|
+
warnAt: ctxWarnAt(stats),
|
|
48387
|
+
auto: stats.context?.autoCompactAt !== void 0
|
|
48388
|
+
};
|
|
48389
|
+
const window2 = stats.contextWindow;
|
|
48390
|
+
if (this.tokens !== void 0) {
|
|
48391
|
+
view.tokens = this.tokens;
|
|
48392
|
+
view.approx = "";
|
|
48393
|
+
if (window2 !== void 0 && window2 > 0)
|
|
48394
|
+
view.percent = Math.min(100, Math.round(this.tokens / window2 * 1e3) / 10);
|
|
48395
|
+
}
|
|
48396
|
+
return view;
|
|
48397
|
+
}
|
|
48398
|
+
};
|
|
48399
|
+
}
|
|
48400
|
+
});
|
|
48401
|
+
|
|
48001
48402
|
// src/modes/interactive/status-bar.ts
|
|
48002
48403
|
function formatTokens3(count2) {
|
|
48003
48404
|
if (count2 < 1e3) return String(count2);
|
|
@@ -48021,6 +48422,16 @@ function cacheText(cache3, warm = "♨") {
|
|
|
48021
48422
|
const value = cache3.reporting === "silent" ? msg().interactive.statusLine.cacheSilent : cache3.reporting === "reported" && rate !== void 0 ? `${Math.round(rate * 100)}%` : "—";
|
|
48022
48423
|
return `cache ${value}${cache3.warming.state === "scheduled" ? ` ${warm}` : ""}`;
|
|
48023
48424
|
}
|
|
48425
|
+
function tokensText(t, g) {
|
|
48426
|
+
const prompt = t.input + t.cacheRead + t.cacheWrite;
|
|
48427
|
+
const parts = [
|
|
48428
|
+
`${g.ascii ? "sum " : "Σ"}${g.arrowUp}${formatTokens3(prompt)}`,
|
|
48429
|
+
`${g.arrowDown}${formatTokens3(t.output)}`
|
|
48430
|
+
];
|
|
48431
|
+
if (t.cacheRead > 0) parts.push(`R${formatTokens3(t.cacheRead)}`);
|
|
48432
|
+
if (t.cacheWrite > 0) parts.push(`W${formatTokens3(t.cacheWrite)}`);
|
|
48433
|
+
return parts.join(" ");
|
|
48434
|
+
}
|
|
48024
48435
|
function statusCost(stats) {
|
|
48025
48436
|
if (stats.cost === void 0) return void 0;
|
|
48026
48437
|
let external = 0;
|
|
@@ -48085,7 +48496,7 @@ function abbreviateModel(ref, width2) {
|
|
|
48085
48496
|
if (width2 < 48) out = out.replace(/-\d.*$/, "");
|
|
48086
48497
|
return out;
|
|
48087
48498
|
}
|
|
48088
|
-
function usageItems(stats, queue, source, theme) {
|
|
48499
|
+
function usageItems(stats, queue, source, theme, cumulative = false) {
|
|
48089
48500
|
const g = theme.glyphs;
|
|
48090
48501
|
const dim = (text) => theme.fg("dim", text);
|
|
48091
48502
|
const out = {};
|
|
@@ -48093,7 +48504,9 @@ function usageItems(stats, queue, source, theme) {
|
|
|
48093
48504
|
const prompt = t.input + t.cacheRead + t.cacheWrite;
|
|
48094
48505
|
const cache3 = stats.cache;
|
|
48095
48506
|
if (prompt + t.output > 0) {
|
|
48096
|
-
out.tokens = dim(
|
|
48507
|
+
out.tokens = dim(
|
|
48508
|
+
cumulative ? tokensText(t, g) : `${g.arrowUp}${formatTokens3(prompt)} ${g.arrowDown}${formatTokens3(t.output)}`
|
|
48509
|
+
);
|
|
48097
48510
|
if (cache3 !== void 0) out.cache = dim(cacheText(cache3, g.warm));
|
|
48098
48511
|
else if (stats.cacheHitRate !== void 0) {
|
|
48099
48512
|
out.cache = dim(`cache ${Math.round(stats.cacheHitRate * 100)}%`);
|
|
@@ -48123,7 +48536,7 @@ function usageItems(stats, queue, source, theme) {
|
|
|
48123
48536
|
}
|
|
48124
48537
|
return out;
|
|
48125
48538
|
}
|
|
48126
|
-
var MIN_GAP,
|
|
48539
|
+
var MIN_GAP, COMPACT, FULL, FULL_HINT, FULL_STYLE, StatusBar;
|
|
48127
48540
|
var init_status_bar = __esm({
|
|
48128
48541
|
"src/modes/interactive/status-bar.ts"() {
|
|
48129
48542
|
"use strict";
|
|
@@ -48131,9 +48544,9 @@ var init_status_bar = __esm({
|
|
|
48131
48544
|
init_modes();
|
|
48132
48545
|
init_channels();
|
|
48133
48546
|
init_status_quota();
|
|
48547
|
+
init_status_ctx();
|
|
48134
48548
|
init_tui2();
|
|
48135
48549
|
MIN_GAP = 4;
|
|
48136
|
-
METER_WIDTH = 110;
|
|
48137
48550
|
COMPACT = {
|
|
48138
48551
|
model: 0,
|
|
48139
48552
|
ctx: 1,
|
|
@@ -48153,9 +48566,21 @@ var init_status_bar = __esm({
|
|
|
48153
48566
|
hint: 16,
|
|
48154
48567
|
quota: 17
|
|
48155
48568
|
};
|
|
48156
|
-
FULL = {
|
|
48569
|
+
FULL = {
|
|
48570
|
+
model: 0,
|
|
48571
|
+
ctx: 1,
|
|
48572
|
+
cost: 2,
|
|
48573
|
+
duration: 3,
|
|
48574
|
+
ctxUsed: 4,
|
|
48575
|
+
branch: 5,
|
|
48576
|
+
dir: 6,
|
|
48577
|
+
diff: 7,
|
|
48578
|
+
ctxWindow: 8,
|
|
48579
|
+
thinking: 9,
|
|
48580
|
+
ctxAuto: 13
|
|
48581
|
+
};
|
|
48157
48582
|
FULL_HINT = 12;
|
|
48158
|
-
FULL_STYLE = { sep: " | " };
|
|
48583
|
+
FULL_STYLE = { sep: " | ", groups: { ctx: { glue: "" } } };
|
|
48159
48584
|
StatusBar = class {
|
|
48160
48585
|
constructor(source, theme) {
|
|
48161
48586
|
this.source = source;
|
|
@@ -48165,10 +48590,23 @@ var init_status_bar = __esm({
|
|
|
48165
48590
|
theme;
|
|
48166
48591
|
stats;
|
|
48167
48592
|
queue = 0;
|
|
48593
|
+
/** 在途请求的上下文量(message_update 的 usage,≤ 2 Hz 采样);该消息结束后清掉。 */
|
|
48594
|
+
live = new LiveContext(() => this.source.now?.() ?? Date.now());
|
|
48168
48595
|
/** 用量、模型等变化后调用(事件驱动;流式期间不必每帧算)。 */
|
|
48169
48596
|
refresh() {
|
|
48170
48597
|
this.stats = this.source.session().getStats();
|
|
48171
48598
|
}
|
|
48599
|
+
/**
|
|
48600
|
+
* 流式中的助手消息带了 usage(有的协议在开头就给输入量):记下在途请求的上下文量,距上次采样
|
|
48601
|
+
* ≥ 500 ms 才更新(≤ 2 Hz)。返回是否更新了。
|
|
48602
|
+
*/
|
|
48603
|
+
noteStreaming(usage) {
|
|
48604
|
+
return this.live.note(usage);
|
|
48605
|
+
}
|
|
48606
|
+
/** 助手消息结束:丢掉在途值,回到统计值。 */
|
|
48607
|
+
clearStreaming() {
|
|
48608
|
+
this.live.clear();
|
|
48609
|
+
}
|
|
48172
48610
|
setQueue(steering, followUp) {
|
|
48173
48611
|
this.queue = steering + followUp;
|
|
48174
48612
|
}
|
|
@@ -48219,7 +48657,9 @@ var init_status_bar = __esm({
|
|
|
48219
48657
|
if (usage.cache !== void 0) right(usage.cache, COMPACT.cache);
|
|
48220
48658
|
if (usage.cost !== void 0) right(usage.cost, COMPACT.cost);
|
|
48221
48659
|
if (usage.rebill !== void 0) right(usage.rebill, COMPACT.rebill);
|
|
48222
|
-
|
|
48660
|
+
const ctx = this.live.view(stats, g.ascii);
|
|
48661
|
+
if (full) fullCtxParts(ctx, theme, FULL).forEach((part) => parts.push(part));
|
|
48662
|
+
else right(compactCtxText(ctx, width2, theme), p.ctx);
|
|
48223
48663
|
this.gitParts(p, full).forEach((part) => parts.push(part));
|
|
48224
48664
|
if (full) {
|
|
48225
48665
|
const cost2 = statusCost(stats);
|
|
@@ -48280,17 +48720,6 @@ var init_status_bar = __esm({
|
|
|
48280
48720
|
}
|
|
48281
48721
|
return out;
|
|
48282
48722
|
}
|
|
48283
|
-
ctxText(percent3, width2, decimal) {
|
|
48284
|
-
const theme = this.theme;
|
|
48285
|
-
if (percent3 === void 0) return theme.fg("dim", decimal ? "Ctx ?" : "ctx ?");
|
|
48286
|
-
const color = levelColor(percent3 / 100);
|
|
48287
|
-
if (!decimal && width2 >= METER_WIDTH) {
|
|
48288
|
-
const meter = new Meter(percent3 / 100, { label: theme.fg("dim", "ctx"), theme });
|
|
48289
|
-
return meter.render(80)[0] ?? "";
|
|
48290
|
-
}
|
|
48291
|
-
if (decimal) return theme.fg("dim", "Ctx ") + theme.fg(color, `${percent3.toFixed(1)}%`);
|
|
48292
|
-
return theme.fg("dim", "ctx ") + theme.fg(color, `${Math.round(percent3)}%`);
|
|
48293
|
-
}
|
|
48294
48723
|
render(width2) {
|
|
48295
48724
|
const style = this.layout() === "full" ? FULL_STYLE : {};
|
|
48296
48725
|
return [layoutRow(this.parts(width2), width2, this.theme, style)];
|
|
@@ -48648,7 +49077,7 @@ function usageOf(node) {
|
|
|
48648
49077
|
return void 0;
|
|
48649
49078
|
}
|
|
48650
49079
|
}
|
|
48651
|
-
function
|
|
49080
|
+
function tokensText2(node, theme) {
|
|
48652
49081
|
const { arrowUp, arrowDown } = theme.glyphs;
|
|
48653
49082
|
if (node.kind === "turn") {
|
|
48654
49083
|
const u = node.usage;
|
|
@@ -48792,7 +49221,7 @@ function formatRow(row3, width2, ctx, selected = false) {
|
|
|
48792
49221
|
if (width2 < NARROW_WIDTH) right = ` ${duration}`;
|
|
48793
49222
|
else {
|
|
48794
49223
|
const bar = barText(row3, barWidth(width2), theme);
|
|
48795
|
-
const tokens = padToWidth(
|
|
49224
|
+
const tokens = padToWidth(tokensText2(row3.node, theme), TOKENS_WIDTH);
|
|
48796
49225
|
const cache3 = cacheText2(row3.node).padStart(CACHE_WIDTH);
|
|
48797
49226
|
right = ` ${duration} ${bar} ${tokens} ${cache3}`;
|
|
48798
49227
|
}
|
|
@@ -48843,7 +49272,7 @@ function formatTraceText(trace, ctx, rows = expandAll((expanded) => flattenTrace
|
|
|
48843
49272
|
for (const row3 of rows) {
|
|
48844
49273
|
const indent2 = " ".repeat(row3.depth);
|
|
48845
49274
|
const mark = statusMark(row3.node, theme);
|
|
48846
|
-
const cols = [durationText(row3.node, theme),
|
|
49275
|
+
const cols = [durationText(row3.node, theme), tokensText2(row3.node, theme), cacheText2(row3.node)].filter((c) => c !== "").join(" ");
|
|
48847
49276
|
const label2 = `${indent2}${mark === "" ? "" : `${mark} `}${rowLabel(row3, ctx)}`;
|
|
48848
49277
|
lines2.push(cols === "" ? label2 : `${label2} ${cols}`);
|
|
48849
49278
|
}
|
|
@@ -50921,6 +51350,7 @@ async function runPrintMode(runtime, context) {
|
|
|
50921
51350
|
usage: stats.tokens,
|
|
50922
51351
|
cost: stats.cost,
|
|
50923
51352
|
cacheHitRate: stats.cacheHitRate,
|
|
51353
|
+
...contextOf(stats),
|
|
50924
51354
|
...stats.cache !== void 0 ? { cache: stats.cache } : {},
|
|
50925
51355
|
...stats.tasks !== void 0 ? { tasks: stats.tasks } : {},
|
|
50926
51356
|
...denied.length > 0 ? { deniedTools: denied } : {},
|
|
@@ -51003,6 +51433,13 @@ function describeDenied(denied) {
|
|
|
51003
51433
|
const tools = [...counts].map(([name, n]) => `${name} ×${n}`);
|
|
51004
51434
|
return msg().print.print.denied(denied.length, tools, denied[0]?.reason ?? "");
|
|
51005
51435
|
}
|
|
51436
|
+
function contextOf(stats) {
|
|
51437
|
+
const context = {};
|
|
51438
|
+
if (stats.contextTokens !== void 0) context["tokens"] = stats.contextTokens;
|
|
51439
|
+
if (stats.contextWindow !== void 0) context["window"] = stats.contextWindow;
|
|
51440
|
+
if (stats.contextPercent !== void 0) context["percent"] = stats.contextPercent;
|
|
51441
|
+
return Object.keys(context).length > 0 ? { context } : {};
|
|
51442
|
+
}
|
|
51006
51443
|
var STDIN_WAIT_HINT_MS, STDIN_FIRST_BYTE_MS;
|
|
51007
51444
|
var init_print_mode = __esm({
|
|
51008
51445
|
"src/modes/print/print-mode.ts"() {
|
|
@@ -51630,6 +52067,8 @@ function taskFacts(task, now) {
|
|
|
51630
52067
|
facts.push(
|
|
51631
52068
|
`↑${formatTokenCount(usage.input + usage.cacheRead + usage.cacheWrite)} ↓${formatTokenCount(usage.output)}`
|
|
51632
52069
|
);
|
|
52070
|
+
const context = formatTaskContext(task);
|
|
52071
|
+
if (context !== void 0) facts.push(msg().panels.tasks.context(context));
|
|
51633
52072
|
if (task.costUsd !== void 0 && task.costUsd > 0) facts.push(formatUsd2(task.costUsd));
|
|
51634
52073
|
return facts;
|
|
51635
52074
|
}
|
|
@@ -51696,6 +52135,7 @@ var init_tasks_report = __esm({
|
|
|
51696
52135
|
"src/modes/interactive/tasks-report.ts"() {
|
|
51697
52136
|
"use strict";
|
|
51698
52137
|
init_external();
|
|
52138
|
+
init_task_record();
|
|
51699
52139
|
init_subagent_registry();
|
|
51700
52140
|
init_i18n();
|
|
51701
52141
|
init_session_report();
|
|
@@ -51756,6 +52196,529 @@ var init_task_background = __esm({
|
|
|
51756
52196
|
}
|
|
51757
52197
|
});
|
|
51758
52198
|
|
|
52199
|
+
// src/compaction/breakdown.ts
|
|
52200
|
+
function textPiece(category, name, text) {
|
|
52201
|
+
const count2 = countText(text, { wide: 0, narrow: 0 });
|
|
52202
|
+
return { category, name, wide: count2.wide, narrow: count2.narrow, fixed: 0 };
|
|
52203
|
+
}
|
|
52204
|
+
function imagePiece(name) {
|
|
52205
|
+
return { category: "images", name, wide: 0, narrow: 0, fixed: IMAGE_TOKENS };
|
|
52206
|
+
}
|
|
52207
|
+
function contentPieces(content, category, name, imageSource) {
|
|
52208
|
+
if (typeof content === "string") return [textPiece(category, name, content)];
|
|
52209
|
+
return content.map(
|
|
52210
|
+
(block) => block.type === "text" ? textPiece(category, name, block.text) : imagePiece(imageSource)
|
|
52211
|
+
);
|
|
52212
|
+
}
|
|
52213
|
+
function messagePieces(message) {
|
|
52214
|
+
switch (message.role) {
|
|
52215
|
+
case "system": {
|
|
52216
|
+
const pieces2 = Object.entries(message.sections).map(
|
|
52217
|
+
([name, text]) => textPiece("system", name, text ?? "")
|
|
52218
|
+
);
|
|
52219
|
+
const tools = message.toolsAdded;
|
|
52220
|
+
if (tools !== void 0) {
|
|
52221
|
+
for (const tool of tools) pieces2.push(textPiece("tools", tool.name, JSON.stringify(tool)));
|
|
52222
|
+
pieces2.push({
|
|
52223
|
+
category: "tools",
|
|
52224
|
+
name: void 0,
|
|
52225
|
+
wide: 0,
|
|
52226
|
+
narrow: 2 + Math.max(0, tools.length - 1),
|
|
52227
|
+
fixed: 0
|
|
52228
|
+
});
|
|
52229
|
+
}
|
|
52230
|
+
return pieces2;
|
|
52231
|
+
}
|
|
52232
|
+
case "user":
|
|
52233
|
+
return contentPieces(message.content, "user", void 0, "user");
|
|
52234
|
+
case "toolResult":
|
|
52235
|
+
return contentPieces(message.content, "toolResults", message.toolName, "toolResult");
|
|
52236
|
+
case "custom":
|
|
52237
|
+
return contentPieces(message.content, "custom", message.customType, "custom");
|
|
52238
|
+
case "assistant":
|
|
52239
|
+
return message.content.map(
|
|
52240
|
+
(block) => block.type === "text" ? textPiece("assistant", void 0, block.text) : block.type === "thinking" ? textPiece("reasoning", void 0, block.thinking) : textPiece("toolCalls", block.name, block.name + JSON.stringify(block.arguments))
|
|
52241
|
+
);
|
|
52242
|
+
case "compactionSummary":
|
|
52243
|
+
return [textPiece("summaries", "compaction", message.summary)];
|
|
52244
|
+
case "branchSummary":
|
|
52245
|
+
return [textPiece("summaries", "branch", message.summary)];
|
|
52246
|
+
}
|
|
52247
|
+
}
|
|
52248
|
+
function allocate(pieces2, total) {
|
|
52249
|
+
const tokens = pieces2.map((p) => p.fixed + p.wide + Math.floor(p.narrow / CHARS_PER_TOKEN2));
|
|
52250
|
+
let left = total - tokens.reduce((sum, n) => sum + n, 0);
|
|
52251
|
+
const order = pieces2.map((p, i) => ({ i, rest: p.narrow % CHARS_PER_TOKEN2 })).filter((x) => x.rest > 0).sort((a, b) => b.rest - a.rest || a.i - b.i);
|
|
52252
|
+
for (const { i } of order) {
|
|
52253
|
+
if (left <= 0) break;
|
|
52254
|
+
tokens[i] = (tokens[i] ?? 0) + 1;
|
|
52255
|
+
left--;
|
|
52256
|
+
}
|
|
52257
|
+
if (left !== 0 && tokens.length > 0) {
|
|
52258
|
+
let max = 0;
|
|
52259
|
+
for (let i = 1; i < tokens.length; i++) if ((tokens[i] ?? 0) > (tokens[max] ?? 0)) max = i;
|
|
52260
|
+
tokens[max] = (tokens[max] ?? 0) + left;
|
|
52261
|
+
}
|
|
52262
|
+
return tokens;
|
|
52263
|
+
}
|
|
52264
|
+
function breakdownMessages(messages) {
|
|
52265
|
+
const totals2 = /* @__PURE__ */ new Map();
|
|
52266
|
+
const parts = /* @__PURE__ */ new Map();
|
|
52267
|
+
for (const category of BREAKDOWN_CATEGORIES) {
|
|
52268
|
+
totals2.set(category, { tokens: 0, count: 0 });
|
|
52269
|
+
parts.set(category, /* @__PURE__ */ new Map());
|
|
52270
|
+
}
|
|
52271
|
+
const toolResults = [];
|
|
52272
|
+
let total = 0;
|
|
52273
|
+
let hasSystem = false;
|
|
52274
|
+
for (const message of messages) {
|
|
52275
|
+
const messageTokens = estimateMessageTokens(message);
|
|
52276
|
+
total += messageTokens;
|
|
52277
|
+
if (message.role === "system") hasSystem = true;
|
|
52278
|
+
if (message.role === "toolResult") {
|
|
52279
|
+
toolResults.push({
|
|
52280
|
+
ordinal: toolResults.length + 1,
|
|
52281
|
+
toolName: message.toolName,
|
|
52282
|
+
tokens: messageTokens
|
|
52283
|
+
});
|
|
52284
|
+
}
|
|
52285
|
+
const pieces2 = messagePieces(message);
|
|
52286
|
+
const allocated = allocate(pieces2, messageTokens);
|
|
52287
|
+
pieces2.forEach((piece, i) => {
|
|
52288
|
+
const tokens = allocated[i] ?? 0;
|
|
52289
|
+
const entry = totals2.get(piece.category);
|
|
52290
|
+
if (entry === void 0) return;
|
|
52291
|
+
entry.tokens += tokens;
|
|
52292
|
+
if (piece.name !== void 0 || piece.category !== "tools") entry.count++;
|
|
52293
|
+
if (piece.name !== void 0) {
|
|
52294
|
+
const named = parts.get(piece.category);
|
|
52295
|
+
named?.set(piece.name, (named.get(piece.name) ?? 0) + tokens);
|
|
52296
|
+
}
|
|
52297
|
+
});
|
|
52298
|
+
}
|
|
52299
|
+
const entries = BREAKDOWN_CATEGORIES.map((category) => {
|
|
52300
|
+
const entry = totals2.get(category) ?? { tokens: 0, count: 0 };
|
|
52301
|
+
const named = [...parts.get(category) ?? /* @__PURE__ */ new Map()].map(([name, tokens]) => ({ name, tokens })).sort((a, b) => b.tokens - a.tokens || a.name.localeCompare(b.name));
|
|
52302
|
+
return { category, tokens: entry.tokens, count: entry.count, parts: named };
|
|
52303
|
+
});
|
|
52304
|
+
const prefixTokens = entries.filter((e) => e.category === "system" || e.category === "tools").reduce((sum, e) => sum + e.tokens, 0);
|
|
52305
|
+
return { entries, total, prefixTokens, hasSystem, toolResults };
|
|
52306
|
+
}
|
|
52307
|
+
function largestToolResults(breakdown, n) {
|
|
52308
|
+
return [...breakdown.toolResults].sort((a, b) => b.tokens - a.tokens || a.ordinal - b.ordinal).slice(0, Math.max(0, n));
|
|
52309
|
+
}
|
|
52310
|
+
var CHARS_PER_TOKEN2, BREAKDOWN_CATEGORIES;
|
|
52311
|
+
var init_breakdown = __esm({
|
|
52312
|
+
"src/compaction/breakdown.ts"() {
|
|
52313
|
+
"use strict";
|
|
52314
|
+
init_estimate();
|
|
52315
|
+
CHARS_PER_TOKEN2 = 4;
|
|
52316
|
+
BREAKDOWN_CATEGORIES = [
|
|
52317
|
+
"system",
|
|
52318
|
+
"tools",
|
|
52319
|
+
"user",
|
|
52320
|
+
"assistant",
|
|
52321
|
+
"reasoning",
|
|
52322
|
+
"toolCalls",
|
|
52323
|
+
"toolResults",
|
|
52324
|
+
"images",
|
|
52325
|
+
"summaries",
|
|
52326
|
+
"custom"
|
|
52327
|
+
];
|
|
52328
|
+
}
|
|
52329
|
+
});
|
|
52330
|
+
|
|
52331
|
+
// src/cli/startup-screen.ts
|
|
52332
|
+
function startupScreenLevel(runtime) {
|
|
52333
|
+
return runtime.config.ui?.quietStartup ?? "normal";
|
|
52334
|
+
}
|
|
52335
|
+
function trustSourceLabel(source) {
|
|
52336
|
+
const labels2 = msg().cli.startupScreen.trustSource;
|
|
52337
|
+
return source === "trust-file" ? labels2.trustFile : labels2[source];
|
|
52338
|
+
}
|
|
52339
|
+
function tildePath(path, home) {
|
|
52340
|
+
if (home === void 0 || home === "") return path;
|
|
52341
|
+
const trimmed = /[\\/]$/.test(home) ? home.slice(0, -1) : home;
|
|
52342
|
+
if (path === trimmed) return "~";
|
|
52343
|
+
const next = path[trimmed.length];
|
|
52344
|
+
return path.startsWith(trimmed) && (next === "/" || next === "\\") ? `~${path.slice(trimmed.length)}` : path;
|
|
52345
|
+
}
|
|
52346
|
+
function startupInfo(runtime, home) {
|
|
52347
|
+
const { resources } = runtime;
|
|
52348
|
+
const info2 = {
|
|
52349
|
+
version: AMA_VERSION,
|
|
52350
|
+
model: formatModelRef(runtime.model),
|
|
52351
|
+
thinking: runtime.thinkingLevel,
|
|
52352
|
+
cwd: tildePath(runtime.paths.cwd, home),
|
|
52353
|
+
trusted: runtime.trust.trusted,
|
|
52354
|
+
trustSource: trustSourceLabel(runtime.trust.source),
|
|
52355
|
+
permissionMode: runtime.session.state.permissionMode,
|
|
52356
|
+
preset: runtime.config.tools?.preset ?? "default",
|
|
52357
|
+
codemode: effectiveCodemodeMode(runtime.config),
|
|
52358
|
+
contextFiles: resources.contextFiles.map((f) => (0, import_node_path93.basename)(f.path)),
|
|
52359
|
+
skills: resources.skills.filter((s2) => !isBuiltinSkill(s2)).length,
|
|
52360
|
+
prompts: resources.prompts.length,
|
|
52361
|
+
hooks: runtime.hooks.list().length,
|
|
52362
|
+
warnings: runtime.warnings.length
|
|
52363
|
+
};
|
|
52364
|
+
if (runtime.host !== void 0) info2.host = runtime.host.adapter.id;
|
|
52365
|
+
return info2;
|
|
52366
|
+
}
|
|
52367
|
+
var import_node_path93;
|
|
52368
|
+
var init_startup_screen = __esm({
|
|
52369
|
+
"src/cli/startup-screen.ts"() {
|
|
52370
|
+
"use strict";
|
|
52371
|
+
init_builtin3();
|
|
52372
|
+
import_node_path93 = require("node:path");
|
|
52373
|
+
init_channels();
|
|
52374
|
+
init_presets2();
|
|
52375
|
+
init_i18n();
|
|
52376
|
+
init_version();
|
|
52377
|
+
}
|
|
52378
|
+
});
|
|
52379
|
+
|
|
52380
|
+
// src/modes/interactive/panels.ts
|
|
52381
|
+
function keyValue(rows, theme, wrap2 = false) {
|
|
52382
|
+
return new KeyValue(rows, { theme, maxKeyRatio: 0.3, ...wrap2 ? { wrap: true } : {} });
|
|
52383
|
+
}
|
|
52384
|
+
function cacheSection(session, theme, now) {
|
|
52385
|
+
return [
|
|
52386
|
+
theme.bold(msg().panels.cache.title),
|
|
52387
|
+
new Indent(keyValue(cacheRows(session, now), theme), 2)
|
|
52388
|
+
];
|
|
52389
|
+
}
|
|
52390
|
+
function sessionPanel(session, theme, options = {}) {
|
|
52391
|
+
const m = msg().panels.session;
|
|
52392
|
+
const now = options.now ?? Date.now();
|
|
52393
|
+
const state = session.state;
|
|
52394
|
+
const stats = session.getStats();
|
|
52395
|
+
const t = stats.tokens;
|
|
52396
|
+
const sep5 = theme.fg("dim", " · ");
|
|
52397
|
+
const model = state.model === void 0 ? "?" : `${state.model.provider}/${state.model.id}`;
|
|
52398
|
+
const ratio = stats.contextPercent === void 0 ? void 0 : stats.contextPercent / 100;
|
|
52399
|
+
const approx = contextEstimated(stats) ? "≈" : "";
|
|
52400
|
+
const meter = new Meter(ratio, {
|
|
52401
|
+
theme,
|
|
52402
|
+
warnAt: ctxWarnAt(stats),
|
|
52403
|
+
percent: (r) => approx + ctxPercentText(r * 100, false)
|
|
52404
|
+
}).render(40)[0] ?? "";
|
|
52405
|
+
const window2 = stats.contextTokens === void 0 && stats.contextWindow === void 0 ? "" : sep5 + `${stats.contextTokens === void 0 ? "?" : approx + formatTokenCount(stats.contextTokens)} / ${stats.contextWindow === void 0 ? "?" : formatTokenCount(stats.contextWindow)}`;
|
|
52406
|
+
const auto = autoCompactText(stats);
|
|
52407
|
+
const rows = [
|
|
52408
|
+
{
|
|
52409
|
+
key: m.model,
|
|
52410
|
+
value: theme.fg("accent", model) + sep5 + m.thinking(state.thinkingLevel) + sep5 + m.permission(permissionModeLabel(state.permissionMode))
|
|
52411
|
+
},
|
|
52412
|
+
{
|
|
52413
|
+
key: m.messages,
|
|
52414
|
+
value: [
|
|
52415
|
+
m.user(stats.userMessages),
|
|
52416
|
+
m.assistant(stats.assistantMessages),
|
|
52417
|
+
m.toolCalls(stats.toolCalls)
|
|
52418
|
+
].join(sep5)
|
|
52419
|
+
},
|
|
52420
|
+
{
|
|
52421
|
+
key: m.usage,
|
|
52422
|
+
value: [
|
|
52423
|
+
m.input(formatTokenCount(t.input)),
|
|
52424
|
+
m.output(formatTokenCount(t.output)),
|
|
52425
|
+
m.cacheRead(formatTokenCount(t.cacheRead)),
|
|
52426
|
+
m.cacheWrite(formatTokenCount(t.cacheWrite)),
|
|
52427
|
+
formatUsd2(stats.cost)
|
|
52428
|
+
].join(sep5)
|
|
52429
|
+
},
|
|
52430
|
+
{ key: m.context, value: meter + window2 + (auto === void 0 ? "" : sep5 + auto) }
|
|
52431
|
+
];
|
|
52432
|
+
const tasks = taskStatsText(session);
|
|
52433
|
+
if (tasks !== void 0) rows.push({ key: m.subagents, value: tasks });
|
|
52434
|
+
const external = externalRows(session);
|
|
52435
|
+
const externalSection = external.length > 0 ? ["", theme.bold(m.external), new Indent(keyValue(external, theme), 2)] : [];
|
|
52436
|
+
const file = state.sessionFile === void 0 ? m.notSaved : tildePath(state.sessionFile, options.home);
|
|
52437
|
+
const parts = [
|
|
52438
|
+
keyValue(rows, theme),
|
|
52439
|
+
"",
|
|
52440
|
+
...cacheSection(session, theme, now),
|
|
52441
|
+
...externalSection
|
|
52442
|
+
];
|
|
52443
|
+
return new Card(new Stack(parts), {
|
|
52444
|
+
theme,
|
|
52445
|
+
title: m.title(state.sessionId.slice(0, 8)),
|
|
52446
|
+
subtitle: file
|
|
52447
|
+
});
|
|
52448
|
+
}
|
|
52449
|
+
function cachePanel(session, theme, now = Date.now()) {
|
|
52450
|
+
return new Card(keyValue(cacheRows(session, now), theme), {
|
|
52451
|
+
theme,
|
|
52452
|
+
title: msg().panels.cache.title
|
|
52453
|
+
});
|
|
52454
|
+
}
|
|
52455
|
+
function permissionsPanel(runtime, session, theme) {
|
|
52456
|
+
const m = msg().panels.permissions;
|
|
52457
|
+
const rules = runtime.permission.rules;
|
|
52458
|
+
const mode = session.state.permissionMode;
|
|
52459
|
+
const order = mode === "auto" ? m.orderAuto : mode === "allowlist" ? m.orderAllowlist : m.orderDefault;
|
|
52460
|
+
const effect = (decision) => theme.fg(DECISION_COLOR[decision] ?? "text", decision.padEnd(5));
|
|
52461
|
+
const parts = [
|
|
52462
|
+
keyValue(
|
|
52463
|
+
[
|
|
52464
|
+
{
|
|
52465
|
+
key: m.mode,
|
|
52466
|
+
value: m.modeValue(permissionModeLabel(mode), mode, (t) => theme.fg("dim", t))
|
|
52467
|
+
},
|
|
52468
|
+
{ key: m.order, value: order }
|
|
52469
|
+
],
|
|
52470
|
+
theme,
|
|
52471
|
+
true
|
|
52472
|
+
),
|
|
52473
|
+
theme.bold(rules.length === 0 ? m.rulesNone : m.rules(rules.length))
|
|
52474
|
+
];
|
|
52475
|
+
if (rules.length > 0) {
|
|
52476
|
+
parts.push(
|
|
52477
|
+
new Indent(
|
|
52478
|
+
keyValue(
|
|
52479
|
+
rules.map((r) => ({
|
|
52480
|
+
key: effect(r.effect),
|
|
52481
|
+
value: `${r.raw} ${theme.fg("dim", `[${r.source}]`)}`
|
|
52482
|
+
})),
|
|
52483
|
+
theme
|
|
52484
|
+
),
|
|
52485
|
+
2
|
|
52486
|
+
)
|
|
52487
|
+
);
|
|
52488
|
+
}
|
|
52489
|
+
const recent = runtime.permission.autoDecisions?.() ?? [];
|
|
52490
|
+
if (recent.length > 0) {
|
|
52491
|
+
parts.push(theme.bold(m.recentAuto(recent.length)));
|
|
52492
|
+
parts.push(
|
|
52493
|
+
new Indent(
|
|
52494
|
+
keyValue(
|
|
52495
|
+
recent.map((d) => ({
|
|
52496
|
+
key: autoLayerText(d.layer),
|
|
52497
|
+
value: `${effect(d.decision)} ${d.toolName} ${d.summary} — ${d.reason}` + (d.cached === true ? theme.fg("dim", m.cached) : "")
|
|
52498
|
+
})),
|
|
52499
|
+
theme
|
|
52500
|
+
),
|
|
52501
|
+
2
|
|
52502
|
+
)
|
|
52503
|
+
);
|
|
52504
|
+
}
|
|
52505
|
+
return new Card(new Stack(parts), { theme });
|
|
52506
|
+
}
|
|
52507
|
+
var Stack, Indent, DECISION_COLOR;
|
|
52508
|
+
var init_panels2 = __esm({
|
|
52509
|
+
"src/modes/interactive/panels.ts"() {
|
|
52510
|
+
"use strict";
|
|
52511
|
+
init_i18n();
|
|
52512
|
+
init_modes();
|
|
52513
|
+
init_tui2();
|
|
52514
|
+
init_status_ctx();
|
|
52515
|
+
init_session_report();
|
|
52516
|
+
init_startup_screen();
|
|
52517
|
+
Stack = class {
|
|
52518
|
+
constructor(parts) {
|
|
52519
|
+
this.parts = parts;
|
|
52520
|
+
}
|
|
52521
|
+
parts;
|
|
52522
|
+
render(width2) {
|
|
52523
|
+
return this.parts.flatMap((part) => typeof part === "string" ? [part] : part.render(width2));
|
|
52524
|
+
}
|
|
52525
|
+
invalidate() {
|
|
52526
|
+
for (const part of this.parts) if (typeof part !== "string") part.invalidate();
|
|
52527
|
+
}
|
|
52528
|
+
};
|
|
52529
|
+
Indent = class {
|
|
52530
|
+
constructor(child, columns) {
|
|
52531
|
+
this.child = child;
|
|
52532
|
+
this.columns = columns;
|
|
52533
|
+
}
|
|
52534
|
+
child;
|
|
52535
|
+
columns;
|
|
52536
|
+
render(width2) {
|
|
52537
|
+
const pad3 = " ".repeat(this.columns);
|
|
52538
|
+
return this.child.render(Math.max(1, width2 - this.columns)).map((line2) => line2 === "" ? "" : pad3 + line2);
|
|
52539
|
+
}
|
|
52540
|
+
invalidate() {
|
|
52541
|
+
this.child.invalidate();
|
|
52542
|
+
}
|
|
52543
|
+
};
|
|
52544
|
+
DECISION_COLOR = {
|
|
52545
|
+
allow: "success",
|
|
52546
|
+
deny: "error",
|
|
52547
|
+
ask: "warning"
|
|
52548
|
+
};
|
|
52549
|
+
}
|
|
52550
|
+
});
|
|
52551
|
+
|
|
52552
|
+
// src/modes/context-report.ts
|
|
52553
|
+
function contextSnapshot(session) {
|
|
52554
|
+
let messages = session.messages;
|
|
52555
|
+
let estimate;
|
|
52556
|
+
let compaction = {};
|
|
52557
|
+
let prefixPending = false;
|
|
52558
|
+
if (session instanceof AgentSessionImpl) {
|
|
52559
|
+
const branch = session.manager.branch();
|
|
52560
|
+
const items = buildProjection(branch).items;
|
|
52561
|
+
messages = items.map((item) => item.message);
|
|
52562
|
+
estimate = estimateProjectedTokens(items, branch);
|
|
52563
|
+
compaction = session.options.compaction ?? {};
|
|
52564
|
+
if (!messages.some((message) => "role" in message && message.role === "system")) {
|
|
52565
|
+
prefixPending = true;
|
|
52566
|
+
messages = [pendingPrefixMessage(session), ...messages];
|
|
52567
|
+
}
|
|
52568
|
+
} else estimate = estimateContextTokens(messages);
|
|
52569
|
+
const stats = session.getStats();
|
|
52570
|
+
if (stats.contextTokens !== void 0) estimate = { ...estimate, tokens: stats.contextTokens };
|
|
52571
|
+
const window2 = stats.contextWindow;
|
|
52572
|
+
const reserve = compaction.reserveTokens ?? DEFAULT_COMPACTION_SETTINGS.reserveTokens;
|
|
52573
|
+
const budget = window2 === void 0 ? void 0 : Math.max(0, window2 - reserve);
|
|
52574
|
+
const percent3 = window2 === void 0 || window2 <= 0 ? void 0 : Math.min(100, Math.round(estimate.tokens / window2 * 1e3) / 10);
|
|
52575
|
+
return {
|
|
52576
|
+
breakdown: breakdownMessages(messages),
|
|
52577
|
+
estimate,
|
|
52578
|
+
prefixPending,
|
|
52579
|
+
window: window2,
|
|
52580
|
+
percent: percent3,
|
|
52581
|
+
autoCompaction: session.state.autoCompaction,
|
|
52582
|
+
compactAt: budget,
|
|
52583
|
+
pruneAt: budget === void 0 ? void 0 : prunePolicy(budget, compaction.prune).triggerTokens
|
|
52584
|
+
};
|
|
52585
|
+
}
|
|
52586
|
+
function headerRows(snap) {
|
|
52587
|
+
const m = msg().report.contextReport;
|
|
52588
|
+
const { estimate, window: window2 } = snap;
|
|
52589
|
+
const rows = [
|
|
52590
|
+
{
|
|
52591
|
+
key: m.keyUsed,
|
|
52592
|
+
value: m.used(
|
|
52593
|
+
formatTokenCount(estimate.tokens),
|
|
52594
|
+
window2 === void 0 ? "?" : formatTokenCount(window2),
|
|
52595
|
+
snap.percent === void 0 ? void 0 : `${snap.percent.toFixed(1)}%`
|
|
52596
|
+
)
|
|
52597
|
+
}
|
|
52598
|
+
];
|
|
52599
|
+
if (window2 !== void 0)
|
|
52600
|
+
rows.push({
|
|
52601
|
+
key: m.keyLeft,
|
|
52602
|
+
value: m.left(formatTokenCount(Math.max(0, window2 - estimate.tokens)))
|
|
52603
|
+
});
|
|
52604
|
+
rows.push({
|
|
52605
|
+
key: m.keySource,
|
|
52606
|
+
value: snap.prefixPending ? m.sourcePrefix : estimate.lastUsageIndex === null ? m.sourceEstimate : m.sourceUsage(
|
|
52607
|
+
formatTokenCount(estimate.usageTokens),
|
|
52608
|
+
formatTokenCount(estimate.trailingTokens)
|
|
52609
|
+
)
|
|
52610
|
+
});
|
|
52611
|
+
let auto;
|
|
52612
|
+
if (!snap.autoCompaction) auto = m.autoCompactOff;
|
|
52613
|
+
else if (snap.compactAt === void 0) auto = m.windowUnknown;
|
|
52614
|
+
else if (estimate.tokens >= snap.compactAt)
|
|
52615
|
+
auto = m.autoCompactReached(formatTokenCount(snap.compactAt));
|
|
52616
|
+
else
|
|
52617
|
+
auto = m.autoCompact(
|
|
52618
|
+
formatTokenCount(snap.compactAt),
|
|
52619
|
+
formatTokenCount(snap.compactAt - estimate.tokens)
|
|
52620
|
+
);
|
|
52621
|
+
rows.push({ key: m.keyAutoCompact, value: auto });
|
|
52622
|
+
if (snap.autoCompaction && snap.pruneAt !== void 0)
|
|
52623
|
+
rows.push({ key: m.keyPrune, value: m.prune(formatTokenCount(Math.floor(snap.pruneAt))) });
|
|
52624
|
+
return rows;
|
|
52625
|
+
}
|
|
52626
|
+
function partName(entry, name) {
|
|
52627
|
+
const names = msg().report.contextReport.partNames;
|
|
52628
|
+
if (entry.category === "summaries" || entry.category === "images")
|
|
52629
|
+
return names[name] ?? name;
|
|
52630
|
+
return name;
|
|
52631
|
+
}
|
|
52632
|
+
function partsText(entry) {
|
|
52633
|
+
const m = msg().report.contextReport;
|
|
52634
|
+
const shown2 = entry.parts.slice(0, MAX_PARTS).map((part) => `${partName(entry, part.name)} ${formatTokenCount(part.tokens)}`);
|
|
52635
|
+
if (entry.parts.length > MAX_PARTS) shown2.push(m.more(entry.parts.length - MAX_PARTS));
|
|
52636
|
+
if (entry.category === "images" && entry.count > 0) shown2.unshift(m.images(entry.count));
|
|
52637
|
+
return shown2.join(" · ");
|
|
52638
|
+
}
|
|
52639
|
+
function categoryRows(breakdown, theme) {
|
|
52640
|
+
const m = msg().report.contextReport;
|
|
52641
|
+
const dim = (text) => theme === void 0 ? text : theme.fg("dim", text);
|
|
52642
|
+
return breakdown.entries.map((entry) => {
|
|
52643
|
+
const ratio = breakdown.total > 0 ? entry.tokens / breakdown.total : void 0;
|
|
52644
|
+
const meter = new Meter(ratio, { warnAt: 2, dangerAt: 2, ...theme ? { theme } : {} });
|
|
52645
|
+
const parts = partsText(entry);
|
|
52646
|
+
return {
|
|
52647
|
+
key: m.categories[entry.category],
|
|
52648
|
+
value: `${formatTokenCount(entry.tokens).padStart(6)} ${meter.render(40)[0] ?? ""}` + (parts === "" ? "" : ` ${dim(parts)}`)
|
|
52649
|
+
};
|
|
52650
|
+
});
|
|
52651
|
+
}
|
|
52652
|
+
function largestRows(breakdown) {
|
|
52653
|
+
return largestToolResults(breakdown, CONTEXT_TOP_RESULTS).map((result) => ({
|
|
52654
|
+
key: `#${result.ordinal}`,
|
|
52655
|
+
value: `${formatTokenCount(result.tokens).padStart(6)} ${result.toolName}`
|
|
52656
|
+
}));
|
|
52657
|
+
}
|
|
52658
|
+
function describeContext(session) {
|
|
52659
|
+
const m = msg().report.contextReport;
|
|
52660
|
+
const snap = contextSnapshot(session);
|
|
52661
|
+
const { breakdown } = snap;
|
|
52662
|
+
const lines2 = [m.title, ...renderRows(headerRows(snap), " "), ""];
|
|
52663
|
+
lines2.push(m.breakdown(formatTokenCount(breakdown.total)));
|
|
52664
|
+
lines2.push(
|
|
52665
|
+
` ${snap.prefixPending ? m.prefixEstimated : breakdown.hasSystem ? m.prefixCounted : m.prefixPending}`
|
|
52666
|
+
);
|
|
52667
|
+
if (breakdown.total === 0) lines2.push(` ${m.empty}`);
|
|
52668
|
+
else lines2.push(...renderRows(categoryRows(breakdown, void 0), " "));
|
|
52669
|
+
lines2.push("", m.largest(CONTEXT_TOP_RESULTS));
|
|
52670
|
+
const largest = largestRows(breakdown);
|
|
52671
|
+
if (largest.length === 0) lines2.push(` ${m.noToolResults}`);
|
|
52672
|
+
else lines2.push(...renderRows(largest, " "));
|
|
52673
|
+
return lines2.join("\n");
|
|
52674
|
+
}
|
|
52675
|
+
function contextPanel(session, theme) {
|
|
52676
|
+
const m = msg().report.contextReport;
|
|
52677
|
+
const snap = contextSnapshot(session);
|
|
52678
|
+
const { breakdown } = snap;
|
|
52679
|
+
const table2 = (rows, wrap2 = false) => new KeyValue(rows, { theme, maxKeyRatio: 0.3, ...wrap2 ? { wrap: true } : {} });
|
|
52680
|
+
const largest = largestRows(breakdown);
|
|
52681
|
+
const parts = [
|
|
52682
|
+
table2(headerRows(snap)),
|
|
52683
|
+
"",
|
|
52684
|
+
theme.bold(m.breakdown(formatTokenCount(breakdown.total))),
|
|
52685
|
+
new Indent(
|
|
52686
|
+
new Stack([
|
|
52687
|
+
new Text(
|
|
52688
|
+
theme.fg(
|
|
52689
|
+
"dim",
|
|
52690
|
+
snap.prefixPending ? m.prefixEstimated : breakdown.hasSystem ? m.prefixCounted : m.prefixPending
|
|
52691
|
+
)
|
|
52692
|
+
),
|
|
52693
|
+
breakdown.total === 0 ? theme.fg("dim", m.empty) : table2(categoryRows(breakdown, theme), true)
|
|
52694
|
+
]),
|
|
52695
|
+
2
|
|
52696
|
+
),
|
|
52697
|
+
"",
|
|
52698
|
+
theme.bold(m.largest(CONTEXT_TOP_RESULTS)),
|
|
52699
|
+
largest.length === 0 ? new Indent(new Stack([theme.fg("dim", m.noToolResults)]), 2) : new Indent(table2(largest), 2)
|
|
52700
|
+
];
|
|
52701
|
+
return new Card(new Stack(parts), { theme, title: m.title });
|
|
52702
|
+
}
|
|
52703
|
+
var CONTEXT_TOP_RESULTS, MAX_PARTS;
|
|
52704
|
+
var init_context_report = __esm({
|
|
52705
|
+
"src/modes/context-report.ts"() {
|
|
52706
|
+
"use strict";
|
|
52707
|
+
init_session2();
|
|
52708
|
+
init_session_compaction();
|
|
52709
|
+
init_breakdown();
|
|
52710
|
+
init_estimate();
|
|
52711
|
+
init_prune_tier();
|
|
52712
|
+
init_i18n();
|
|
52713
|
+
init_projection();
|
|
52714
|
+
init_tui2();
|
|
52715
|
+
init_panels2();
|
|
52716
|
+
init_session_report();
|
|
52717
|
+
CONTEXT_TOP_RESULTS = 5;
|
|
52718
|
+
MAX_PARTS = 6;
|
|
52719
|
+
}
|
|
52720
|
+
});
|
|
52721
|
+
|
|
51759
52722
|
// src/modes/commands-core.ts
|
|
51760
52723
|
function command(name, key, args) {
|
|
51761
52724
|
const info2 = {
|
|
@@ -51927,6 +52890,8 @@ async function runSlashCommand(line2, ctx) {
|
|
|
51927
52890
|
}
|
|
51928
52891
|
case "session":
|
|
51929
52892
|
return { kind: "handled", message: describeSession(session) };
|
|
52893
|
+
case "context":
|
|
52894
|
+
return { kind: "handled", message: describeContext(session) };
|
|
51930
52895
|
case "cache":
|
|
51931
52896
|
return { kind: "handled", message: cacheCommand(session, args) };
|
|
51932
52897
|
case "rewind":
|
|
@@ -51977,6 +52942,7 @@ var init_commands_core = __esm({
|
|
|
51977
52942
|
init_tasks_report();
|
|
51978
52943
|
init_task_background();
|
|
51979
52944
|
init_session_report();
|
|
52945
|
+
init_context_report();
|
|
51980
52946
|
init_i18n();
|
|
51981
52947
|
BUILTIN_COMMANDS = [
|
|
51982
52948
|
command("help", "help"),
|
|
@@ -51991,6 +52957,7 @@ var init_commands_core = __esm({
|
|
|
51991
52957
|
command("tools", "tools", { key: "toolsArgs" }),
|
|
51992
52958
|
command("hooks", "hooks"),
|
|
51993
52959
|
command("session", "session"),
|
|
52960
|
+
command("context", "context"),
|
|
51994
52961
|
command("cache", "cache", "[warm off|streaming|idle | fingerprint]"),
|
|
51995
52962
|
command("statusline", "statusline", "[full|compact]"),
|
|
51996
52963
|
command("plan", "plan", { key: "planArgs" }),
|
|
@@ -52539,55 +53506,6 @@ var init_bypass = __esm({
|
|
|
52539
53506
|
}
|
|
52540
53507
|
});
|
|
52541
53508
|
|
|
52542
|
-
// src/cli/startup-screen.ts
|
|
52543
|
-
function startupScreenLevel(runtime) {
|
|
52544
|
-
return runtime.config.ui?.quietStartup ?? "normal";
|
|
52545
|
-
}
|
|
52546
|
-
function trustSourceLabel(source) {
|
|
52547
|
-
const labels2 = msg().cli.startupScreen.trustSource;
|
|
52548
|
-
return source === "trust-file" ? labels2.trustFile : labels2[source];
|
|
52549
|
-
}
|
|
52550
|
-
function tildePath(path, home) {
|
|
52551
|
-
if (home === void 0 || home === "") return path;
|
|
52552
|
-
const trimmed = /[\\/]$/.test(home) ? home.slice(0, -1) : home;
|
|
52553
|
-
if (path === trimmed) return "~";
|
|
52554
|
-
const next = path[trimmed.length];
|
|
52555
|
-
return path.startsWith(trimmed) && (next === "/" || next === "\\") ? `~${path.slice(trimmed.length)}` : path;
|
|
52556
|
-
}
|
|
52557
|
-
function startupInfo(runtime, home) {
|
|
52558
|
-
const { resources } = runtime;
|
|
52559
|
-
const info2 = {
|
|
52560
|
-
version: AMA_VERSION,
|
|
52561
|
-
model: formatModelRef(runtime.model),
|
|
52562
|
-
thinking: runtime.thinkingLevel,
|
|
52563
|
-
cwd: tildePath(runtime.paths.cwd, home),
|
|
52564
|
-
trusted: runtime.trust.trusted,
|
|
52565
|
-
trustSource: trustSourceLabel(runtime.trust.source),
|
|
52566
|
-
permissionMode: runtime.session.state.permissionMode,
|
|
52567
|
-
preset: runtime.config.tools?.preset ?? "default",
|
|
52568
|
-
codemode: effectiveCodemodeMode(runtime.config),
|
|
52569
|
-
contextFiles: resources.contextFiles.map((f) => (0, import_node_path93.basename)(f.path)),
|
|
52570
|
-
skills: resources.skills.filter((s2) => !isBuiltinSkill(s2)).length,
|
|
52571
|
-
prompts: resources.prompts.length,
|
|
52572
|
-
hooks: runtime.hooks.list().length,
|
|
52573
|
-
warnings: runtime.warnings.length
|
|
52574
|
-
};
|
|
52575
|
-
if (runtime.host !== void 0) info2.host = runtime.host.adapter.id;
|
|
52576
|
-
return info2;
|
|
52577
|
-
}
|
|
52578
|
-
var import_node_path93;
|
|
52579
|
-
var init_startup_screen = __esm({
|
|
52580
|
-
"src/cli/startup-screen.ts"() {
|
|
52581
|
-
"use strict";
|
|
52582
|
-
init_builtin3();
|
|
52583
|
-
import_node_path93 = require("node:path");
|
|
52584
|
-
init_channels();
|
|
52585
|
-
init_presets2();
|
|
52586
|
-
init_i18n();
|
|
52587
|
-
init_version();
|
|
52588
|
-
}
|
|
52589
|
-
});
|
|
52590
|
-
|
|
52591
53509
|
// src/modes/interactive/config-panel.ts
|
|
52592
53510
|
function settingValueText(spec2, value, theme) {
|
|
52593
53511
|
if (value.value === void 0 && spec2.key === "ui.ascii")
|
|
@@ -52850,8 +53768,8 @@ var init_config_panel = __esm({
|
|
|
52850
53768
|
const dynamic = value.value === void 0 ? settingDynamicDefault(row3.id) : void 0;
|
|
52851
53769
|
const text = dynamic === void 0 ? doc : `${doc} · ${dynamic}`;
|
|
52852
53770
|
const spec2 = settingsRegistry().find((x) => x.key === row3.id);
|
|
52853
|
-
const
|
|
52854
|
-
const lines2 =
|
|
53771
|
+
const blocked2 = spec2 === void 0 ? void 0 : blockedReason(spec2, value, this.scope);
|
|
53772
|
+
const lines2 = blocked2 === void 0 ? [] : [theme.fg("warning", truncateToWidth(blocked2, width2))];
|
|
52855
53773
|
if (text !== "") lines2.push(...wrapTextWithAnsi(theme.fg("dim", text), width2));
|
|
52856
53774
|
return lines2.slice(0, 3);
|
|
52857
53775
|
}
|
|
@@ -53894,8 +54812,8 @@ var init_config_ui = __esm({
|
|
|
53894
54812
|
const spec2 = settingSpec(key);
|
|
53895
54813
|
if (panel === void 0 || spec2 === void 0) return;
|
|
53896
54814
|
const current3 = getConfigValue(readSnapshot(this.input()), key);
|
|
53897
|
-
const
|
|
53898
|
-
if (
|
|
54815
|
+
const blocked2 = blockedReason(spec2, current3, scope);
|
|
54816
|
+
if (blocked2 !== void 0) return panel.setNotice(blocked2, "warning");
|
|
53899
54817
|
const value = current3.value;
|
|
53900
54818
|
switch (spec2.kind) {
|
|
53901
54819
|
case "bool":
|
|
@@ -56005,6 +56923,8 @@ function taskRow(info2, ctx) {
|
|
|
56005
56923
|
status,
|
|
56006
56924
|
turns: Math.max(state?.turns ?? 0, info2.turns ?? 0)
|
|
56007
56925
|
};
|
|
56926
|
+
const context = formatTaskContext(info2);
|
|
56927
|
+
if (context !== void 0) row3.context = context;
|
|
56008
56928
|
const tool = state?.tools.at(-1);
|
|
56009
56929
|
if (tool !== void 0 && status !== "queued") row3.tool = tool;
|
|
56010
56930
|
if (status !== "queued") {
|
|
@@ -56020,6 +56940,7 @@ function rowFacts(row3, withTool = true) {
|
|
|
56020
56940
|
const facts = [statusLabel(row3.status)];
|
|
56021
56941
|
if (row3.elapsedMs !== void 0) facts[0] += ` ${formatElapsed(row3.elapsedMs)}`;
|
|
56022
56942
|
if (row3.turns > 0) facts.push(msg().agents.turns(row3.turns));
|
|
56943
|
+
if (row3.context !== void 0) facts.push(msg().agents.context(row3.context));
|
|
56023
56944
|
if (withTool && row3.tool !== void 0 && row3.status === "running") facts.push(row3.tool);
|
|
56024
56945
|
return facts.join(" · ");
|
|
56025
56946
|
}
|
|
@@ -56027,6 +56948,7 @@ var BAR_ROWS, BAR_RETAIN_MS, ACTIVE, AgentBar;
|
|
|
56027
56948
|
var init_agent_bar = __esm({
|
|
56028
56949
|
"src/modes/interactive/agent-bar.ts"() {
|
|
56029
56950
|
"use strict";
|
|
56951
|
+
init_task_record();
|
|
56030
56952
|
init_i18n();
|
|
56031
56953
|
init_tui2();
|
|
56032
56954
|
BAR_ROWS = 3;
|
|
@@ -56611,171 +57533,6 @@ var init_agent_view = __esm({
|
|
|
56611
57533
|
}
|
|
56612
57534
|
});
|
|
56613
57535
|
|
|
56614
|
-
// src/modes/interactive/panels.ts
|
|
56615
|
-
function keyValue(rows, theme, wrap2 = false) {
|
|
56616
|
-
return new KeyValue(rows, { theme, maxKeyRatio: 0.3, ...wrap2 ? { wrap: true } : {} });
|
|
56617
|
-
}
|
|
56618
|
-
function cacheSection(session, theme, now) {
|
|
56619
|
-
return [
|
|
56620
|
-
theme.bold(msg().panels.cache.title),
|
|
56621
|
-
new Indent(keyValue(cacheRows(session, now), theme), 2)
|
|
56622
|
-
];
|
|
56623
|
-
}
|
|
56624
|
-
function sessionPanel(session, theme, options = {}) {
|
|
56625
|
-
const m = msg().panels.session;
|
|
56626
|
-
const now = options.now ?? Date.now();
|
|
56627
|
-
const state = session.state;
|
|
56628
|
-
const stats = session.getStats();
|
|
56629
|
-
const t = stats.tokens;
|
|
56630
|
-
const sep5 = theme.fg("dim", " · ");
|
|
56631
|
-
const model = state.model === void 0 ? "?" : `${state.model.provider}/${state.model.id}`;
|
|
56632
|
-
const ratio = stats.contextPercent === void 0 ? void 0 : stats.contextPercent / 100;
|
|
56633
|
-
const meter = new Meter(ratio, { theme }).render(40)[0] ?? "";
|
|
56634
|
-
const window2 = stats.contextTokens === void 0 && stats.contextWindow === void 0 ? "" : sep5 + `${stats.contextTokens === void 0 ? "?" : formatTokenCount(stats.contextTokens)} / ${stats.contextWindow === void 0 ? "?" : formatTokenCount(stats.contextWindow)}`;
|
|
56635
|
-
const rows = [
|
|
56636
|
-
{
|
|
56637
|
-
key: m.model,
|
|
56638
|
-
value: theme.fg("accent", model) + sep5 + m.thinking(state.thinkingLevel) + sep5 + m.permission(permissionModeLabel(state.permissionMode))
|
|
56639
|
-
},
|
|
56640
|
-
{
|
|
56641
|
-
key: m.messages,
|
|
56642
|
-
value: [
|
|
56643
|
-
m.user(stats.userMessages),
|
|
56644
|
-
m.assistant(stats.assistantMessages),
|
|
56645
|
-
m.toolCalls(stats.toolCalls)
|
|
56646
|
-
].join(sep5)
|
|
56647
|
-
},
|
|
56648
|
-
{
|
|
56649
|
-
key: m.usage,
|
|
56650
|
-
value: [
|
|
56651
|
-
m.input(formatTokenCount(t.input)),
|
|
56652
|
-
m.output(formatTokenCount(t.output)),
|
|
56653
|
-
m.cacheRead(formatTokenCount(t.cacheRead)),
|
|
56654
|
-
m.cacheWrite(formatTokenCount(t.cacheWrite)),
|
|
56655
|
-
formatUsd2(stats.cost)
|
|
56656
|
-
].join(sep5)
|
|
56657
|
-
},
|
|
56658
|
-
{ key: m.context, value: meter + window2 }
|
|
56659
|
-
];
|
|
56660
|
-
const tasks = taskStatsText(session);
|
|
56661
|
-
if (tasks !== void 0) rows.push({ key: m.subagents, value: tasks });
|
|
56662
|
-
const external = externalRows(session);
|
|
56663
|
-
const externalSection = external.length > 0 ? ["", theme.bold(m.external), new Indent(keyValue(external, theme), 2)] : [];
|
|
56664
|
-
const file = state.sessionFile === void 0 ? m.notSaved : tildePath(state.sessionFile, options.home);
|
|
56665
|
-
const parts = [
|
|
56666
|
-
keyValue(rows, theme),
|
|
56667
|
-
"",
|
|
56668
|
-
...cacheSection(session, theme, now),
|
|
56669
|
-
...externalSection
|
|
56670
|
-
];
|
|
56671
|
-
return new Card(new Stack(parts), {
|
|
56672
|
-
theme,
|
|
56673
|
-
title: m.title(state.sessionId.slice(0, 8)),
|
|
56674
|
-
subtitle: file
|
|
56675
|
-
});
|
|
56676
|
-
}
|
|
56677
|
-
function cachePanel(session, theme, now = Date.now()) {
|
|
56678
|
-
return new Card(keyValue(cacheRows(session, now), theme), {
|
|
56679
|
-
theme,
|
|
56680
|
-
title: msg().panels.cache.title
|
|
56681
|
-
});
|
|
56682
|
-
}
|
|
56683
|
-
function permissionsPanel(runtime, session, theme) {
|
|
56684
|
-
const m = msg().panels.permissions;
|
|
56685
|
-
const rules = runtime.permission.rules;
|
|
56686
|
-
const mode = session.state.permissionMode;
|
|
56687
|
-
const order = mode === "auto" ? m.orderAuto : mode === "allowlist" ? m.orderAllowlist : m.orderDefault;
|
|
56688
|
-
const effect = (decision) => theme.fg(DECISION_COLOR[decision] ?? "text", decision.padEnd(5));
|
|
56689
|
-
const parts = [
|
|
56690
|
-
keyValue(
|
|
56691
|
-
[
|
|
56692
|
-
{
|
|
56693
|
-
key: m.mode,
|
|
56694
|
-
value: m.modeValue(permissionModeLabel(mode), mode, (t) => theme.fg("dim", t))
|
|
56695
|
-
},
|
|
56696
|
-
{ key: m.order, value: order }
|
|
56697
|
-
],
|
|
56698
|
-
theme,
|
|
56699
|
-
true
|
|
56700
|
-
),
|
|
56701
|
-
theme.bold(rules.length === 0 ? m.rulesNone : m.rules(rules.length))
|
|
56702
|
-
];
|
|
56703
|
-
if (rules.length > 0) {
|
|
56704
|
-
parts.push(
|
|
56705
|
-
new Indent(
|
|
56706
|
-
keyValue(
|
|
56707
|
-
rules.map((r) => ({
|
|
56708
|
-
key: effect(r.effect),
|
|
56709
|
-
value: `${r.raw} ${theme.fg("dim", `[${r.source}]`)}`
|
|
56710
|
-
})),
|
|
56711
|
-
theme
|
|
56712
|
-
),
|
|
56713
|
-
2
|
|
56714
|
-
)
|
|
56715
|
-
);
|
|
56716
|
-
}
|
|
56717
|
-
const recent = runtime.permission.autoDecisions?.() ?? [];
|
|
56718
|
-
if (recent.length > 0) {
|
|
56719
|
-
parts.push(theme.bold(m.recentAuto(recent.length)));
|
|
56720
|
-
parts.push(
|
|
56721
|
-
new Indent(
|
|
56722
|
-
keyValue(
|
|
56723
|
-
recent.map((d) => ({
|
|
56724
|
-
key: autoLayerText(d.layer),
|
|
56725
|
-
value: `${effect(d.decision)} ${d.toolName} ${d.summary} — ${d.reason}` + (d.cached === true ? theme.fg("dim", m.cached) : "")
|
|
56726
|
-
})),
|
|
56727
|
-
theme
|
|
56728
|
-
),
|
|
56729
|
-
2
|
|
56730
|
-
)
|
|
56731
|
-
);
|
|
56732
|
-
}
|
|
56733
|
-
return new Card(new Stack(parts), { theme });
|
|
56734
|
-
}
|
|
56735
|
-
var Stack, Indent, DECISION_COLOR;
|
|
56736
|
-
var init_panels2 = __esm({
|
|
56737
|
-
"src/modes/interactive/panels.ts"() {
|
|
56738
|
-
"use strict";
|
|
56739
|
-
init_i18n();
|
|
56740
|
-
init_modes();
|
|
56741
|
-
init_tui2();
|
|
56742
|
-
init_session_report();
|
|
56743
|
-
init_startup_screen();
|
|
56744
|
-
Stack = class {
|
|
56745
|
-
constructor(parts) {
|
|
56746
|
-
this.parts = parts;
|
|
56747
|
-
}
|
|
56748
|
-
parts;
|
|
56749
|
-
render(width2) {
|
|
56750
|
-
return this.parts.flatMap((part) => typeof part === "string" ? [part] : part.render(width2));
|
|
56751
|
-
}
|
|
56752
|
-
invalidate() {
|
|
56753
|
-
for (const part of this.parts) if (typeof part !== "string") part.invalidate();
|
|
56754
|
-
}
|
|
56755
|
-
};
|
|
56756
|
-
Indent = class {
|
|
56757
|
-
constructor(child, columns) {
|
|
56758
|
-
this.child = child;
|
|
56759
|
-
this.columns = columns;
|
|
56760
|
-
}
|
|
56761
|
-
child;
|
|
56762
|
-
columns;
|
|
56763
|
-
render(width2) {
|
|
56764
|
-
const pad3 = " ".repeat(this.columns);
|
|
56765
|
-
return this.child.render(Math.max(1, width2 - this.columns)).map((line2) => line2 === "" ? "" : pad3 + line2);
|
|
56766
|
-
}
|
|
56767
|
-
invalidate() {
|
|
56768
|
-
this.child.invalidate();
|
|
56769
|
-
}
|
|
56770
|
-
};
|
|
56771
|
-
DECISION_COLOR = {
|
|
56772
|
-
allow: "success",
|
|
56773
|
-
deny: "error",
|
|
56774
|
-
ask: "warning"
|
|
56775
|
-
};
|
|
56776
|
-
}
|
|
56777
|
-
});
|
|
56778
|
-
|
|
56779
57536
|
// src/modes/interactive/agent-panels.ts
|
|
56780
57537
|
function planPanel(controller, session, theme, displayPath3 = (p) => p) {
|
|
56781
57538
|
const m = msg().panels.plan;
|
|
@@ -58141,6 +58898,7 @@ var init_commands2 = __esm({
|
|
|
58141
58898
|
init_fake_visibility();
|
|
58142
58899
|
init_modes();
|
|
58143
58900
|
init_commands_core();
|
|
58901
|
+
init_context_report();
|
|
58144
58902
|
init_message_view();
|
|
58145
58903
|
init_panels2();
|
|
58146
58904
|
init_pickers();
|
|
@@ -58160,6 +58918,12 @@ var init_commands2 = __esm({
|
|
|
58160
58918
|
await ui.traceView(args === "" ? void 0 : args);
|
|
58161
58919
|
return true;
|
|
58162
58920
|
},
|
|
58921
|
+
context: async (ui) => {
|
|
58922
|
+
const theme = ui.theme?.();
|
|
58923
|
+
if (ui.panel === void 0 || theme === void 0) return false;
|
|
58924
|
+
ui.panel(contextPanel(ui.session(), theme));
|
|
58925
|
+
return true;
|
|
58926
|
+
},
|
|
58163
58927
|
memory: async (ui, args) => {
|
|
58164
58928
|
if (ui.memoryPanel === void 0) return false;
|
|
58165
58929
|
await ui.memoryPanel(args);
|
|
@@ -58657,7 +59421,7 @@ var init_status_line = __esm({
|
|
|
58657
59421
|
stat16
|
|
58658
59422
|
);
|
|
58659
59423
|
}
|
|
58660
|
-
const usage = usageItems(stats, this.bar.queued(), this.source, theme);
|
|
59424
|
+
const usage = usageItems(stats, this.bar.queued(), this.source, theme, true);
|
|
58661
59425
|
add3("right", usage.tokens, PRIORITY.tokens);
|
|
58662
59426
|
add3("right", usage.cache, PRIORITY.cache);
|
|
58663
59427
|
add3("right", usage.rebill, PRIORITY.rebill);
|
|
@@ -60717,6 +61481,16 @@ var init_run_indicator = __esm({
|
|
|
60717
61481
|
function createSessionEventHandler(deps) {
|
|
60718
61482
|
const { view, tools, status, area, agentUi, indicator, session, setQueue, notice, render } = deps;
|
|
60719
61483
|
const images = new ImageBudgetNotices((text) => notice("info", text));
|
|
61484
|
+
const windowHinted = /* @__PURE__ */ new Set();
|
|
61485
|
+
const refresh = () => {
|
|
61486
|
+
status.refresh();
|
|
61487
|
+
if (status.current().contextWindow !== void 0) return;
|
|
61488
|
+
const model = session().state.model;
|
|
61489
|
+
const ref = model === void 0 ? void 0 : formatModelRef(model);
|
|
61490
|
+
if (ref === void 0 || windowHinted.has(ref)) return;
|
|
61491
|
+
windowHinted.add(ref);
|
|
61492
|
+
view.addNotice("info", msg().interactive.statusLine.noWindow(ref));
|
|
61493
|
+
};
|
|
60720
61494
|
return (event) => {
|
|
60721
61495
|
if (area.onEvent(event) || agentUi().onEvent(event)) {
|
|
60722
61496
|
if (event.type === "subagent_start" || event.type === "subagent_end") indicator.sync();
|
|
@@ -60727,7 +61501,7 @@ function createSessionEventHandler(deps) {
|
|
|
60727
61501
|
case "agent_settled":
|
|
60728
61502
|
if (event.warning !== void 0 && event.warning !== LIMIT_WARNING)
|
|
60729
61503
|
view.addNotice("warn", event.warning);
|
|
60730
|
-
|
|
61504
|
+
refresh();
|
|
60731
61505
|
break;
|
|
60732
61506
|
case "message_start": {
|
|
60733
61507
|
const message = event.message;
|
|
@@ -60740,12 +61514,14 @@ function createSessionEventHandler(deps) {
|
|
|
60740
61514
|
}
|
|
60741
61515
|
case "message_update":
|
|
60742
61516
|
view.updateAssistant(event.message);
|
|
61517
|
+
status.noteStreaming(event.message.usage);
|
|
60743
61518
|
break;
|
|
60744
61519
|
case "message_end":
|
|
60745
61520
|
if (event.message.role === "assistant") {
|
|
60746
61521
|
view.endAssistant(event.message);
|
|
61522
|
+
status.clearStreaming();
|
|
60747
61523
|
status.refresh();
|
|
60748
|
-
}
|
|
61524
|
+
} else if (event.message.role === "user") refresh();
|
|
60749
61525
|
break;
|
|
60750
61526
|
case "tool_execution_start": {
|
|
60751
61527
|
const started = tools.start(event);
|
|
@@ -60792,7 +61568,7 @@ function createSessionEventHandler(deps) {
|
|
|
60792
61568
|
case "model_changed":
|
|
60793
61569
|
case "thinking_level_changed":
|
|
60794
61570
|
case "session_changed":
|
|
60795
|
-
|
|
61571
|
+
refresh();
|
|
60796
61572
|
render();
|
|
60797
61573
|
return;
|
|
60798
61574
|
default:
|
|
@@ -60806,11 +61582,407 @@ var init_session_events = __esm({
|
|
|
60806
61582
|
"src/modes/interactive/session-events.ts"() {
|
|
60807
61583
|
"use strict";
|
|
60808
61584
|
init_i18n();
|
|
61585
|
+
init_channels();
|
|
60809
61586
|
init_session_report();
|
|
60810
61587
|
init_event_notices();
|
|
60811
61588
|
}
|
|
60812
61589
|
});
|
|
60813
61590
|
|
|
61591
|
+
// src/tui/program-status.ts
|
|
61592
|
+
function sanitizeLine(text) {
|
|
61593
|
+
return text.replace(/[\x00-\x1f\x7f-\x9f]/g, " ").replace(/\s+/g, " ").trim();
|
|
61594
|
+
}
|
|
61595
|
+
function truncateUtf8(text, maxBytes) {
|
|
61596
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
|
|
61597
|
+
const budget = maxBytes - Buffer.byteLength(ELLIPSIS, "utf8");
|
|
61598
|
+
let used = 0;
|
|
61599
|
+
let out = "";
|
|
61600
|
+
for (const ch2 of text) {
|
|
61601
|
+
const n = Buffer.byteLength(ch2, "utf8");
|
|
61602
|
+
if (used + n > budget) break;
|
|
61603
|
+
used += n;
|
|
61604
|
+
out += ch2;
|
|
61605
|
+
}
|
|
61606
|
+
return out + ELLIPSIS;
|
|
61607
|
+
}
|
|
61608
|
+
function validId(id) {
|
|
61609
|
+
if (Buffer.byteLength(id, "utf8") > MAX_ID_BYTES) return false;
|
|
61610
|
+
const segments3 = id.split("/");
|
|
61611
|
+
return segments3.length <= MAX_ID_DEPTH && segments3.every((s2) => SEGMENT.test(s2));
|
|
61612
|
+
}
|
|
61613
|
+
function idSegment(raw, n = 12) {
|
|
61614
|
+
const s2 = raw.replace(/[^A-Za-z0-9_.+-]/g, "_").slice(0, n);
|
|
61615
|
+
return s2 === "" ? "x" : s2;
|
|
61616
|
+
}
|
|
61617
|
+
function encodeText(text, maxBytes) {
|
|
61618
|
+
if (text === void 0) return void 0;
|
|
61619
|
+
const line2 = sanitizeLine(text);
|
|
61620
|
+
if (line2 === "") return void 0;
|
|
61621
|
+
return Buffer.from(truncateUtf8(line2, maxBytes), "utf8").toString("base64");
|
|
61622
|
+
}
|
|
61623
|
+
function encodePairs(report2) {
|
|
61624
|
+
if (!STATES.includes(report2.state)) return void 0;
|
|
61625
|
+
if (report2.id !== void 0 && !validId(report2.id)) return void 0;
|
|
61626
|
+
const pairs = [`state=${report2.state}`];
|
|
61627
|
+
if (report2.id !== void 0) pairs.push(`id=${report2.id}`);
|
|
61628
|
+
if (report2.state === "blocked" && report2.kind !== void 0 && KINDS4.includes(report2.kind))
|
|
61629
|
+
pairs.push(`kind=${report2.kind}`);
|
|
61630
|
+
const p = report2.progress;
|
|
61631
|
+
if ((report2.state === "working" || report2.state === "blocked") && p !== void 0 && Number.isInteger(p) && p >= 0 && p <= 100)
|
|
61632
|
+
pairs.push(`progress=${p}`);
|
|
61633
|
+
if (report2.app !== void 0 && SEGMENT.test(report2.app)) pairs.push(`app=${report2.app}`);
|
|
61634
|
+
if (report2.state !== "clear") {
|
|
61635
|
+
const title = encodeText(report2.title, MAX_TITLE_BYTES);
|
|
61636
|
+
if (title !== void 0) pairs.push(`title=${title}`);
|
|
61637
|
+
const msg2 = encodeText(report2.msg, MAX_MSG_BYTES);
|
|
61638
|
+
if (msg2 !== void 0) pairs.push(`msg=${msg2}`);
|
|
61639
|
+
}
|
|
61640
|
+
while (osc(pairs.join(":")).length > MAX_SEQUENCE_BYTES) {
|
|
61641
|
+
const last = pairs.at(-1);
|
|
61642
|
+
if (!last.startsWith("msg=") && !last.startsWith("title=")) return void 0;
|
|
61643
|
+
pairs.pop();
|
|
61644
|
+
}
|
|
61645
|
+
return pairs.join(":");
|
|
61646
|
+
}
|
|
61647
|
+
function osc(body) {
|
|
61648
|
+
return `\x1B]7501;${body}\x1B\\`;
|
|
61649
|
+
}
|
|
61650
|
+
function tmuxPassthrough(sequence) {
|
|
61651
|
+
return `\x1BPtmux;${sequence.replaceAll("\x1B", "\x1B\x1B")}\x1B\\`;
|
|
61652
|
+
}
|
|
61653
|
+
function isProgramStatusReply(sequence) {
|
|
61654
|
+
return /^\x1b\]7501;\?/.test(sequence);
|
|
61655
|
+
}
|
|
61656
|
+
function isDa1Reply(sequence) {
|
|
61657
|
+
return /^\x1b\[\?[\d;]*c$/.test(sequence);
|
|
61658
|
+
}
|
|
61659
|
+
var PROGRAM_STATUS_QUERY, DA1_QUERY, MAX_SEQUENCE_BYTES, MAX_TITLE_BYTES, MAX_MSG_BYTES, MAX_ID_BYTES, MAX_ID_DEPTH, SEGMENT, STATES, KINDS4, ELLIPSIS, ProgramStatusEmitter;
|
|
61660
|
+
var init_program_status = __esm({
|
|
61661
|
+
"src/tui/program-status.ts"() {
|
|
61662
|
+
"use strict";
|
|
61663
|
+
PROGRAM_STATUS_QUERY = "\x1B]7501;?\x1B\\";
|
|
61664
|
+
DA1_QUERY = "\x1B[c";
|
|
61665
|
+
MAX_SEQUENCE_BYTES = 4096;
|
|
61666
|
+
MAX_TITLE_BYTES = 192;
|
|
61667
|
+
MAX_MSG_BYTES = 2048;
|
|
61668
|
+
MAX_ID_BYTES = 128;
|
|
61669
|
+
MAX_ID_DEPTH = 8;
|
|
61670
|
+
SEGMENT = /^[A-Za-z0-9_.+-]{1,32}$/;
|
|
61671
|
+
STATES = ["idle", "working", "done", "blocked", "error", "clear"];
|
|
61672
|
+
KINDS4 = ["permission", "question", "auth"];
|
|
61673
|
+
ELLIPSIS = "…";
|
|
61674
|
+
ProgramStatusEmitter = class {
|
|
61675
|
+
constructor(options) {
|
|
61676
|
+
this.options = options;
|
|
61677
|
+
this.tmux = Boolean(options.env?.["TMUX"]);
|
|
61678
|
+
this.now = options.now ?? Date.now;
|
|
61679
|
+
}
|
|
61680
|
+
options;
|
|
61681
|
+
support = "unknown";
|
|
61682
|
+
tmux;
|
|
61683
|
+
desired = /* @__PURE__ */ new Map();
|
|
61684
|
+
sent = /* @__PURE__ */ new Map();
|
|
61685
|
+
timers = /* @__PURE__ */ new Map();
|
|
61686
|
+
probeTimer;
|
|
61687
|
+
now;
|
|
61688
|
+
/** 当前是否会写出报告。 */
|
|
61689
|
+
get supported() {
|
|
61690
|
+
return this.support === "yes";
|
|
61691
|
+
}
|
|
61692
|
+
/** 按模式开始:on 直接启用,auto 发检测查询(tmux 里不检测,等同 off),off 什么都不做。 */
|
|
61693
|
+
start() {
|
|
61694
|
+
if (this.support !== "unknown") return;
|
|
61695
|
+
const mode = this.options.mode;
|
|
61696
|
+
if (mode === "off" || mode === "auto" && this.tmux) {
|
|
61697
|
+
this.support = "no";
|
|
61698
|
+
return;
|
|
61699
|
+
}
|
|
61700
|
+
if (mode === "on") return this.enable();
|
|
61701
|
+
this.support = "probing";
|
|
61702
|
+
this.options.write(PROGRAM_STATUS_QUERY + DA1_QUERY);
|
|
61703
|
+
this.probeTimer = setTimeout(() => this.settleProbe(false), this.options.timeoutMs ?? 300);
|
|
61704
|
+
this.probeTimer.unref?.();
|
|
61705
|
+
}
|
|
61706
|
+
/** 输入解析里调用:吞掉检测回复(返回 true),其余返回 false。 */
|
|
61707
|
+
handleInput(sequence) {
|
|
61708
|
+
if (isProgramStatusReply(sequence)) {
|
|
61709
|
+
if (this.support === "probing") this.settleProbe(true);
|
|
61710
|
+
return true;
|
|
61711
|
+
}
|
|
61712
|
+
if (isDa1Reply(sequence)) {
|
|
61713
|
+
if (this.support === "probing") this.settleProbe(false);
|
|
61714
|
+
return true;
|
|
61715
|
+
}
|
|
61716
|
+
return false;
|
|
61717
|
+
}
|
|
61718
|
+
/** 设定某个 id(缺省根记录)的状态;`clear` 同时忘掉该 id 及其下层的记录。 */
|
|
61719
|
+
report(report2) {
|
|
61720
|
+
const key = report2.id ?? "";
|
|
61721
|
+
const full = this.options.app !== void 0 ? { ...report2, app: this.options.app } : report2;
|
|
61722
|
+
if (report2.state === "clear") {
|
|
61723
|
+
for (const id of [...this.desired.keys()])
|
|
61724
|
+
if (key === "" || id === key || id.startsWith(`${key}/`)) this.forget(id);
|
|
61725
|
+
}
|
|
61726
|
+
this.desired.set(key, full);
|
|
61727
|
+
if (this.support === "yes") this.flush(key);
|
|
61728
|
+
if (report2.state === "clear") this.desired.delete(key);
|
|
61729
|
+
}
|
|
61730
|
+
/** 停止计时器(不再写任何东西)。 */
|
|
61731
|
+
dispose() {
|
|
61732
|
+
if (this.probeTimer !== void 0) clearTimeout(this.probeTimer);
|
|
61733
|
+
this.probeTimer = void 0;
|
|
61734
|
+
for (const timer of this.timers.values()) clearTimeout(timer);
|
|
61735
|
+
this.timers.clear();
|
|
61736
|
+
if (this.support === "probing") this.support = "no";
|
|
61737
|
+
}
|
|
61738
|
+
settleProbe(ok) {
|
|
61739
|
+
if (this.probeTimer !== void 0) clearTimeout(this.probeTimer);
|
|
61740
|
+
this.probeTimer = void 0;
|
|
61741
|
+
if (ok) this.enable();
|
|
61742
|
+
else this.support = "no";
|
|
61743
|
+
}
|
|
61744
|
+
enable() {
|
|
61745
|
+
this.support = "yes";
|
|
61746
|
+
for (const key of this.desired.keys()) this.flush(key);
|
|
61747
|
+
}
|
|
61748
|
+
forget(id) {
|
|
61749
|
+
this.desired.delete(id);
|
|
61750
|
+
this.sent.delete(id);
|
|
61751
|
+
const timer = this.timers.get(id);
|
|
61752
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
61753
|
+
this.timers.delete(id);
|
|
61754
|
+
}
|
|
61755
|
+
flush(key) {
|
|
61756
|
+
const report2 = this.desired.get(key);
|
|
61757
|
+
if (report2 === void 0) return;
|
|
61758
|
+
const body = encodePairs(report2);
|
|
61759
|
+
if (body === void 0) return;
|
|
61760
|
+
const last = this.sent.get(key);
|
|
61761
|
+
if (last?.body === body) return;
|
|
61762
|
+
const throttle = this.options.throttleMs ?? 500;
|
|
61763
|
+
const head = `${report2.state}:${report2.kind ?? ""}`;
|
|
61764
|
+
const wait = last !== void 0 && last.head === head ? last.at + throttle - this.now() : 0;
|
|
61765
|
+
if (wait > 0 && report2.state !== "clear") {
|
|
61766
|
+
if (!this.timers.has(key)) {
|
|
61767
|
+
const timer2 = setTimeout(() => {
|
|
61768
|
+
this.timers.delete(key);
|
|
61769
|
+
this.flush(key);
|
|
61770
|
+
}, wait);
|
|
61771
|
+
timer2.unref?.();
|
|
61772
|
+
this.timers.set(key, timer2);
|
|
61773
|
+
}
|
|
61774
|
+
return;
|
|
61775
|
+
}
|
|
61776
|
+
const timer = this.timers.get(key);
|
|
61777
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
61778
|
+
this.timers.delete(key);
|
|
61779
|
+
const sequence = osc(body);
|
|
61780
|
+
this.options.write(this.tmux ? tmuxPassthrough(sequence) : sequence);
|
|
61781
|
+
if (report2.state === "clear") this.sent.delete(key);
|
|
61782
|
+
else this.sent.set(key, { body, head, at: this.now() });
|
|
61783
|
+
}
|
|
61784
|
+
};
|
|
61785
|
+
}
|
|
61786
|
+
});
|
|
61787
|
+
|
|
61788
|
+
// src/modes/interactive/program-status-ui.ts
|
|
61789
|
+
function blocked(kind, text) {
|
|
61790
|
+
return { state: "blocked", kind, msg: text };
|
|
61791
|
+
}
|
|
61792
|
+
function programStatusUi(deps) {
|
|
61793
|
+
const { terminal, programStatus } = deps.options;
|
|
61794
|
+
const mode = deps.runtime.config.ui?.programStatus ?? "auto";
|
|
61795
|
+
if (terminal !== void 0 && programStatus === void 0 || mode === "off")
|
|
61796
|
+
return { wrap: (handler) => handler, start: () => void 0, exit: () => void 0 };
|
|
61797
|
+
const emitter = new ProgramStatusEmitter({
|
|
61798
|
+
write: (data2) => deps.tui.terminal.write(data2),
|
|
61799
|
+
mode,
|
|
61800
|
+
env: deps.env,
|
|
61801
|
+
app: "ama",
|
|
61802
|
+
...programStatus
|
|
61803
|
+
});
|
|
61804
|
+
const tracker = new ProgramStatusTracker(emitter, deps.cwd);
|
|
61805
|
+
deps.tui.addInputListener((data2) => {
|
|
61806
|
+
if (emitter.handleInput(data2)) return true;
|
|
61807
|
+
tracker.acknowledge();
|
|
61808
|
+
return false;
|
|
61809
|
+
});
|
|
61810
|
+
return {
|
|
61811
|
+
wrap: (handler) => (event) => {
|
|
61812
|
+
tracker.onEvent(event);
|
|
61813
|
+
handler(event);
|
|
61814
|
+
},
|
|
61815
|
+
start: () => {
|
|
61816
|
+
emitter.start();
|
|
61817
|
+
tracker.sync();
|
|
61818
|
+
},
|
|
61819
|
+
exit: () => {
|
|
61820
|
+
emitter.report({ state: "clear" });
|
|
61821
|
+
emitter.dispose();
|
|
61822
|
+
}
|
|
61823
|
+
};
|
|
61824
|
+
}
|
|
61825
|
+
var AUTH_EXPIRED, ProgramStatusTracker;
|
|
61826
|
+
var init_program_status_ui = __esm({
|
|
61827
|
+
"src/modes/interactive/program-status-ui.ts"() {
|
|
61828
|
+
"use strict";
|
|
61829
|
+
init_i18n();
|
|
61830
|
+
init_program_status();
|
|
61831
|
+
init_tool_summary();
|
|
61832
|
+
AUTH_EXPIRED = /\bauth_expired\b/;
|
|
61833
|
+
ProgramStatusTracker = class {
|
|
61834
|
+
constructor(emitter, cwd = () => void 0) {
|
|
61835
|
+
this.emitter = emitter;
|
|
61836
|
+
this.cwd = cwd;
|
|
61837
|
+
}
|
|
61838
|
+
emitter;
|
|
61839
|
+
cwd;
|
|
61840
|
+
running = false;
|
|
61841
|
+
activity;
|
|
61842
|
+
approvals = /* @__PURE__ */ new Map();
|
|
61843
|
+
plan;
|
|
61844
|
+
auth;
|
|
61845
|
+
outcome;
|
|
61846
|
+
lastError;
|
|
61847
|
+
tasks = /* @__PURE__ */ new Map();
|
|
61848
|
+
onEvent(event) {
|
|
61849
|
+
const run7 = msg().interactive.view.run;
|
|
61850
|
+
switch (event.type) {
|
|
61851
|
+
case "session_start":
|
|
61852
|
+
if (event.reason !== "startup") this.reset();
|
|
61853
|
+
break;
|
|
61854
|
+
case "agent_start":
|
|
61855
|
+
this.running = true;
|
|
61856
|
+
this.activity = run7.thinking;
|
|
61857
|
+
this.outcome = this.auth = this.lastError = void 0;
|
|
61858
|
+
for (const [key, task] of this.tasks)
|
|
61859
|
+
if (task.state !== "working" && task.state !== "blocked") this.dropTask(key);
|
|
61860
|
+
break;
|
|
61861
|
+
case "message_update": {
|
|
61862
|
+
const last = event.message.content.at(-1);
|
|
61863
|
+
this.activity = last?.type === "text" ? run7.replying : run7.thinking;
|
|
61864
|
+
break;
|
|
61865
|
+
}
|
|
61866
|
+
case "tool_execution_start":
|
|
61867
|
+
if (event.parentToolCallId === void 0) this.activity = run7.runningTool(event.toolName);
|
|
61868
|
+
break;
|
|
61869
|
+
case "compaction_start":
|
|
61870
|
+
this.activity = run7.compacting;
|
|
61871
|
+
break;
|
|
61872
|
+
case "message_end":
|
|
61873
|
+
if (event.message.role === "assistant" && event.message.stopReason === "error")
|
|
61874
|
+
this.lastError = event.message.errorMessage ?? "error";
|
|
61875
|
+
break;
|
|
61876
|
+
case "agent_end":
|
|
61877
|
+
if (!event.willRetry) this.outcome = this.outcomeOf(event.stopReason);
|
|
61878
|
+
break;
|
|
61879
|
+
case "agent_settled":
|
|
61880
|
+
this.running = false;
|
|
61881
|
+
this.outcome ??= { state: "done" };
|
|
61882
|
+
break;
|
|
61883
|
+
case "permission_request": {
|
|
61884
|
+
const summary2 = flat(toolSummary(event.toolName, event.input, this.cwd()), 80);
|
|
61885
|
+
const text = summary2 === "" ? event.toolName : `${event.toolName} · ${summary2}`;
|
|
61886
|
+
const taskId = event.context?.taskId;
|
|
61887
|
+
this.approvals.set(event.requestId, { msg: text, ...taskId ? { taskId } : {} });
|
|
61888
|
+
const task = taskId !== void 0 ? this.tasks.get(taskId) : void 0;
|
|
61889
|
+
if (task !== void 0) Object.assign(task, { state: "blocked", msg: text });
|
|
61890
|
+
break;
|
|
61891
|
+
}
|
|
61892
|
+
case "permission_resolved": {
|
|
61893
|
+
const taskId = this.approvals.get(event.requestId)?.taskId;
|
|
61894
|
+
this.approvals.delete(event.requestId);
|
|
61895
|
+
const task = taskId !== void 0 ? this.tasks.get(taskId) : void 0;
|
|
61896
|
+
const still = [...this.approvals.values()].some((p) => p.taskId === taskId);
|
|
61897
|
+
if (task?.state === "blocked" && !still) Object.assign(task, { state: "working" });
|
|
61898
|
+
break;
|
|
61899
|
+
}
|
|
61900
|
+
case "plan_proposed":
|
|
61901
|
+
this.plan = msg().plan.dialog.title;
|
|
61902
|
+
break;
|
|
61903
|
+
case "plan_resolved":
|
|
61904
|
+
this.plan = void 0;
|
|
61905
|
+
break;
|
|
61906
|
+
case "model_changed":
|
|
61907
|
+
this.auth = void 0;
|
|
61908
|
+
break;
|
|
61909
|
+
case "subagent_start":
|
|
61910
|
+
this.tasks.set(event.taskId, {
|
|
61911
|
+
id: `task/${idSegment(event.taskId)}`,
|
|
61912
|
+
title: event.description,
|
|
61913
|
+
state: "working",
|
|
61914
|
+
msg: event.agent
|
|
61915
|
+
});
|
|
61916
|
+
break;
|
|
61917
|
+
case "subagent_update": {
|
|
61918
|
+
const task = this.tasks.get(event.taskId);
|
|
61919
|
+
if (task?.state === "working" && event.toolName !== void 0)
|
|
61920
|
+
task.msg = run7.runningTool(event.toolName);
|
|
61921
|
+
break;
|
|
61922
|
+
}
|
|
61923
|
+
case "subagent_end": {
|
|
61924
|
+
const task = this.tasks.get(event.taskId);
|
|
61925
|
+
if (task === void 0) break;
|
|
61926
|
+
const s2 = event.status;
|
|
61927
|
+
task.state = s2 === "completed" ? "done" : s2 === "aborted" || s2 === "interrupted" ? "idle" : "error";
|
|
61928
|
+
delete task.msg;
|
|
61929
|
+
break;
|
|
61930
|
+
}
|
|
61931
|
+
default:
|
|
61932
|
+
return;
|
|
61933
|
+
}
|
|
61934
|
+
this.sync();
|
|
61935
|
+
}
|
|
61936
|
+
/** 用户按键:已看到的 done / error 回到 idle。 */
|
|
61937
|
+
acknowledge() {
|
|
61938
|
+
if (this.running || this.outcome === void 0 || this.outcome.state === "idle") return;
|
|
61939
|
+
this.outcome = { state: "idle" };
|
|
61940
|
+
this.sync();
|
|
61941
|
+
}
|
|
61942
|
+
/** 当前根记录(测试也用)。 */
|
|
61943
|
+
root() {
|
|
61944
|
+
const pending = [...this.approvals.values()].at(-1);
|
|
61945
|
+
if (pending !== void 0) return blocked("permission", pending.msg);
|
|
61946
|
+
if (this.plan !== void 0) return blocked("question", this.plan);
|
|
61947
|
+
if (this.auth !== void 0) return blocked("auth", this.auth);
|
|
61948
|
+
if (this.running)
|
|
61949
|
+
return { state: "working", ...this.activity !== void 0 ? { msg: this.activity } : {} };
|
|
61950
|
+
return this.outcome ?? { state: "idle" };
|
|
61951
|
+
}
|
|
61952
|
+
/** 写出全部记录(发射器同值去重)。 */
|
|
61953
|
+
sync() {
|
|
61954
|
+
this.emitter.report(this.root());
|
|
61955
|
+
for (const task of this.tasks.values())
|
|
61956
|
+
this.emitter.report({
|
|
61957
|
+
id: task.id,
|
|
61958
|
+
state: task.state,
|
|
61959
|
+
title: task.title,
|
|
61960
|
+
...task.state === "blocked" ? { kind: "permission" } : {},
|
|
61961
|
+
...task.msg !== void 0 ? { msg: task.msg } : {}
|
|
61962
|
+
});
|
|
61963
|
+
}
|
|
61964
|
+
outcomeOf(stopReason) {
|
|
61965
|
+
if (stopReason === "aborted") return { state: "idle" };
|
|
61966
|
+
if (stopReason !== "error") return { state: "done" };
|
|
61967
|
+
const text = flat(this.lastError ?? "error", 200);
|
|
61968
|
+
if (AUTH_EXPIRED.test(text)) this.auth = text;
|
|
61969
|
+
return { state: "error", msg: text };
|
|
61970
|
+
}
|
|
61971
|
+
dropTask(key) {
|
|
61972
|
+
const task = this.tasks.get(key);
|
|
61973
|
+
this.tasks.delete(key);
|
|
61974
|
+
if (task !== void 0) this.emitter.report({ id: task.id, state: "clear" });
|
|
61975
|
+
}
|
|
61976
|
+
reset() {
|
|
61977
|
+
this.running = false;
|
|
61978
|
+
this.approvals.clear();
|
|
61979
|
+
this.plan = this.auth = this.outcome = this.lastError = this.activity = void 0;
|
|
61980
|
+
for (const key of [...this.tasks.keys()]) this.dropTask(key);
|
|
61981
|
+
}
|
|
61982
|
+
};
|
|
61983
|
+
}
|
|
61984
|
+
});
|
|
61985
|
+
|
|
60814
61986
|
// src/modes/interactive/terminal-setup.ts
|
|
60815
61987
|
function processTerminal() {
|
|
60816
61988
|
const stdin = process.stdin;
|
|
@@ -60855,6 +62027,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
60855
62027
|
const keys = options.keybindings ?? loadKeys(runtime, (m) => startupWarnings.push(m));
|
|
60856
62028
|
let session = currentSession(runtime);
|
|
60857
62029
|
const tui = new TUI(terminal);
|
|
62030
|
+
const osc7501 = programStatusUi({ tui, runtime, env, options, cwd: () => session.state.cwd });
|
|
60858
62031
|
const view = new MessageView({
|
|
60859
62032
|
theme,
|
|
60860
62033
|
...ui.showThinking !== void 0 ? { showThinking: ui.showThinking } : {},
|
|
@@ -60954,7 +62127,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
60954
62127
|
queueView.setQueue(steering, followUp);
|
|
60955
62128
|
render();
|
|
60956
62129
|
};
|
|
60957
|
-
const
|
|
62130
|
+
const handleEvent3 = createSessionEventHandler({
|
|
60958
62131
|
view,
|
|
60959
62132
|
tools,
|
|
60960
62133
|
status,
|
|
@@ -60966,6 +62139,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
60966
62139
|
notice,
|
|
60967
62140
|
render
|
|
60968
62141
|
});
|
|
62142
|
+
const onEvent = osc7501.wrap(handleEvent3);
|
|
60969
62143
|
let unsubscribe = session.subscribe(onEvent);
|
|
60970
62144
|
const startupLevel = startupScreenLevel(runtime);
|
|
60971
62145
|
const home = env["HOME"] ?? env["USERPROFILE"];
|
|
@@ -61193,6 +62367,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
61193
62367
|
if (hintTimer !== void 0) clearTimeout(hintTimer);
|
|
61194
62368
|
loader.stop();
|
|
61195
62369
|
area.dispose();
|
|
62370
|
+
osc7501.exit();
|
|
61196
62371
|
view.addExitSummary(exitSummaryLines(session.getStats(), now() - startedAt, theme));
|
|
61197
62372
|
tui.clear();
|
|
61198
62373
|
tui.addChild(view);
|
|
@@ -61231,6 +62406,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
61231
62406
|
);
|
|
61232
62407
|
return;
|
|
61233
62408
|
}
|
|
62409
|
+
osc7501.start();
|
|
61234
62410
|
runtime.approvals.setUiBroker(broker);
|
|
61235
62411
|
runtime.notifier.set((message, level) => notice(level, message));
|
|
61236
62412
|
agentUi.attach(session);
|
|
@@ -61287,6 +62463,7 @@ var init_interactive_mode = __esm({
|
|
|
61287
62463
|
init_run_indicator();
|
|
61288
62464
|
init_status_area();
|
|
61289
62465
|
init_session_events();
|
|
62466
|
+
init_program_status_ui();
|
|
61290
62467
|
init_subagent_view();
|
|
61291
62468
|
init_terminal_setup();
|
|
61292
62469
|
init_tool_view();
|
|
@@ -67009,7 +68186,7 @@ function traceHtmlData(source, opts) {
|
|
|
67009
68186
|
}
|
|
67010
68187
|
const du = durationText(node, theme);
|
|
67011
68188
|
if (du !== "") out.du = du;
|
|
67012
|
-
const tk =
|
|
68189
|
+
const tk = tokensText2(node, theme);
|
|
67013
68190
|
if (tk !== "") out.tk = tk;
|
|
67014
68191
|
const ca = cacheText2(node);
|
|
67015
68192
|
if (ca !== "") out.ca = ca;
|