@armadra/agent 0.7.0 → 0.7.2
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 +65 -0
- package/CHANGELOG.zh-CN.md +41 -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 +13 -1
- package/dist/agent/session-compaction.js +36 -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/auth/oauth/token-store.d.ts +2 -0
- package/dist/auth/oauth/token-store.js +7 -2
- package/dist/bundle/ama.cjs +1684 -490
- package/dist/checkpoints/shadow-git.js +2 -1
- 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 +23 -0
- package/dist/compaction/prefix-estimate.js +34 -0
- package/dist/config/auth-file.js +10 -2
- package/dist/config/fs-retry.d.ts +18 -0
- package/dist/config/fs-retry.js +33 -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 +53 -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 +94 -0
- package/dist/i18n/messages/report-context.js +95 -0
- package/dist/i18n/messages/report.d.ts +96 -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 +35 -0
- package/dist/modes/context-report.js +172 -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 +24 -1
- 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 +23 -1
- 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.2" : 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,111 @@ 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
|
+
keyAutoCompact: "Auto-compact",
|
|
2996
|
+
autoCompact: (at, distance2) => `at ${at}, ≈ ${distance2} to go`,
|
|
2997
|
+
autoCompactReached: (at) => `at ${at}, reached`,
|
|
2998
|
+
autoCompactOff: "off",
|
|
2999
|
+
windowUnknown: "window unknown",
|
|
3000
|
+
keyPrune: "Pruning",
|
|
3001
|
+
prune: (at) => `old tool results trimmed from ${at}`,
|
|
3002
|
+
breakdown: (total) => `By category (estimated, ${total})`,
|
|
3003
|
+
prefixCounted: "System prompt and tool declarations are counted from the stored system messages; the full estimate can differ from reported usage.",
|
|
3004
|
+
prefixPending: "System prompt and tool declarations are not counted until the first request.",
|
|
3005
|
+
categories: {
|
|
3006
|
+
system: "System prompt",
|
|
3007
|
+
tools: "Tool declarations",
|
|
3008
|
+
user: "User messages",
|
|
3009
|
+
assistant: "Assistant text",
|
|
3010
|
+
reasoning: "Reasoning",
|
|
3011
|
+
toolCalls: "Tool-call arguments",
|
|
3012
|
+
toolResults: "Tool results",
|
|
3013
|
+
images: "Images",
|
|
3014
|
+
summaries: "Summaries",
|
|
3015
|
+
custom: "Custom messages"
|
|
3016
|
+
},
|
|
3017
|
+
partNames: {
|
|
3018
|
+
compaction: "compaction",
|
|
3019
|
+
branch: "branch",
|
|
3020
|
+
user: "user",
|
|
3021
|
+
toolResult: "tool result",
|
|
3022
|
+
custom: "custom"
|
|
3023
|
+
},
|
|
3024
|
+
images: (count2) => plural(count2, "image"),
|
|
3025
|
+
more: (count2) => `+${count2} more`,
|
|
3026
|
+
largest: (count2) => `Largest tool results (top ${count2})`,
|
|
3027
|
+
noToolResults: "no tool results",
|
|
3028
|
+
empty: "No messages in the context yet."
|
|
3029
|
+
};
|
|
3030
|
+
zh16 = {
|
|
3031
|
+
title: "上下文",
|
|
3032
|
+
keyUsed: "已用",
|
|
3033
|
+
used: (tokens, window2, percent3) => `${tokens} / ${window2}${percent3 !== void 0 ? `(${percent3})` : ""}`,
|
|
3034
|
+
keyLeft: "剩余",
|
|
3035
|
+
left: (tokens) => `${tokens} token`,
|
|
3036
|
+
keySource: "来源",
|
|
3037
|
+
sourceUsage: (usage, estimate) => `usage 实测 ${usage} + 估算 ${estimate}`,
|
|
3038
|
+
sourceEstimate: "全量估算(还没有可用的 usage)",
|
|
3039
|
+
keyAutoCompact: "自动压缩",
|
|
3040
|
+
autoCompact: (at, distance2) => `${at} 触发,还差 ≈ ${distance2}`,
|
|
3041
|
+
autoCompactReached: (at) => `${at} 触发,已达到`,
|
|
3042
|
+
autoCompactOff: "关闭",
|
|
3043
|
+
windowUnknown: "窗口未知",
|
|
3044
|
+
keyPrune: "裁剪",
|
|
3045
|
+
prune: (at) => `超过 ${at} 时清理旧工具结果`,
|
|
3046
|
+
breakdown: (total) => `按类别(估算,${total})`,
|
|
3047
|
+
prefixCounted: "系统提示与工具声明按会话里存的 system 消息计入;全量估算可能与 usage 实测不同。",
|
|
3048
|
+
prefixPending: "系统提示与工具声明在首次请求后才计入。",
|
|
3049
|
+
categories: {
|
|
3050
|
+
system: "系统提示",
|
|
3051
|
+
tools: "工具声明",
|
|
3052
|
+
user: "用户消息",
|
|
3053
|
+
assistant: "助手文本",
|
|
3054
|
+
reasoning: "推理",
|
|
3055
|
+
toolCalls: "工具调用参数",
|
|
3056
|
+
toolResults: "工具结果",
|
|
3057
|
+
images: "附件图片",
|
|
3058
|
+
summaries: "摘要",
|
|
3059
|
+
custom: "自定义消息"
|
|
3060
|
+
},
|
|
3061
|
+
partNames: {
|
|
3062
|
+
compaction: "压缩",
|
|
3063
|
+
branch: "分支",
|
|
3064
|
+
user: "用户",
|
|
3065
|
+
toolResult: "工具结果",
|
|
3066
|
+
custom: "自定义"
|
|
3067
|
+
},
|
|
3068
|
+
images: (count2) => `${count2} 张`,
|
|
3069
|
+
more: (count2) => `另有 ${count2} 项`,
|
|
3070
|
+
largest: (count2) => `最大的工具结果(前 ${count2})`,
|
|
3071
|
+
noToolResults: "没有工具结果",
|
|
3072
|
+
empty: "上下文里还没有消息。"
|
|
3073
|
+
};
|
|
3074
|
+
}
|
|
3075
|
+
});
|
|
3076
|
+
|
|
3077
|
+
// src/i18n/messages/report.ts
|
|
3078
|
+
var en17, zh17;
|
|
2973
3079
|
var init_report = __esm({
|
|
2974
3080
|
"src/i18n/messages/report.ts"() {
|
|
2975
3081
|
"use strict";
|
|
2976
3082
|
init_format();
|
|
2977
|
-
|
|
3083
|
+
init_report_context();
|
|
3084
|
+
en17 = {
|
|
2978
3085
|
/** 内置斜杠命令:`args` 只写需要翻译的占位,说明整句。 */
|
|
2979
3086
|
commands: {
|
|
2980
3087
|
help: "List commands",
|
|
@@ -2994,6 +3101,7 @@ var init_report = __esm({
|
|
|
2994
3101
|
tools: "List / set active tools",
|
|
2995
3102
|
hooks: "List loaded hooks",
|
|
2996
3103
|
session: "Session info, usage and cache",
|
|
3104
|
+
context: "Context breakdown by category (estimated), source, window and auto-compact threshold",
|
|
2997
3105
|
cache: "Cache stats; switch warming for this session; print the prefix fingerprint",
|
|
2998
3106
|
statusline: "Footer info two lines / one line (Ctrl+G)",
|
|
2999
3107
|
planArgs: "[goal] | approve [mode|fresh] | reject",
|
|
@@ -3053,6 +3161,8 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3053
3161
|
notDirectory: (path) => `Not a directory: ${path}
|
|
3054
3162
|
`
|
|
3055
3163
|
},
|
|
3164
|
+
/** `/context`:上下文分类明细(report-context.ts)。 */
|
|
3165
|
+
contextReport: en16,
|
|
3056
3166
|
/** `/session`、`/cache` 报告与缓存提示行。 */
|
|
3057
3167
|
cache: {
|
|
3058
3168
|
unreported: "not reported",
|
|
@@ -3153,10 +3263,13 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3153
3263
|
model: (model, thinking, permission) => `${model} · thinking ${thinking} · permission ${permission}`,
|
|
3154
3264
|
keyMessages: "Messages",
|
|
3155
3265
|
messages: (user, assistant, tools) => `user ${user} · assistant ${assistant} · tool calls ${tools}`,
|
|
3156
|
-
keyUsage: "
|
|
3266
|
+
keyUsage: "Total usage",
|
|
3157
3267
|
usage: (input2, output, cacheRead, cacheWrite, cost2) => `input ${input2} · output ${output} · cache read ${cacheRead} · cache write ${cacheWrite} · ${cost2}`,
|
|
3158
3268
|
keyContext: "Context",
|
|
3159
3269
|
context: (tokens, window2, percent3) => `${tokens} / ${window2} (${percent3}%)`,
|
|
3270
|
+
/** 上下文行末尾:距自动压缩(档二)还有多少 token;自动压缩关闭 / 熔断时换成 autoCompactOff。 */
|
|
3271
|
+
toAutoCompact: (tokens) => `≈ ${tokens} until auto-compaction`,
|
|
3272
|
+
autoCompactOff: "auto-compaction off",
|
|
3160
3273
|
keyAgents: "Sub-agents",
|
|
3161
3274
|
externalTitle: "External agents",
|
|
3162
3275
|
noFingerprint: "This session does not provide a prefix fingerprint",
|
|
@@ -3218,7 +3331,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3218
3331
|
userHooks: (path) => `User hooks.json: ${path}`
|
|
3219
3332
|
}
|
|
3220
3333
|
};
|
|
3221
|
-
|
|
3334
|
+
zh17 = {
|
|
3222
3335
|
commands: {
|
|
3223
3336
|
help: "列出命令",
|
|
3224
3337
|
new: "新建会话",
|
|
@@ -3237,6 +3350,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3237
3350
|
tools: "列出 / 设置活动工具",
|
|
3238
3351
|
hooks: "列出已加载的 Hook",
|
|
3239
3352
|
session: "会话信息、用量与缓存",
|
|
3353
|
+
context: "上下文按类别拆分(估算)、来源、窗口与自动压缩阈值",
|
|
3240
3354
|
cache: "缓存统计;切换本会话保温;打印前缀指纹",
|
|
3241
3355
|
statusline: "底部信息行两行 / 一行(Ctrl+G)",
|
|
3242
3356
|
planArgs: "[目标] | approve [模式|fresh] | reject",
|
|
@@ -3294,6 +3408,7 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3294
3408
|
notDirectory: (path) => `不是目录:${path}
|
|
3295
3409
|
`
|
|
3296
3410
|
},
|
|
3411
|
+
contextReport: zh16,
|
|
3297
3412
|
cache: {
|
|
3298
3413
|
unreported: "未报告",
|
|
3299
3414
|
unknown: "未知",
|
|
@@ -3389,10 +3504,12 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3389
3504
|
model: (model, thinking, permission) => `${model} · 思考 ${thinking} · 权限 ${permission}`,
|
|
3390
3505
|
keyMessages: "消息",
|
|
3391
3506
|
messages: (user, assistant, tools) => `用户 ${user} · 助手 ${assistant} · 工具调用 ${tools}`,
|
|
3392
|
-
keyUsage: "
|
|
3507
|
+
keyUsage: "累计用量",
|
|
3393
3508
|
usage: (input2, output, cacheRead, cacheWrite, cost2) => `输入 ${input2} · 输出 ${output} · 缓存读 ${cacheRead} · 缓存写 ${cacheWrite} · ${cost2}`,
|
|
3394
3509
|
keyContext: "上下文",
|
|
3395
3510
|
context: (tokens, window2, percent3) => `${tokens} / ${window2}(${percent3}%)`,
|
|
3511
|
+
toAutoCompact: (tokens) => `距自动压缩 ≈ ${tokens}`,
|
|
3512
|
+
autoCompactOff: "自动压缩关闭",
|
|
3396
3513
|
keyAgents: "子 Agent",
|
|
3397
3514
|
externalTitle: "外部 Agent",
|
|
3398
3515
|
noFingerprint: "当前会话不提供前缀指纹",
|
|
@@ -3457,12 +3574,12 @@ Available: ${inactive.join(", ")}` : ""}`,
|
|
|
3457
3574
|
});
|
|
3458
3575
|
|
|
3459
3576
|
// src/i18n/messages/print.ts
|
|
3460
|
-
var
|
|
3577
|
+
var en18, zh18;
|
|
3461
3578
|
var init_print = __esm({
|
|
3462
3579
|
"src/i18n/messages/print.ts"() {
|
|
3463
3580
|
"use strict";
|
|
3464
3581
|
init_format();
|
|
3465
|
-
|
|
3582
|
+
en18 = {
|
|
3466
3583
|
/** `ama -p` 的 stderr。 */
|
|
3467
3584
|
print: {
|
|
3468
3585
|
stdinIgnored: (wait) => `ama: no piped input within ${wait}, ignored; to wait for it, end the arguments with -
|
|
@@ -3493,7 +3610,7 @@ var init_print = __esm({
|
|
|
3493
3610
|
badMode: (modes) => `mode must be ${modes.join(" | ")}`
|
|
3494
3611
|
}
|
|
3495
3612
|
};
|
|
3496
|
-
|
|
3613
|
+
zh18 = {
|
|
3497
3614
|
print: {
|
|
3498
3615
|
stdinIgnored: (wait) => `ama: 未在 ${wait}内收到管道输入,已忽略;需要等待请在末尾加 -
|
|
3499
3616
|
`,
|
|
@@ -3526,7 +3643,7 @@ var init_print = __esm({
|
|
|
3526
3643
|
});
|
|
3527
3644
|
|
|
3528
3645
|
// src/i18n/messages/config-keys.ts
|
|
3529
|
-
var dynamicDefaultsEn, dynamicDefaultsZh, keysEn, keysZh,
|
|
3646
|
+
var dynamicDefaultsEn, dynamicDefaultsZh, keysEn, keysZh, en19, zh19;
|
|
3530
3647
|
var init_config_keys = __esm({
|
|
3531
3648
|
"src/i18n/messages/config-keys.ts"() {
|
|
3532
3649
|
"use strict";
|
|
@@ -3626,6 +3743,7 @@ var init_config_keys = __esm({
|
|
|
3626
3743
|
"ui.animation": "false: the spinner stays still while running and redraws only when seconds change; the startup logo does not animate",
|
|
3627
3744
|
"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
3745
|
"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",
|
|
3746
|
+
"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
3747
|
"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
3748
|
"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
3749
|
"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 +3867,7 @@ var init_config_keys = __esm({
|
|
|
3749
3867
|
"ui.animation": "false:运行中 spinner 静止,只在秒数变化时重绘;启动字符画不播放动画",
|
|
3750
3868
|
"ui.restoreOnCancel": "运行中 Esc 中断、本回合还没有任何回复或工具调用时,撤回该回合并把原消息放回输入框",
|
|
3751
3869
|
"ui.enterWhileRunning": "运行中按 Enter:queue(缺省)排队插话,等下一个投递点送达;interrupt 打断当前回合并立即发送。app.message.interrupt 键(缺省 Ctrl+X)做另一种",
|
|
3870
|
+
"ui.programStatus": "用 OSC 7501 把运行状态报告给终端(idle / working / blocked / done / error):auto(缺省)终端回应检测查询后才发(tmux 里不发),on 不检测直接发(tmux 里经 passthrough 包裹,需要 allow-passthrough on),off 不发。只用于交互界面",
|
|
3752
3871
|
"ui.statusLine": "底部信息行:full 两行(速率行 + 状态行),compact 一行;运行时 Ctrl+G 或 /statusline 切换(第五波 W5-A 起生效)",
|
|
3753
3872
|
"ui.language": "界面语言:auto 按 LC_ALL / LC_MESSAGES / LANG 判断(zh* 为中文,其余英文),zh,en;AMA_LANG、--lang 覆盖;只影响界面,发给模型的文本固定英文",
|
|
3754
3873
|
"ui.replyLanguage": "模型回复语言(如 Chinese):会话开始在 rules 节末尾追加一句英文规则;不设时零字节变化;只认用户级(第六波起生效)",
|
|
@@ -3822,8 +3941,8 @@ var init_config_keys = __esm({
|
|
|
3822
3941
|
todo: "todo 工具;只认用户级(第五波 W5-F / W5-H2 起生效)",
|
|
3823
3942
|
"todo.reminder": "连续 N 回合未更新且有未完成项时提醒复述;0 关闭"
|
|
3824
3943
|
};
|
|
3825
|
-
|
|
3826
|
-
|
|
3944
|
+
en19 = { keys: keysEn, dynamicDefaults: dynamicDefaultsEn };
|
|
3945
|
+
zh19 = {
|
|
3827
3946
|
keys: keysZh,
|
|
3828
3947
|
dynamicDefaults: dynamicDefaultsZh
|
|
3829
3948
|
};
|
|
@@ -3831,12 +3950,12 @@ var init_config_keys = __esm({
|
|
|
3831
3950
|
});
|
|
3832
3951
|
|
|
3833
3952
|
// src/i18n/messages/config.ts
|
|
3834
|
-
var
|
|
3953
|
+
var en20, zh20;
|
|
3835
3954
|
var init_config = __esm({
|
|
3836
3955
|
"src/i18n/messages/config.ts"() {
|
|
3837
3956
|
"use strict";
|
|
3838
3957
|
init_config_keys();
|
|
3839
|
-
|
|
3958
|
+
en20 = {
|
|
3840
3959
|
/** 配置校验诊断(checker.ts、schema.ts、schema-w5.ts、schema-w6.ts)。 */
|
|
3841
3960
|
schema: {
|
|
3842
3961
|
enumArray: (choices) => `should be an array of ${choices.join(" | ")}`,
|
|
@@ -3957,9 +4076,9 @@ var init_config = __esm({
|
|
|
3957
4076
|
models: "Custom models (an entry with the same id replaces the whole model)",
|
|
3958
4077
|
modelOverrides: "Only changes metadata of existing models"
|
|
3959
4078
|
},
|
|
3960
|
-
...
|
|
4079
|
+
...en19
|
|
3961
4080
|
};
|
|
3962
|
-
|
|
4081
|
+
zh20 = {
|
|
3963
4082
|
schema: {
|
|
3964
4083
|
enumArray: (choices) => `应为 ${choices.join(" | ")} 组成的数组`,
|
|
3965
4084
|
ports: "应为端口号数组(0–65535;0 = 任意空闲端口)",
|
|
@@ -4071,18 +4190,18 @@ var init_config = __esm({
|
|
|
4071
4190
|
models: "自定义模型(同 id 整条替换)",
|
|
4072
4191
|
modelOverrides: "只改已有模型的元数据"
|
|
4073
4192
|
},
|
|
4074
|
-
...
|
|
4193
|
+
...zh19
|
|
4075
4194
|
};
|
|
4076
4195
|
}
|
|
4077
4196
|
});
|
|
4078
4197
|
|
|
4079
4198
|
// src/i18n/messages/drivers.ts
|
|
4080
|
-
var
|
|
4199
|
+
var en21, zh21;
|
|
4081
4200
|
var init_drivers = __esm({
|
|
4082
4201
|
"src/i18n/messages/drivers.ts"() {
|
|
4083
4202
|
"use strict";
|
|
4084
4203
|
init_format();
|
|
4085
|
-
|
|
4204
|
+
en21 = {
|
|
4086
4205
|
/** 外部 Agent 的 notice 与日志。 */
|
|
4087
4206
|
agent: {
|
|
4088
4207
|
reapedOrphans: (pids) => `cleaned up external agent processes left over from last time: ${pids}`,
|
|
@@ -4142,7 +4261,7 @@ var init_drivers = __esm({
|
|
|
4142
4261
|
noId: (label2) => `${label2}: the adapter returned by create() has no id`
|
|
4143
4262
|
}
|
|
4144
4263
|
};
|
|
4145
|
-
|
|
4264
|
+
zh21 = {
|
|
4146
4265
|
agent: {
|
|
4147
4266
|
reapedOrphans: (pids) => `清理了上次遗留的外部 Agent 进程:${pids}`,
|
|
4148
4267
|
unverifiedVersion: (program, version, verified) => `${program} ${version} 不在已验证区间 ${verified},协议可能有变化`,
|
|
@@ -4203,12 +4322,12 @@ var init_drivers = __esm({
|
|
|
4203
4322
|
});
|
|
4204
4323
|
|
|
4205
4324
|
// src/i18n/messages/session.ts
|
|
4206
|
-
var
|
|
4325
|
+
var en22, zh22;
|
|
4207
4326
|
var init_session = __esm({
|
|
4208
4327
|
"src/i18n/messages/session.ts"() {
|
|
4209
4328
|
"use strict";
|
|
4210
4329
|
init_format();
|
|
4211
|
-
|
|
4330
|
+
en22 = {
|
|
4212
4331
|
/** `ama sessions list / show / prune`(search / export / trace 各有自己的文案)。 */
|
|
4213
4332
|
cli: {
|
|
4214
4333
|
usage: `Usage: ama sessions list [--all] [--session-dir <dir>]
|
|
@@ -4344,7 +4463,7 @@ var init_session = __esm({
|
|
|
4344
4463
|
}
|
|
4345
4464
|
}
|
|
4346
4465
|
};
|
|
4347
|
-
|
|
4466
|
+
zh22 = {
|
|
4348
4467
|
cli: {
|
|
4349
4468
|
usage: `用法:ama sessions list [--all] [--session-dir <目录>]
|
|
4350
4469
|
ama sessions show <id> [--session-dir <目录>]
|
|
@@ -4477,7 +4596,7 @@ var init_session = __esm({
|
|
|
4477
4596
|
});
|
|
4478
4597
|
|
|
4479
4598
|
// src/i18n/messages/errors.ts
|
|
4480
|
-
var EN_HINT, ZH_HINT,
|
|
4599
|
+
var EN_HINT, ZH_HINT, en23, zh23;
|
|
4481
4600
|
var init_errors2 = __esm({
|
|
4482
4601
|
"src/i18n/messages/errors.ts"() {
|
|
4483
4602
|
"use strict";
|
|
@@ -4492,7 +4611,7 @@ var init_errors2 = __esm({
|
|
|
4492
4611
|
no_tool: "(没找到缩放工具:装 ImageMagick,macOS 自带 sips)",
|
|
4493
4612
|
still_too_large: "(缩放后仍超限)"
|
|
4494
4613
|
};
|
|
4495
|
-
|
|
4614
|
+
en23 = {
|
|
4496
4615
|
/** [W6-I3] 图片附件:当前模型不收图片(`--image` / `@路径`)。 */
|
|
4497
4616
|
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
4617
|
/** [W6-I3] SDK(`createRuntime` / `createAgentSession`)。 */
|
|
@@ -4564,7 +4683,7 @@ var init_errors2 = __esm({
|
|
|
4564
4683
|
}
|
|
4565
4684
|
}
|
|
4566
4685
|
};
|
|
4567
|
-
|
|
4686
|
+
zh23 = {
|
|
4568
4687
|
imageUnsupported: (model) => `${model ?? "当前模型"} 不接受图片输入(模型 input 没有 image);换一个支持图像的模型再试(ama models list 里标「图片」的,或在配置里给该模型写 "input": ["text", "image"])`,
|
|
4569
4688
|
cacheParamsStripped: (key, field2, suggestion) => `${key}:该端点不支持 ${field2},已自动去掉缓存参数重发;可在 config 里设 ${suggestion ?? "相应的 compat 开关"}`,
|
|
4570
4689
|
sdk: {
|
|
@@ -4635,12 +4754,12 @@ var init_errors2 = __esm({
|
|
|
4635
4754
|
});
|
|
4636
4755
|
|
|
4637
4756
|
// src/i18n/messages/agents.ts
|
|
4638
|
-
var
|
|
4757
|
+
var en24, zh24;
|
|
4639
4758
|
var init_agents = __esm({
|
|
4640
4759
|
"src/i18n/messages/agents.ts"() {
|
|
4641
4760
|
"use strict";
|
|
4642
4761
|
init_format();
|
|
4643
|
-
|
|
4762
|
+
en24 = {
|
|
4644
4763
|
status: {
|
|
4645
4764
|
queued: "queued",
|
|
4646
4765
|
running: "running",
|
|
@@ -4652,6 +4771,8 @@ var init_agents = __esm({
|
|
|
4652
4771
|
interrupted: "interrupted"
|
|
4653
4772
|
},
|
|
4654
4773
|
turns: (n) => plural(n, "turn"),
|
|
4774
|
+
/** 外部 Agent 报告的上下文占用(`34%`、`0.4%`)。 */
|
|
4775
|
+
context: (percent3) => `ctx ${percent3}`,
|
|
4655
4776
|
bar: {
|
|
4656
4777
|
more: (n) => `${n} more`,
|
|
4657
4778
|
keys: (up, down) => `${up}${down} select · Enter open · Esc back`,
|
|
@@ -4710,7 +4831,7 @@ var init_agents = __esm({
|
|
|
4710
4831
|
externalNoSession: (runner) => `Live output is kept only in memory; ${runner} did not report a session to resume.`
|
|
4711
4832
|
}
|
|
4712
4833
|
};
|
|
4713
|
-
|
|
4834
|
+
zh24 = {
|
|
4714
4835
|
status: {
|
|
4715
4836
|
queued: "排队",
|
|
4716
4837
|
running: "运行中",
|
|
@@ -4722,6 +4843,7 @@ var init_agents = __esm({
|
|
|
4722
4843
|
interrupted: "已中断"
|
|
4723
4844
|
},
|
|
4724
4845
|
turns: (n) => `${n} 轮`,
|
|
4846
|
+
context: (percent3) => `ctx ${percent3}`,
|
|
4725
4847
|
bar: {
|
|
4726
4848
|
more: (n) => `另 ${n} 个`,
|
|
4727
4849
|
keys: (up, down) => `${up}${down} 选择 · Enter 打开 · Esc 返回`,
|
|
@@ -4778,12 +4900,12 @@ var init_agents = __esm({
|
|
|
4778
4900
|
});
|
|
4779
4901
|
|
|
4780
4902
|
// src/i18n/messages/trace.ts
|
|
4781
|
-
var
|
|
4903
|
+
var en25, zh25;
|
|
4782
4904
|
var init_trace = __esm({
|
|
4783
4905
|
"src/i18n/messages/trace.ts"() {
|
|
4784
4906
|
"use strict";
|
|
4785
4907
|
init_format();
|
|
4786
|
-
|
|
4908
|
+
en25 = {
|
|
4787
4909
|
title: "Trace",
|
|
4788
4910
|
/** 顶部汇总行。 */
|
|
4789
4911
|
summary: (turns, requests, tools) => `${plural(turns, "turn")} · ${plural(requests, "request")} · ${plural(tools, "tool call")}`,
|
|
@@ -4902,7 +5024,7 @@ var init_trace = __esm({
|
|
|
4902
5024
|
badNow: (raw) => `--now expects epoch milliseconds (got ${raw})`
|
|
4903
5025
|
}
|
|
4904
5026
|
};
|
|
4905
|
-
|
|
5027
|
+
zh25 = {
|
|
4906
5028
|
title: "轨迹",
|
|
4907
5029
|
summary: (turns, requests, tools) => `${turns} 回合 · ${requests} 请求 · ${tools} 次工具`,
|
|
4908
5030
|
cache: (percent3) => `缓存 ${percent3}`,
|
|
@@ -5021,12 +5143,12 @@ var init_trace = __esm({
|
|
|
5021
5143
|
});
|
|
5022
5144
|
|
|
5023
5145
|
// src/i18n/messages/memory.ts
|
|
5024
|
-
var
|
|
5146
|
+
var en26, zh26;
|
|
5025
5147
|
var init_memory = __esm({
|
|
5026
5148
|
"src/i18n/messages/memory.ts"() {
|
|
5027
5149
|
"use strict";
|
|
5028
5150
|
init_format();
|
|
5029
|
-
|
|
5151
|
+
en26 = {
|
|
5030
5152
|
scope: { user: "user", project: "project", workspace: "workspace" },
|
|
5031
5153
|
panel: {
|
|
5032
5154
|
title: "Memory",
|
|
@@ -5086,7 +5208,7 @@ var init_memory = __esm({
|
|
|
5086
5208
|
untrusted: (cwd) => `Project scope skipped: ${cwd} is not trusted (run ama --trust there once).`
|
|
5087
5209
|
}
|
|
5088
5210
|
};
|
|
5089
|
-
|
|
5211
|
+
zh26 = {
|
|
5090
5212
|
scope: { user: "用户", project: "项目", workspace: "工作空间" },
|
|
5091
5213
|
panel: {
|
|
5092
5214
|
title: "记忆",
|
|
@@ -5150,11 +5272,11 @@ var init_memory = __esm({
|
|
|
5150
5272
|
});
|
|
5151
5273
|
|
|
5152
5274
|
// src/i18n/messages/auth.ts
|
|
5153
|
-
var
|
|
5275
|
+
var en27, zh27;
|
|
5154
5276
|
var init_auth = __esm({
|
|
5155
5277
|
"src/i18n/messages/auth.ts"() {
|
|
5156
5278
|
"use strict";
|
|
5157
|
-
|
|
5279
|
+
en27 = {
|
|
5158
5280
|
usage: `Usage: ama auth set [<provider>] [--auth-file <file>] read the key from stdin (no provider on a TTY: pick one)
|
|
5159
5281
|
ama auth list [--auth-file <file>]
|
|
5160
5282
|
ama auth remove <provider> [--auth-file <file>]
|
|
@@ -5262,7 +5384,7 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
|
|
|
5262
5384
|
relogin: (provider) => `${provider}: sign-in expired, run ama auth login ${provider}`
|
|
5263
5385
|
}
|
|
5264
5386
|
};
|
|
5265
|
-
|
|
5387
|
+
zh27 = {
|
|
5266
5388
|
usage: `用法:ama auth set [<provider>] [--auth-file <文件>] 从 stdin 读取 key(TTY 下不给供应商则先选)
|
|
5267
5389
|
ama auth list [--auth-file <文件>]
|
|
5268
5390
|
ama auth remove <provider> [--auth-file <文件>]
|
|
@@ -5374,11 +5496,11 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
|
|
|
5374
5496
|
});
|
|
5375
5497
|
|
|
5376
5498
|
// src/i18n/messages/settings.ts
|
|
5377
|
-
var
|
|
5499
|
+
var en28, zh28;
|
|
5378
5500
|
var init_settings = __esm({
|
|
5379
5501
|
"src/i18n/messages/settings.ts"() {
|
|
5380
5502
|
"use strict";
|
|
5381
|
-
|
|
5503
|
+
en28 = {
|
|
5382
5504
|
groups: {
|
|
5383
5505
|
ui: "Interface",
|
|
5384
5506
|
model: "Model",
|
|
@@ -5402,6 +5524,7 @@ var init_settings = __esm({
|
|
|
5402
5524
|
"ui.statusLine": "Status line",
|
|
5403
5525
|
"ui.restoreOnCancel": "Restore on cancel",
|
|
5404
5526
|
"ui.enterWhileRunning": "Enter while running",
|
|
5527
|
+
"ui.programStatus": "Terminal program status",
|
|
5405
5528
|
"ui.quietStartup": "Startup screen",
|
|
5406
5529
|
"ui.ascii": "ASCII glyphs",
|
|
5407
5530
|
"ui.language": "Interface language",
|
|
@@ -5551,7 +5674,7 @@ var init_settings = __esm({
|
|
|
5551
5674
|
missingValue: "missing <value>"
|
|
5552
5675
|
}
|
|
5553
5676
|
};
|
|
5554
|
-
|
|
5677
|
+
zh28 = {
|
|
5555
5678
|
groups: {
|
|
5556
5679
|
ui: "界面",
|
|
5557
5680
|
model: "模型",
|
|
@@ -5574,6 +5697,7 @@ var init_settings = __esm({
|
|
|
5574
5697
|
"ui.statusLine": "底部信息行",
|
|
5575
5698
|
"ui.restoreOnCancel": "中断后放回原消息",
|
|
5576
5699
|
"ui.enterWhileRunning": "运行中按 Enter",
|
|
5700
|
+
"ui.programStatus": "终端程序状态",
|
|
5577
5701
|
"ui.quietStartup": "启动画面",
|
|
5578
5702
|
"ui.ascii": "ASCII 字形",
|
|
5579
5703
|
"ui.language": "界面语言",
|
|
@@ -5726,12 +5850,12 @@ var init_settings = __esm({
|
|
|
5726
5850
|
});
|
|
5727
5851
|
|
|
5728
5852
|
// src/i18n/messages/acp.ts
|
|
5729
|
-
var
|
|
5853
|
+
var en29, zh29;
|
|
5730
5854
|
var init_acp = __esm({
|
|
5731
5855
|
"src/i18n/messages/acp.ts"() {
|
|
5732
5856
|
"use strict";
|
|
5733
5857
|
init_format();
|
|
5734
|
-
|
|
5858
|
+
en29 = {
|
|
5735
5859
|
/** ACP 服务端(`ama --mode acp`)的现有文案。 */
|
|
5736
5860
|
core: {
|
|
5737
5861
|
missingParam: (key) => `missing ${key}`,
|
|
@@ -5793,7 +5917,7 @@ var init_acp = __esm({
|
|
|
5793
5917
|
authTerminal: (name, command3) => `${name} (run in a terminal: ${command3})`
|
|
5794
5918
|
}
|
|
5795
5919
|
};
|
|
5796
|
-
|
|
5920
|
+
zh29 = {
|
|
5797
5921
|
core: {
|
|
5798
5922
|
missingParam: (key) => `缺少 ${key}`,
|
|
5799
5923
|
promptNotArray: "prompt 应为内容块数组",
|
|
@@ -5852,7 +5976,7 @@ var init_acp = __esm({
|
|
|
5852
5976
|
});
|
|
5853
5977
|
|
|
5854
5978
|
// src/i18n/catalog.ts
|
|
5855
|
-
var
|
|
5979
|
+
var en30, zh30, CATALOGS, MESSAGE_DOMAINS;
|
|
5856
5980
|
var init_catalog = __esm({
|
|
5857
5981
|
"src/i18n/catalog.ts"() {
|
|
5858
5982
|
"use strict";
|
|
@@ -5876,7 +6000,7 @@ var init_catalog = __esm({
|
|
|
5876
6000
|
init_auth();
|
|
5877
6001
|
init_settings();
|
|
5878
6002
|
init_acp();
|
|
5879
|
-
|
|
6003
|
+
en30 = {
|
|
5880
6004
|
cli: en3,
|
|
5881
6005
|
subcommands: en6,
|
|
5882
6006
|
interactive: en10,
|
|
@@ -5885,20 +6009,20 @@ var init_catalog = __esm({
|
|
|
5885
6009
|
rewind: en13,
|
|
5886
6010
|
panels: en14,
|
|
5887
6011
|
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:
|
|
6012
|
+
report: en17,
|
|
6013
|
+
print: en18,
|
|
6014
|
+
config: en20,
|
|
6015
|
+
drivers: en21,
|
|
6016
|
+
session: en22,
|
|
6017
|
+
errors: en23,
|
|
6018
|
+
agents: en24,
|
|
6019
|
+
trace: en25,
|
|
6020
|
+
memory: en26,
|
|
6021
|
+
auth: en27,
|
|
6022
|
+
settings: en28,
|
|
6023
|
+
acp: en29
|
|
5900
6024
|
};
|
|
5901
|
-
|
|
6025
|
+
zh30 = {
|
|
5902
6026
|
cli: zh3,
|
|
5903
6027
|
subcommands: zh6,
|
|
5904
6028
|
interactive: zh10,
|
|
@@ -5907,21 +6031,21 @@ var init_catalog = __esm({
|
|
|
5907
6031
|
rewind: zh13,
|
|
5908
6032
|
panels: zh14,
|
|
5909
6033
|
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:
|
|
6034
|
+
report: zh17,
|
|
6035
|
+
print: zh18,
|
|
6036
|
+
config: zh20,
|
|
6037
|
+
drivers: zh21,
|
|
6038
|
+
session: zh22,
|
|
6039
|
+
errors: zh23,
|
|
6040
|
+
agents: zh24,
|
|
6041
|
+
trace: zh25,
|
|
6042
|
+
memory: zh26,
|
|
6043
|
+
auth: zh27,
|
|
6044
|
+
settings: zh28,
|
|
6045
|
+
acp: zh29
|
|
5922
6046
|
};
|
|
5923
|
-
CATALOGS = { en:
|
|
5924
|
-
MESSAGE_DOMAINS = Object.keys(
|
|
6047
|
+
CATALOGS = { en: en30, zh: zh30 };
|
|
6048
|
+
MESSAGE_DOMAINS = Object.keys(en30);
|
|
5925
6049
|
}
|
|
5926
6050
|
});
|
|
5927
6051
|
|
|
@@ -6432,6 +6556,35 @@ var init_args = __esm({
|
|
|
6432
6556
|
}
|
|
6433
6557
|
});
|
|
6434
6558
|
|
|
6559
|
+
// src/config/fs-retry.ts
|
|
6560
|
+
function isTransientFsError(code, platform = process.platform) {
|
|
6561
|
+
return platform === "win32" && typeof code === "string" && TRANSIENT_WIN32.has(code);
|
|
6562
|
+
}
|
|
6563
|
+
function sleepSync(ms) {
|
|
6564
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
6565
|
+
}
|
|
6566
|
+
function retryTransientFs(fn, options = {}) {
|
|
6567
|
+
const attempts2 = options.attempts ?? 8;
|
|
6568
|
+
const delayMs = options.delayMs ?? 20;
|
|
6569
|
+
const sleep6 = options.sleep ?? sleepSync;
|
|
6570
|
+
for (let n = 1; ; n++) {
|
|
6571
|
+
try {
|
|
6572
|
+
return fn();
|
|
6573
|
+
} catch (error2) {
|
|
6574
|
+
const code = error2.code;
|
|
6575
|
+
if (n >= attempts2 || !isTransientFsError(code, options.platform)) throw error2;
|
|
6576
|
+
sleep6(delayMs * n);
|
|
6577
|
+
}
|
|
6578
|
+
}
|
|
6579
|
+
}
|
|
6580
|
+
var TRANSIENT_WIN32;
|
|
6581
|
+
var init_fs_retry = __esm({
|
|
6582
|
+
"src/config/fs-retry.ts"() {
|
|
6583
|
+
"use strict";
|
|
6584
|
+
TRANSIENT_WIN32 = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY"]);
|
|
6585
|
+
}
|
|
6586
|
+
});
|
|
6587
|
+
|
|
6435
6588
|
// src/config/checker.ts
|
|
6436
6589
|
function join(path, key) {
|
|
6437
6590
|
if (typeof key === "number") return `${path}[${key}]`;
|
|
@@ -7271,6 +7424,7 @@ function validateConfig(value) {
|
|
|
7271
7424
|
"animation",
|
|
7272
7425
|
"restoreOnCancel",
|
|
7273
7426
|
"enterWhileRunning",
|
|
7427
|
+
"programStatus",
|
|
7274
7428
|
...W5_UI_KEYS,
|
|
7275
7429
|
...W6_UI_KEYS
|
|
7276
7430
|
],
|
|
@@ -7286,6 +7440,7 @@ function validateConfig(value) {
|
|
|
7286
7440
|
c.boolean(s2, "animation", p);
|
|
7287
7441
|
c.boolean(s2, "restoreOnCancel", p);
|
|
7288
7442
|
c.oneOf(s2, "enterWhileRunning", p, ["queue", "interrupt"]);
|
|
7443
|
+
c.oneOf(s2, "programStatus", p, ["auto", "on", "off"]);
|
|
7289
7444
|
checkUiW5(c, s2, p);
|
|
7290
7445
|
checkUiW6(c, s2, p);
|
|
7291
7446
|
}
|
|
@@ -7745,7 +7900,12 @@ function writeAuthFile(path, file) {
|
|
|
7745
7900
|
const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
7746
7901
|
(0, import_node_fs3.writeFileSync)(tmp, `${JSON.stringify(file, null, 2)}
|
|
7747
7902
|
`, { mode: 384 });
|
|
7748
|
-
|
|
7903
|
+
try {
|
|
7904
|
+
retryTransientFs(() => (0, import_node_fs3.renameSync)(tmp, path));
|
|
7905
|
+
} catch (error2) {
|
|
7906
|
+
(0, import_node_fs3.rmSync)(tmp, { force: true });
|
|
7907
|
+
throw error2;
|
|
7908
|
+
}
|
|
7749
7909
|
if (process.platform !== "win32") (0, import_node_fs3.chmodSync)(path, 384);
|
|
7750
7910
|
}
|
|
7751
7911
|
function setAuthKey(path, provider, apiKey) {
|
|
@@ -7796,6 +7956,7 @@ var init_auth_file = __esm({
|
|
|
7796
7956
|
"src/config/auth-file.ts"() {
|
|
7797
7957
|
"use strict";
|
|
7798
7958
|
import_node_fs3 = require("node:fs");
|
|
7959
|
+
init_fs_retry();
|
|
7799
7960
|
import_node_path4 = require("node:path");
|
|
7800
7961
|
init_load();
|
|
7801
7962
|
init_paths();
|
|
@@ -10958,7 +11119,7 @@ var init_catalog_data = __esm({
|
|
|
10958
11119
|
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}}]}',
|
|
10959
11120
|
chatgpt: '{"version":1,"provider":"chatgpt","modelsDev":false,"models":[]}',
|
|
10960
11121
|
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}}]}',
|
|
10961
|
-
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 时)计,作上界;平峰为半价。快照价是平峰价或旧价"}]}',
|
|
11122
|
+
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}}]}',
|
|
10962
11123
|
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}}]}',
|
|
10963
11124
|
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"}]}',
|
|
10964
11125
|
lmstudio: '{"version":1,"provider":"lmstudio","modelsDev":false,"models":[]}',
|
|
@@ -12497,14 +12658,48 @@ function allowsImages(options) {
|
|
|
12497
12658
|
return options?.model === void 0 || options.model.input.includes("image");
|
|
12498
12659
|
}
|
|
12499
12660
|
function normalizeContext(context, options) {
|
|
12500
|
-
const
|
|
12661
|
+
const head = new SystemState();
|
|
12662
|
+
const tools = new SystemState();
|
|
12501
12663
|
const messages = [];
|
|
12502
12664
|
const allowImages = allowsImages(options);
|
|
12665
|
+
const fold = removesToolsMidway(context.messages);
|
|
12666
|
+
let pending = [];
|
|
12667
|
+
const flush = () => {
|
|
12668
|
+
if (pending.length === 0) return;
|
|
12669
|
+
messages.push({ role: "user", content: systemReminderText(pending), timestamp: 0 });
|
|
12670
|
+
pending = [];
|
|
12671
|
+
};
|
|
12503
12672
|
for (const message of context.messages) {
|
|
12504
|
-
if (message.role
|
|
12505
|
-
|
|
12673
|
+
if (message.role !== "system") {
|
|
12674
|
+
flush();
|
|
12675
|
+
messages.push(filterMessage(message, allowImages));
|
|
12676
|
+
continue;
|
|
12677
|
+
}
|
|
12678
|
+
tools.apply(message);
|
|
12679
|
+
if (fold || messages.length === 0) {
|
|
12680
|
+
head.apply(message);
|
|
12681
|
+
continue;
|
|
12682
|
+
}
|
|
12683
|
+
const text = renderSystemUpdate(message);
|
|
12684
|
+
if (text.length > 0) pending.push(text);
|
|
12685
|
+
}
|
|
12686
|
+
flush();
|
|
12687
|
+
return { ...head.snapshot(), tools: tools.snapshot().tools, messages };
|
|
12688
|
+
}
|
|
12689
|
+
function removesToolsMidway(transcript) {
|
|
12690
|
+
let started = false;
|
|
12691
|
+
for (const message of transcript) {
|
|
12692
|
+
if (message.role !== "system") started = true;
|
|
12693
|
+
else if (started && (message.toolsRemoved?.length ?? 0) > 0) return true;
|
|
12506
12694
|
}
|
|
12507
|
-
return
|
|
12695
|
+
return false;
|
|
12696
|
+
}
|
|
12697
|
+
function systemReminderText(updates) {
|
|
12698
|
+
return `<system-reminder>
|
|
12699
|
+
${updates.join("\n\n")}
|
|
12700
|
+
|
|
12701
|
+
These updates replace the earlier versions of those system prompt sections.
|
|
12702
|
+
</system-reminder>`;
|
|
12508
12703
|
}
|
|
12509
12704
|
function renderSystemUpdate(message) {
|
|
12510
12705
|
const parts = [];
|
|
@@ -21553,8 +21748,10 @@ var init_session_cache = __esm({
|
|
|
21553
21748
|
return stats;
|
|
21554
21749
|
}
|
|
21555
21750
|
/**
|
|
21556
|
-
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3
|
|
21557
|
-
*
|
|
21751
|
+
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3):上一次请求(含保温)距今超过目录承诺的 TTL。
|
|
21752
|
+
* 目录没有承诺 TTL 时返回 false:隐式缓存的寿命可能远长于 10 分钟,按猜测的寿命提前裁剪会改写
|
|
21753
|
+
* 仍然有效的缓存(隐式 600 s 只用于未命中归因)。只对 `reported` 端点判断;`silent` / `unknown`
|
|
21754
|
+
* 返回 false,档一退化为只按阈值。
|
|
21558
21755
|
*/
|
|
21559
21756
|
isCold() {
|
|
21560
21757
|
const prev = this.prev;
|
|
@@ -21563,7 +21760,7 @@ var init_session_cache = __esm({
|
|
|
21563
21760
|
const endpoint = endpointKey({ model, baseUrl: model.baseUrl ?? "" });
|
|
21564
21761
|
if (this.tracker.get(endpoint, model.compat?.cacheReporting) !== "reported") return false;
|
|
21565
21762
|
const ttl = cacheTtlMs(this.modelOf(prev), prev.options.cacheRetention);
|
|
21566
|
-
return this.now() - prev.at >
|
|
21763
|
+
return ttl !== void 0 && this.now() - prev.at > ttl;
|
|
21567
21764
|
}
|
|
21568
21765
|
/**
|
|
21569
21766
|
* 摘要续写的前缀(第三波 §1.8):当前转录按回合同样的方式转换,且上一次 turn 请求的消息
|
|
@@ -21853,6 +22050,30 @@ var init_breaker = __esm({
|
|
|
21853
22050
|
}
|
|
21854
22051
|
});
|
|
21855
22052
|
|
|
22053
|
+
// src/compaction/prefix-estimate.ts
|
|
22054
|
+
function estimatePrefixTokens(sections, tools) {
|
|
22055
|
+
const message = { role: "system", sections: { ...sections }, timestamp: 0 };
|
|
22056
|
+
if (tools.length > 0) message.toolsAdded = [...tools];
|
|
22057
|
+
return estimateMessageTokens(message);
|
|
22058
|
+
}
|
|
22059
|
+
function withPrefixBaseline(estimate, hasSystemMessage, prefix) {
|
|
22060
|
+
if (estimate.usageTokens > 0) return { ...estimate, source: "usage" };
|
|
22061
|
+
if (hasSystemMessage) return { ...estimate, source: "estimate" };
|
|
22062
|
+
const base4 = prefix();
|
|
22063
|
+
return {
|
|
22064
|
+
...estimate,
|
|
22065
|
+
tokens: estimate.tokens + base4,
|
|
22066
|
+
trailingTokens: estimate.trailingTokens + base4,
|
|
22067
|
+
source: "prefix"
|
|
22068
|
+
};
|
|
22069
|
+
}
|
|
22070
|
+
var init_prefix_estimate = __esm({
|
|
22071
|
+
"src/compaction/prefix-estimate.ts"() {
|
|
22072
|
+
"use strict";
|
|
22073
|
+
init_estimate();
|
|
22074
|
+
}
|
|
22075
|
+
});
|
|
22076
|
+
|
|
21856
22077
|
// src/compaction/protect.ts
|
|
21857
22078
|
function unescapeXml(text) {
|
|
21858
22079
|
return text.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
@@ -22045,6 +22266,142 @@ Keep it concise; preserve exact file paths and error messages.`;
|
|
|
22045
22266
|
}
|
|
22046
22267
|
});
|
|
22047
22268
|
|
|
22269
|
+
// src/agent/prompt-rules.ts
|
|
22270
|
+
function baseRules(tools) {
|
|
22271
|
+
if (tools.length === 0) return [];
|
|
22272
|
+
const rules = [DESTRUCTIVE_RULE];
|
|
22273
|
+
const has = (name) => tools.some((tool) => tool.name === name);
|
|
22274
|
+
if (has("read")) rules.push(PARALLEL_READS_RULE);
|
|
22275
|
+
if (has("grep") && has("glob")) rules.push(LOCATE_RULE);
|
|
22276
|
+
return rules;
|
|
22277
|
+
}
|
|
22278
|
+
var DESTRUCTIVE_RULE, PARALLEL_READS_RULE, LOCATE_RULE;
|
|
22279
|
+
var init_prompt_rules = __esm({
|
|
22280
|
+
"src/agent/prompt-rules.ts"() {
|
|
22281
|
+
"use strict";
|
|
22282
|
+
DESTRUCTIVE_RULE = "Ask before destructive commands (rm -rf, git reset --hard, force push, deleting branches) unless the user requested them.";
|
|
22283
|
+
PARALLEL_READS_RULE = "Batch independent read-only tool calls into one turn.";
|
|
22284
|
+
LOCATE_RULE = "Locate code with grep/glob before reading; do not guess file paths.";
|
|
22285
|
+
}
|
|
22286
|
+
});
|
|
22287
|
+
|
|
22288
|
+
// src/agent/system-prompt.ts
|
|
22289
|
+
function firstLine(text) {
|
|
22290
|
+
return text.split("\n", 1)[0]?.trim() ?? "";
|
|
22291
|
+
}
|
|
22292
|
+
function toolDecl(tool) {
|
|
22293
|
+
return { name: tool.name, description: tool.description, parameters: tool.parameters };
|
|
22294
|
+
}
|
|
22295
|
+
function toolDecls(tools) {
|
|
22296
|
+
return [...tools].sort((a, b) => a.name.localeCompare(b.name)).map(toolDecl);
|
|
22297
|
+
}
|
|
22298
|
+
function assembleSections(input2) {
|
|
22299
|
+
const tools = [...input2.tools].sort((a, b) => a.name.localeCompare(b.name));
|
|
22300
|
+
const toolLines = tools.map((tool) => {
|
|
22301
|
+
const snippet = tool.promptSnippet ?? firstLine(tool.description);
|
|
22302
|
+
return snippet.startsWith(`${tool.name}:`) ? `- ${snippet}` : `- ${tool.name}: ${snippet}`;
|
|
22303
|
+
});
|
|
22304
|
+
const rules = [
|
|
22305
|
+
...baseRules(tools),
|
|
22306
|
+
...tools.flatMap((tool) => tool.promptGuidelines ?? []),
|
|
22307
|
+
...input2.extraRules ?? []
|
|
22308
|
+
];
|
|
22309
|
+
const projectContext = (input2.contextFiles ?? []).map((file) => `<file path="${escapeXml(file.path)}">
|
|
22310
|
+
${file.content.trim()}
|
|
22311
|
+
</file>`).join("\n\n");
|
|
22312
|
+
let skills = input2.skillsIndex;
|
|
22313
|
+
if (skills === void 0 && input2.skills !== void 0 && input2.skills.length > 0) {
|
|
22314
|
+
skills = [
|
|
22315
|
+
"<available_skills>",
|
|
22316
|
+
...input2.skills.map(
|
|
22317
|
+
(skill) => `<skill name="${escapeXml(skill.name)}" location="${escapeXml(skill.location)}">${escapeXml(skill.description)}</skill>`
|
|
22318
|
+
),
|
|
22319
|
+
"</available_skills>"
|
|
22320
|
+
].join("\n");
|
|
22321
|
+
}
|
|
22322
|
+
const host = (input2.hostInstructions ?? []).map((text) => text.trim()).filter(Boolean);
|
|
22323
|
+
const nonEmpty3 = (text) => text === void 0 || text.trim() === "" ? void 0 : text;
|
|
22324
|
+
return {
|
|
22325
|
+
preamble: input2.preamble ?? DEFAULT_PREAMBLE,
|
|
22326
|
+
tools: toolLines.length > 0 ? `Available tools:
|
|
22327
|
+
${toolLines.join("\n")}` : void 0,
|
|
22328
|
+
rules: rules.length > 0 ? `Rules:
|
|
22329
|
+
${rules.map((rule) => `- ${rule}`).join("\n")}` : void 0,
|
|
22330
|
+
project_context: nonEmpty3(projectContext),
|
|
22331
|
+
skills: nonEmpty3(skills),
|
|
22332
|
+
memory: nonEmpty3(input2.memory),
|
|
22333
|
+
hooks: nonEmpty3(input2.hookContext),
|
|
22334
|
+
cwd: `Current working directory: ${input2.cwd}`,
|
|
22335
|
+
host: host.length > 0 ? host.join("\n\n") : void 0,
|
|
22336
|
+
role: nonEmpty3(input2.role)
|
|
22337
|
+
};
|
|
22338
|
+
}
|
|
22339
|
+
function definedSections(sections) {
|
|
22340
|
+
const out = {};
|
|
22341
|
+
for (const name of SECTION_ORDER) {
|
|
22342
|
+
const text = sections[name];
|
|
22343
|
+
if (text !== void 0) out[name] = text;
|
|
22344
|
+
}
|
|
22345
|
+
return out;
|
|
22346
|
+
}
|
|
22347
|
+
function currentSystemState(messages) {
|
|
22348
|
+
return replaySystem(messages);
|
|
22349
|
+
}
|
|
22350
|
+
function sameTool(a, b) {
|
|
22351
|
+
return a.description === b.description && JSON.stringify(a.parameters) === JSON.stringify(b.parameters);
|
|
22352
|
+
}
|
|
22353
|
+
function diffSystem(current3, sections, tools, timestamp = Date.now()) {
|
|
22354
|
+
if (current3 === void 0) {
|
|
22355
|
+
const full = { role: "system", sections: { ...sections }, timestamp };
|
|
22356
|
+
if (tools.length > 0) full.toolsAdded = tools.map((tool) => ({ ...tool }));
|
|
22357
|
+
return full;
|
|
22358
|
+
}
|
|
22359
|
+
const patch = {};
|
|
22360
|
+
for (const [name, text] of Object.entries(sections)) {
|
|
22361
|
+
if (current3.sections[name] !== text) patch[name] = text;
|
|
22362
|
+
}
|
|
22363
|
+
for (const name of Object.keys(current3.sections)) {
|
|
22364
|
+
if (!(name in sections)) patch[name] = null;
|
|
22365
|
+
}
|
|
22366
|
+
const before2 = new Map(current3.tools.map((tool) => [tool.name, tool]));
|
|
22367
|
+
const after = new Map(tools.map((tool) => [tool.name, tool]));
|
|
22368
|
+
const toolsAdded = tools.filter((tool) => {
|
|
22369
|
+
const old = before2.get(tool.name);
|
|
22370
|
+
return old === void 0 || !sameTool(old, tool);
|
|
22371
|
+
});
|
|
22372
|
+
const toolsRemoved = [...before2.keys()].filter((name) => !after.has(name));
|
|
22373
|
+
if (Object.keys(patch).length === 0 && toolsAdded.length === 0 && toolsRemoved.length === 0) {
|
|
22374
|
+
return void 0;
|
|
22375
|
+
}
|
|
22376
|
+
const message = { role: "system", sections: patch, timestamp };
|
|
22377
|
+
if (toolsAdded.length > 0) message.toolsAdded = toolsAdded.map((tool) => ({ ...tool }));
|
|
22378
|
+
if (toolsRemoved.length > 0) message.toolsRemoved = toolsRemoved;
|
|
22379
|
+
return message;
|
|
22380
|
+
}
|
|
22381
|
+
var SECTION_ORDER, DEFAULT_PREAMBLE;
|
|
22382
|
+
var init_system_prompt = __esm({
|
|
22383
|
+
"src/agent/system-prompt.ts"() {
|
|
22384
|
+
"use strict";
|
|
22385
|
+
init_projection();
|
|
22386
|
+
init_index_prompt();
|
|
22387
|
+
init_prompt_rules();
|
|
22388
|
+
SECTION_ORDER = [
|
|
22389
|
+
"preamble",
|
|
22390
|
+
"tools",
|
|
22391
|
+
"rules",
|
|
22392
|
+
"project_context",
|
|
22393
|
+
"skills",
|
|
22394
|
+
// [W6-C0] 记忆索引(W6-M,docs/wave6-plan.md §3.4);未开启时为 undefined,字节不变
|
|
22395
|
+
"memory",
|
|
22396
|
+
"hooks",
|
|
22397
|
+
"cwd",
|
|
22398
|
+
"host",
|
|
22399
|
+
"role"
|
|
22400
|
+
];
|
|
22401
|
+
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.";
|
|
22402
|
+
}
|
|
22403
|
+
});
|
|
22404
|
+
|
|
22048
22405
|
// src/agent/session-compaction.ts
|
|
22049
22406
|
var DEFAULT_COMPACTION_SETTINGS, KEEP_RECENT_MAX_RATIO, HOOK_CONTEXT_CUSTOM_TYPE, CompactionController;
|
|
22050
22407
|
var init_session_compaction = __esm({
|
|
@@ -22053,12 +22410,14 @@ var init_session_compaction = __esm({
|
|
|
22053
22410
|
init_errors();
|
|
22054
22411
|
init_breaker();
|
|
22055
22412
|
init_estimate();
|
|
22413
|
+
init_prefix_estimate();
|
|
22056
22414
|
init_prune_tier();
|
|
22057
22415
|
init_protect();
|
|
22058
22416
|
init_post_compact();
|
|
22059
22417
|
init_summarize_tier();
|
|
22060
22418
|
init_branch_summary();
|
|
22061
22419
|
init_projection();
|
|
22420
|
+
init_system_prompt();
|
|
22062
22421
|
DEFAULT_COMPACTION_SETTINGS = {
|
|
22063
22422
|
enabled: true,
|
|
22064
22423
|
reserveTokens: 16384,
|
|
@@ -22098,6 +22457,39 @@ var init_session_compaction = __esm({
|
|
|
22098
22457
|
const branch = this.core.manager.branch();
|
|
22099
22458
|
return estimateProjectedTokens(buildProjection(branch).items, branch);
|
|
22100
22459
|
}
|
|
22460
|
+
/**
|
|
22461
|
+
* 统计用的上下文量(`getStats`):投影估算标上来源;系统消息还没落盘时加上前缀基线(系统提示 +
|
|
22462
|
+
* 工具声明,只统计不写分支)。附自动压缩的两个阈值(自动压缩可用时)。压缩调度仍用 `estimate()`。
|
|
22463
|
+
*/
|
|
22464
|
+
contextStats() {
|
|
22465
|
+
const branch = this.core.manager.branch();
|
|
22466
|
+
const items = buildProjection(branch).items;
|
|
22467
|
+
const sourced = withPrefixBaseline(
|
|
22468
|
+
estimateProjectedTokens(items, branch),
|
|
22469
|
+
items.some((item) => item.message.role === "system"),
|
|
22470
|
+
() => this.prefixTokens()
|
|
22471
|
+
);
|
|
22472
|
+
const detail = {
|
|
22473
|
+
source: sourced.source,
|
|
22474
|
+
usageTokens: sourced.usageTokens,
|
|
22475
|
+
trailingTokens: sourced.trailingTokens
|
|
22476
|
+
};
|
|
22477
|
+
const budget = this.budget();
|
|
22478
|
+
const policy = this.prunePolicy();
|
|
22479
|
+
if (this.breaker.autoEnabled && budget !== void 0 && policy !== void 0) {
|
|
22480
|
+
detail.autoCompactAt = budget;
|
|
22481
|
+
detail.pruneAt = Math.floor(policy.triggerTokens);
|
|
22482
|
+
}
|
|
22483
|
+
return { tokens: sourced.tokens, detail };
|
|
22484
|
+
}
|
|
22485
|
+
/** 将要发送的系统提示 + 工具声明的估算(与首条 system 消息同样装配,不落盘)。 */
|
|
22486
|
+
prefixTokens() {
|
|
22487
|
+
const core = this.core;
|
|
22488
|
+
const tools = core.activeToolNames().map((name) => core.activeTool(name)).filter((tool) => tool !== void 0);
|
|
22489
|
+
const system = core.childBase?.().system ?? core.options.system ?? {};
|
|
22490
|
+
const sections = definedSections(assembleSections({ ...system, tools, cwd: core.cwd }));
|
|
22491
|
+
return estimatePrefixTokens(sections, toolDecls(tools));
|
|
22492
|
+
}
|
|
22101
22493
|
budget() {
|
|
22102
22494
|
const window2 = this.core.model().contextWindow;
|
|
22103
22495
|
return window2 === void 0 ? void 0 : Math.max(0, window2 - this.settings.reserveTokens);
|
|
@@ -22463,7 +22855,8 @@ function computeStats(input2) {
|
|
|
22463
22855
|
addCost(entry.usage);
|
|
22464
22856
|
}
|
|
22465
22857
|
}
|
|
22466
|
-
const
|
|
22858
|
+
const contextTokens = input2.context?.tokens ?? input2.contextTokens;
|
|
22859
|
+
const contextPercent = input2.contextWindow === void 0 || contextTokens === void 0 || input2.contextWindow <= 0 ? void 0 : Math.min(100, Math.round(contextTokens / input2.contextWindow * 1e3) / 10);
|
|
22467
22860
|
const stats = {
|
|
22468
22861
|
sessionId: input2.sessionId,
|
|
22469
22862
|
sessionFile: input2.sessionFile,
|
|
@@ -22473,10 +22866,11 @@ function computeStats(input2) {
|
|
|
22473
22866
|
toolResults,
|
|
22474
22867
|
tokens,
|
|
22475
22868
|
cost: cost2,
|
|
22476
|
-
contextTokens
|
|
22869
|
+
contextTokens,
|
|
22477
22870
|
contextWindow: input2.contextWindow,
|
|
22478
22871
|
contextPercent
|
|
22479
22872
|
};
|
|
22873
|
+
if (input2.context !== void 0) stats.context = { ...input2.context.detail };
|
|
22480
22874
|
const rate = cacheHitRate(tokens);
|
|
22481
22875
|
if (rate !== void 0) stats.cacheHitRate = rate;
|
|
22482
22876
|
if (input2.cache !== void 0) stats.cache = input2.cache;
|
|
@@ -24078,6 +24472,8 @@ function applyRunnerEvent(record3, event, sink) {
|
|
|
24078
24472
|
case "usage":
|
|
24079
24473
|
if (event.usage !== void 0) record3.info.usage = event.usage;
|
|
24080
24474
|
if (event.unit === "usd" && event.amount !== void 0) record3.info.costUsd = event.amount;
|
|
24475
|
+
if (event.contextTokens !== void 0) record3.info.contextTokens = event.contextTokens;
|
|
24476
|
+
if (event.contextWindow !== void 0) record3.info.contextWindow = event.contextWindow;
|
|
24081
24477
|
return;
|
|
24082
24478
|
case "notice":
|
|
24083
24479
|
sink.log(event.level, `[task ${taskId}] ${event.text}`);
|
|
@@ -24122,6 +24518,16 @@ function recordDisplay(record3, event, now) {
|
|
|
24122
24518
|
return;
|
|
24123
24519
|
}
|
|
24124
24520
|
}
|
|
24521
|
+
function taskContextPercent(info2) {
|
|
24522
|
+
const { contextTokens: used, contextWindow: size } = info2;
|
|
24523
|
+
if (used === void 0 || size === void 0 || size <= 0) return void 0;
|
|
24524
|
+
return Math.min(100, Math.round(used / size * 1e3) / 10);
|
|
24525
|
+
}
|
|
24526
|
+
function formatTaskContext(info2) {
|
|
24527
|
+
const percent3 = taskContextPercent(info2);
|
|
24528
|
+
if (percent3 === void 0) return void 0;
|
|
24529
|
+
return `${percent3 >= 10 ? Math.round(percent3) : percent3.toFixed(1)}%`;
|
|
24530
|
+
}
|
|
24125
24531
|
function startEvent(record3, handle) {
|
|
24126
24532
|
const event = {
|
|
24127
24533
|
type: "subagent_start",
|
|
@@ -25735,142 +26141,6 @@ var init_session_subagent = __esm({
|
|
|
25735
26141
|
}
|
|
25736
26142
|
});
|
|
25737
26143
|
|
|
25738
|
-
// src/agent/prompt-rules.ts
|
|
25739
|
-
function baseRules(tools) {
|
|
25740
|
-
if (tools.length === 0) return [];
|
|
25741
|
-
const rules = [DESTRUCTIVE_RULE];
|
|
25742
|
-
const has = (name) => tools.some((tool) => tool.name === name);
|
|
25743
|
-
if (has("read")) rules.push(PARALLEL_READS_RULE);
|
|
25744
|
-
if (has("grep") && has("glob")) rules.push(LOCATE_RULE);
|
|
25745
|
-
return rules;
|
|
25746
|
-
}
|
|
25747
|
-
var DESTRUCTIVE_RULE, PARALLEL_READS_RULE, LOCATE_RULE;
|
|
25748
|
-
var init_prompt_rules = __esm({
|
|
25749
|
-
"src/agent/prompt-rules.ts"() {
|
|
25750
|
-
"use strict";
|
|
25751
|
-
DESTRUCTIVE_RULE = "Ask before destructive commands (rm -rf, git reset --hard, force push, deleting branches) unless the user requested them.";
|
|
25752
|
-
PARALLEL_READS_RULE = "Batch independent read-only tool calls into one turn.";
|
|
25753
|
-
LOCATE_RULE = "Locate code with grep/glob before reading; do not guess file paths.";
|
|
25754
|
-
}
|
|
25755
|
-
});
|
|
25756
|
-
|
|
25757
|
-
// src/agent/system-prompt.ts
|
|
25758
|
-
function firstLine(text) {
|
|
25759
|
-
return text.split("\n", 1)[0]?.trim() ?? "";
|
|
25760
|
-
}
|
|
25761
|
-
function toolDecl(tool) {
|
|
25762
|
-
return { name: tool.name, description: tool.description, parameters: tool.parameters };
|
|
25763
|
-
}
|
|
25764
|
-
function toolDecls(tools) {
|
|
25765
|
-
return [...tools].sort((a, b) => a.name.localeCompare(b.name)).map(toolDecl);
|
|
25766
|
-
}
|
|
25767
|
-
function assembleSections(input2) {
|
|
25768
|
-
const tools = [...input2.tools].sort((a, b) => a.name.localeCompare(b.name));
|
|
25769
|
-
const toolLines = tools.map((tool) => {
|
|
25770
|
-
const snippet = tool.promptSnippet ?? firstLine(tool.description);
|
|
25771
|
-
return snippet.startsWith(`${tool.name}:`) ? `- ${snippet}` : `- ${tool.name}: ${snippet}`;
|
|
25772
|
-
});
|
|
25773
|
-
const rules = [
|
|
25774
|
-
...baseRules(tools),
|
|
25775
|
-
...tools.flatMap((tool) => tool.promptGuidelines ?? []),
|
|
25776
|
-
...input2.extraRules ?? []
|
|
25777
|
-
];
|
|
25778
|
-
const projectContext = (input2.contextFiles ?? []).map((file) => `<file path="${escapeXml(file.path)}">
|
|
25779
|
-
${file.content.trim()}
|
|
25780
|
-
</file>`).join("\n\n");
|
|
25781
|
-
let skills = input2.skillsIndex;
|
|
25782
|
-
if (skills === void 0 && input2.skills !== void 0 && input2.skills.length > 0) {
|
|
25783
|
-
skills = [
|
|
25784
|
-
"<available_skills>",
|
|
25785
|
-
...input2.skills.map(
|
|
25786
|
-
(skill) => `<skill name="${escapeXml(skill.name)}" location="${escapeXml(skill.location)}">${escapeXml(skill.description)}</skill>`
|
|
25787
|
-
),
|
|
25788
|
-
"</available_skills>"
|
|
25789
|
-
].join("\n");
|
|
25790
|
-
}
|
|
25791
|
-
const host = (input2.hostInstructions ?? []).map((text) => text.trim()).filter(Boolean);
|
|
25792
|
-
const nonEmpty3 = (text) => text === void 0 || text.trim() === "" ? void 0 : text;
|
|
25793
|
-
return {
|
|
25794
|
-
preamble: input2.preamble ?? DEFAULT_PREAMBLE,
|
|
25795
|
-
tools: toolLines.length > 0 ? `Available tools:
|
|
25796
|
-
${toolLines.join("\n")}` : void 0,
|
|
25797
|
-
rules: rules.length > 0 ? `Rules:
|
|
25798
|
-
${rules.map((rule) => `- ${rule}`).join("\n")}` : void 0,
|
|
25799
|
-
project_context: nonEmpty3(projectContext),
|
|
25800
|
-
skills: nonEmpty3(skills),
|
|
25801
|
-
memory: nonEmpty3(input2.memory),
|
|
25802
|
-
hooks: nonEmpty3(input2.hookContext),
|
|
25803
|
-
cwd: `Current working directory: ${input2.cwd}`,
|
|
25804
|
-
host: host.length > 0 ? host.join("\n\n") : void 0,
|
|
25805
|
-
role: nonEmpty3(input2.role)
|
|
25806
|
-
};
|
|
25807
|
-
}
|
|
25808
|
-
function definedSections(sections) {
|
|
25809
|
-
const out = {};
|
|
25810
|
-
for (const name of SECTION_ORDER) {
|
|
25811
|
-
const text = sections[name];
|
|
25812
|
-
if (text !== void 0) out[name] = text;
|
|
25813
|
-
}
|
|
25814
|
-
return out;
|
|
25815
|
-
}
|
|
25816
|
-
function currentSystemState(messages) {
|
|
25817
|
-
return replaySystem(messages);
|
|
25818
|
-
}
|
|
25819
|
-
function sameTool(a, b) {
|
|
25820
|
-
return a.description === b.description && JSON.stringify(a.parameters) === JSON.stringify(b.parameters);
|
|
25821
|
-
}
|
|
25822
|
-
function diffSystem(current3, sections, tools, timestamp = Date.now()) {
|
|
25823
|
-
if (current3 === void 0) {
|
|
25824
|
-
const full = { role: "system", sections: { ...sections }, timestamp };
|
|
25825
|
-
if (tools.length > 0) full.toolsAdded = tools.map((tool) => ({ ...tool }));
|
|
25826
|
-
return full;
|
|
25827
|
-
}
|
|
25828
|
-
const patch = {};
|
|
25829
|
-
for (const [name, text] of Object.entries(sections)) {
|
|
25830
|
-
if (current3.sections[name] !== text) patch[name] = text;
|
|
25831
|
-
}
|
|
25832
|
-
for (const name of Object.keys(current3.sections)) {
|
|
25833
|
-
if (!(name in sections)) patch[name] = null;
|
|
25834
|
-
}
|
|
25835
|
-
const before2 = new Map(current3.tools.map((tool) => [tool.name, tool]));
|
|
25836
|
-
const after = new Map(tools.map((tool) => [tool.name, tool]));
|
|
25837
|
-
const toolsAdded = tools.filter((tool) => {
|
|
25838
|
-
const old = before2.get(tool.name);
|
|
25839
|
-
return old === void 0 || !sameTool(old, tool);
|
|
25840
|
-
});
|
|
25841
|
-
const toolsRemoved = [...before2.keys()].filter((name) => !after.has(name));
|
|
25842
|
-
if (Object.keys(patch).length === 0 && toolsAdded.length === 0 && toolsRemoved.length === 0) {
|
|
25843
|
-
return void 0;
|
|
25844
|
-
}
|
|
25845
|
-
const message = { role: "system", sections: patch, timestamp };
|
|
25846
|
-
if (toolsAdded.length > 0) message.toolsAdded = toolsAdded.map((tool) => ({ ...tool }));
|
|
25847
|
-
if (toolsRemoved.length > 0) message.toolsRemoved = toolsRemoved;
|
|
25848
|
-
return message;
|
|
25849
|
-
}
|
|
25850
|
-
var SECTION_ORDER, DEFAULT_PREAMBLE;
|
|
25851
|
-
var init_system_prompt = __esm({
|
|
25852
|
-
"src/agent/system-prompt.ts"() {
|
|
25853
|
-
"use strict";
|
|
25854
|
-
init_projection();
|
|
25855
|
-
init_index_prompt();
|
|
25856
|
-
init_prompt_rules();
|
|
25857
|
-
SECTION_ORDER = [
|
|
25858
|
-
"preamble",
|
|
25859
|
-
"tools",
|
|
25860
|
-
"rules",
|
|
25861
|
-
"project_context",
|
|
25862
|
-
"skills",
|
|
25863
|
-
// [W6-C0] 记忆索引(W6-M,docs/wave6-plan.md §3.4);未开启时为 undefined,字节不变
|
|
25864
|
-
"memory",
|
|
25865
|
-
"hooks",
|
|
25866
|
-
"cwd",
|
|
25867
|
-
"host",
|
|
25868
|
-
"role"
|
|
25869
|
-
];
|
|
25870
|
-
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.";
|
|
25871
|
-
}
|
|
25872
|
-
});
|
|
25873
|
-
|
|
25874
26144
|
// src/agent/session-sync.ts
|
|
25875
26145
|
function persistMessage(core, message) {
|
|
25876
26146
|
if (message.role === "custom") {
|
|
@@ -27770,15 +28040,15 @@ var init_session2 = __esm({
|
|
|
27770
28040
|
return lastAssistantText(this.manager.branch());
|
|
27771
28041
|
}
|
|
27772
28042
|
getStats() {
|
|
27773
|
-
const
|
|
28043
|
+
const context = this.compaction.contextStats();
|
|
27774
28044
|
const contextWindow = this.settings.model.contextWindow;
|
|
27775
28045
|
const stats = computeStats({
|
|
27776
28046
|
sessionId: this.manager.id,
|
|
27777
28047
|
sessionFile: this.manager.file(),
|
|
27778
28048
|
branch: this.manager.branch(),
|
|
27779
|
-
|
|
28049
|
+
context,
|
|
27780
28050
|
contextWindow,
|
|
27781
|
-
cache: this.cache.stats({ tokens:
|
|
28051
|
+
cache: this.cache.stats({ tokens: context.tokens, window: contextWindow }),
|
|
27782
28052
|
quota: this.lastQuota
|
|
27783
28053
|
});
|
|
27784
28054
|
return this.extensions.contributeStats(stats);
|
|
@@ -28826,8 +29096,8 @@ var init_shadow_git = __esm({
|
|
|
28826
29096
|
/** 新回合快照:返回提交 id 与是否该降级。 */
|
|
28827
29097
|
snapshot(parent, message) {
|
|
28828
29098
|
return exclusive(this.dir, async () => {
|
|
28829
|
-
const started = this.now();
|
|
28830
29099
|
await this.init();
|
|
29100
|
+
const started = this.now();
|
|
28831
29101
|
await this.writeExcludes();
|
|
28832
29102
|
if (!this.counted) {
|
|
28833
29103
|
const out = await this.run([
|
|
@@ -33316,6 +33586,8 @@ var init_codex_app_server = __esm({
|
|
|
33316
33586
|
tokensTotal;
|
|
33317
33587
|
tokensAtStart;
|
|
33318
33588
|
contextWindow;
|
|
33589
|
+
/** 最近一次请求的总量(`tokenUsage.last.totalTokens`)= 线程当前的上下文占用。 */
|
|
33590
|
+
contextTokens;
|
|
33319
33591
|
closed = false;
|
|
33320
33592
|
interruptRequested = false;
|
|
33321
33593
|
get sessionId() {
|
|
@@ -33455,6 +33727,7 @@ var init_codex_app_server = __esm({
|
|
|
33455
33727
|
input: end.inputTokens - (start?.inputTokens ?? 0),
|
|
33456
33728
|
output: end.outputTokens - (start?.outputTokens ?? 0),
|
|
33457
33729
|
cacheRead: end.cachedInputTokens - (start?.cachedInputTokens ?? 0),
|
|
33730
|
+
...this.contextTokens !== void 0 ? { contextTokens: this.contextTokens } : {},
|
|
33458
33731
|
...this.contextWindow !== void 0 ? { contextWindow: this.contextWindow } : {}
|
|
33459
33732
|
});
|
|
33460
33733
|
}
|
|
@@ -33478,6 +33751,8 @@ var init_codex_app_server = __esm({
|
|
|
33478
33751
|
const usage = params["tokenUsage"] ?? {};
|
|
33479
33752
|
const total = readTokens(usage["total"]);
|
|
33480
33753
|
if (total !== void 0) this.tokensTotal = total;
|
|
33754
|
+
const last = readTokens(usage["last"]);
|
|
33755
|
+
if (last !== void 0 && last.totalTokens > 0) this.contextTokens = last.totalTokens;
|
|
33481
33756
|
if (typeof usage["modelContextWindow"] === "number")
|
|
33482
33757
|
this.contextWindow = usage["modelContextWindow"];
|
|
33483
33758
|
return;
|
|
@@ -34396,6 +34671,8 @@ var init_runner2 = __esm({
|
|
|
34396
34671
|
agent;
|
|
34397
34672
|
/** [W6-C0] 本回合工具的骨架(id → 种类 / 状态 / 起止),回合结束写 `turn_trace`。 */
|
|
34398
34673
|
turnTools = /* @__PURE__ */ new Map();
|
|
34674
|
+
/** 外部 Agent 最近报告的上下文占用与窗口(只记数字,跨回合保留)。 */
|
|
34675
|
+
context = {};
|
|
34399
34676
|
get id() {
|
|
34400
34677
|
return this.sessionId;
|
|
34401
34678
|
}
|
|
@@ -34503,6 +34780,7 @@ var init_runner2 = __esm({
|
|
|
34503
34780
|
this.emit({ type: "notice", level: event.level, text: event.text });
|
|
34504
34781
|
return;
|
|
34505
34782
|
case "usage":
|
|
34783
|
+
this.noteContext(event.contextTokens, event.contextWindow);
|
|
34506
34784
|
if (event.costUsd !== void 0) {
|
|
34507
34785
|
turnCost.usd = event.costUsd;
|
|
34508
34786
|
const budget = this.request.budgetUsd;
|
|
@@ -34522,6 +34800,16 @@ var init_runner2 = __esm({
|
|
|
34522
34800
|
return;
|
|
34523
34801
|
}
|
|
34524
34802
|
}
|
|
34803
|
+
/** 上下文占用或窗口变了:记下并单独发一条只带它们的 usage(任务记录 / Agent 栏即时更新)。 */
|
|
34804
|
+
noteContext(tokens, window2) {
|
|
34805
|
+
const next = { ...this.context };
|
|
34806
|
+
if (tokens !== void 0) next.contextTokens = tokens;
|
|
34807
|
+
if (window2 !== void 0) next.contextWindow = window2;
|
|
34808
|
+
if (next.contextTokens === this.context.contextTokens && next.contextWindow === this.context.contextWindow)
|
|
34809
|
+
return;
|
|
34810
|
+
this.context = next;
|
|
34811
|
+
this.emit({ type: "usage", ...next });
|
|
34812
|
+
}
|
|
34525
34813
|
now() {
|
|
34526
34814
|
return (this.deps.now ?? Date.now)();
|
|
34527
34815
|
}
|
|
@@ -34610,7 +34898,8 @@ var init_runner2 = __esm({
|
|
|
34610
34898
|
sessionId: this.sessionId,
|
|
34611
34899
|
unit,
|
|
34612
34900
|
amount,
|
|
34613
|
-
...usage.totalTokens > 0 ? { tokens: usage.totalTokens } : {}
|
|
34901
|
+
...usage.totalTokens > 0 ? { tokens: usage.totalTokens } : {},
|
|
34902
|
+
...this.context
|
|
34614
34903
|
});
|
|
34615
34904
|
this.emit({ type: "usage", usage, unit, amount });
|
|
34616
34905
|
}
|
|
@@ -34851,6 +35140,8 @@ function aggregateExternal(entries) {
|
|
|
34851
35140
|
}
|
|
34852
35141
|
row3.amount += u.amount;
|
|
34853
35142
|
if (typeof u.tokens === "number") row3.tokens = (row3.tokens ?? 0) + u.tokens;
|
|
35143
|
+
if (typeof u.contextTokens === "number") row3.contextTokens = u.contextTokens;
|
|
35144
|
+
if (typeof u.contextWindow === "number") row3.contextWindow = u.contextWindow;
|
|
34854
35145
|
}
|
|
34855
35146
|
return { byAgent };
|
|
34856
35147
|
}
|
|
@@ -35855,11 +36146,17 @@ var init_acp_events = __esm({
|
|
|
35855
36146
|
usedWireIds = /* @__PURE__ */ new Set();
|
|
35856
36147
|
/** 上次 `session_info_update` 带出的标题。 */
|
|
35857
36148
|
lastTitle = null;
|
|
35858
|
-
/**
|
|
36149
|
+
/** 上次 `usage_update` 的内容(同值不重发)。 */
|
|
36150
|
+
lastUsage;
|
|
36151
|
+
/**
|
|
36152
|
+
* 会话 new / load / resume 的响应发出后由服务端调:`available_commands_update`、`config_option_update`
|
|
36153
|
+
* 与 `usage_update`(客户端可能刚重建线程,用量不去重,照发一次)。
|
|
36154
|
+
*/
|
|
35859
36155
|
announce() {
|
|
35860
36156
|
const { configOptions, commands: commands2 } = this.extras();
|
|
35861
36157
|
this.emit({ sessionUpdate: "available_commands_update", availableCommands: commands2 });
|
|
35862
36158
|
this.emit({ sessionUpdate: "config_option_update", configOptions });
|
|
36159
|
+
this.emitUsage(true);
|
|
35863
36160
|
}
|
|
35864
36161
|
/** 回合结束后由服务端调:`session_info_update`(标题与上次不同才带 title)。 */
|
|
35865
36162
|
emitSessionInfo(title, updatedAt) {
|
|
@@ -35974,6 +36271,9 @@ var init_acp_events = __esm({
|
|
|
35974
36271
|
}))
|
|
35975
36272
|
});
|
|
35976
36273
|
return;
|
|
36274
|
+
case "message_end":
|
|
36275
|
+
if ("role" in event.message && event.message.role === "assistant") this.emitUsage();
|
|
36276
|
+
return;
|
|
35977
36277
|
case "turn_end":
|
|
35978
36278
|
this.emitUsage();
|
|
35979
36279
|
return;
|
|
@@ -35990,20 +36290,29 @@ var init_acp_events = __esm({
|
|
|
35990
36290
|
sessionUpdate: "config_option_update",
|
|
35991
36291
|
configOptions: this.extras().configOptions
|
|
35992
36292
|
});
|
|
36293
|
+
if (event.type === "model_changed") this.emitUsage(true);
|
|
35993
36294
|
return;
|
|
35994
36295
|
default:
|
|
35995
36296
|
return;
|
|
35996
36297
|
}
|
|
35997
36298
|
}
|
|
35998
|
-
|
|
36299
|
+
/**
|
|
36300
|
+
* 发一条 `usage_update`:上下文用量、窗口与会话累计美元。窗口未知时不发(`size` 必填);
|
|
36301
|
+
* 与上次内容相同时不发,`force` 时照发。
|
|
36302
|
+
*/
|
|
36303
|
+
emitUsage(force = false) {
|
|
35999
36304
|
const stats = this.session().getStats();
|
|
36000
36305
|
if (stats.contextWindow === void 0) return;
|
|
36001
|
-
|
|
36306
|
+
const update = {
|
|
36002
36307
|
sessionUpdate: "usage_update",
|
|
36003
36308
|
used: stats.contextTokens ?? 0,
|
|
36004
36309
|
size: stats.contextWindow,
|
|
36005
36310
|
...stats.cost !== void 0 ? { cost: { amount: stats.cost, currency: "USD" } } : {}
|
|
36006
|
-
}
|
|
36311
|
+
};
|
|
36312
|
+
const key = JSON.stringify(update);
|
|
36313
|
+
if (!force && key === this.lastUsage) return;
|
|
36314
|
+
this.lastUsage = key;
|
|
36315
|
+
this.emit(update);
|
|
36007
36316
|
}
|
|
36008
36317
|
/** `session/load`:按消息回放历史(工具结果带前 4 KB 文本;diff 不落盘,回放没有)。 */
|
|
36009
36318
|
replay(messages) {
|
|
@@ -37672,7 +37981,7 @@ var init_bootstrap = __esm({
|
|
|
37672
37981
|
// src/auth/oauth/token-store.ts
|
|
37673
37982
|
function readRaw(path) {
|
|
37674
37983
|
try {
|
|
37675
|
-
const value = JSON.parse((0, import_node_fs43.readFileSync)(path, "utf8"));
|
|
37984
|
+
const value = JSON.parse(retryTransientFs(() => (0, import_node_fs43.readFileSync)(path, "utf8")));
|
|
37676
37985
|
return typeof value === "object" && value !== null && typeof value.providers === "object" ? value : void 0;
|
|
37677
37986
|
} catch {
|
|
37678
37987
|
return void 0;
|
|
@@ -37726,7 +38035,8 @@ function tryAcquire(path) {
|
|
|
37726
38035
|
}
|
|
37727
38036
|
return true;
|
|
37728
38037
|
} catch (error2) {
|
|
37729
|
-
|
|
38038
|
+
const code = error2.code;
|
|
38039
|
+
if (code === "EEXIST" || isTransientFsError(code)) return false;
|
|
37730
38040
|
throw error2;
|
|
37731
38041
|
}
|
|
37732
38042
|
}
|
|
@@ -37765,6 +38075,7 @@ var init_token_store = __esm({
|
|
|
37765
38075
|
import_node_fs43 = require("node:fs");
|
|
37766
38076
|
import_node_path66 = require("node:path");
|
|
37767
38077
|
init_auth_file();
|
|
38078
|
+
init_fs_retry();
|
|
37768
38079
|
init_types2();
|
|
37769
38080
|
init_types_w6();
|
|
37770
38081
|
init_errors();
|
|
@@ -41754,7 +42065,7 @@ var init_meter = __esm({
|
|
|
41754
42065
|
render(width2) {
|
|
41755
42066
|
const { theme, label: label2, cells = 10 } = this.options;
|
|
41756
42067
|
const ratio = this.value === void 0 ? void 0 : Math.min(1, Math.max(0, this.value));
|
|
41757
|
-
const percent3 = ratio === void 0 ? "—" : `${Math.round(ratio * 100)}%`;
|
|
42068
|
+
const percent3 = ratio === void 0 ? "—" : this.options.percent?.(ratio) ?? `${Math.round(ratio * 100)}%`;
|
|
41758
42069
|
const color = (c, text) => theme ? theme.fg(c, text) : text;
|
|
41759
42070
|
const head = label2 === void 0 || label2 === "" ? "" : `${label2} `;
|
|
41760
42071
|
const filled = ratio === void 0 ? 0 : Math.round(ratio * cells);
|
|
@@ -42186,6 +42497,7 @@ var init_key_docs = __esm({
|
|
|
42186
42497
|
animation: true,
|
|
42187
42498
|
restoreOnCancel: true,
|
|
42188
42499
|
enterWhileRunning: "queue",
|
|
42500
|
+
programStatus: "auto",
|
|
42189
42501
|
language: "auto"
|
|
42190
42502
|
},
|
|
42191
42503
|
// [W6-C0] 第六波键的缺省(行为由各批次实现)
|
|
@@ -42591,6 +42903,7 @@ function buildBaseSchema() {
|
|
|
42591
42903
|
animation: bool(),
|
|
42592
42904
|
restoreOnCancel: bool(),
|
|
42593
42905
|
enterWhileRunning: oneOf(["queue", "interrupt"]),
|
|
42906
|
+
programStatus: oneOf(["auto", "on", "off"]),
|
|
42594
42907
|
statusLine: oneOf(STATUS_LINE_MODES),
|
|
42595
42908
|
language: oneOf(LANGUAGE_SETTINGS),
|
|
42596
42909
|
replyLanguage: str3(),
|
|
@@ -45284,12 +45597,12 @@ function handleChunk2(chunk, state, tracker) {
|
|
|
45284
45597
|
}
|
|
45285
45598
|
const usage = obj6(chunk["usageMetadata"]);
|
|
45286
45599
|
if (usage) output.usage = parseGoogleUsage(usage);
|
|
45287
|
-
const
|
|
45600
|
+
const blocked2 = str7(obj6(chunk["promptFeedback"])?.["blockReason"]);
|
|
45288
45601
|
const candidates2 = Array.isArray(chunk["candidates"]) ? chunk["candidates"] : [];
|
|
45289
45602
|
const candidate = obj6(candidates2[0]);
|
|
45290
|
-
if (!candidate &&
|
|
45291
|
-
output.rawStopReason =
|
|
45292
|
-
throw new ProviderStopError(`Prompt blocked: ${
|
|
45603
|
+
if (!candidate && blocked2) {
|
|
45604
|
+
output.rawStopReason = blocked2;
|
|
45605
|
+
throw new ProviderStopError(`Prompt blocked: ${blocked2}`);
|
|
45293
45606
|
}
|
|
45294
45607
|
const parts = obj6(candidate?.["content"])?.["parts"];
|
|
45295
45608
|
if (Array.isArray(parts)) {
|
|
@@ -46244,6 +46557,7 @@ var init_settings_registry = __esm({
|
|
|
46244
46557
|
row2("ui.statusLine", "ui", "now", "any"),
|
|
46245
46558
|
row2("ui.restoreOnCancel", "ui", "nextSession", "any"),
|
|
46246
46559
|
row2("ui.enterWhileRunning", "ui", "now", "any"),
|
|
46560
|
+
row2("ui.programStatus", "ui", "restart", "any"),
|
|
46247
46561
|
row2("ui.quietStartup", "ui", "restart", "any"),
|
|
46248
46562
|
row2("ui.ascii", "ui", "restart", "any", { envOverride: "AMA_ASCII" }),
|
|
46249
46563
|
row2("ui.language", "ui", "restart", "any", { envOverride: "AMA_LANG" }),
|
|
@@ -47552,6 +47866,17 @@ function formatTokenCount(count2) {
|
|
|
47552
47866
|
if (count2 < 1e6) return `${Math.round(count2 / 1e3)}k`;
|
|
47553
47867
|
return `${trim((count2 / 1e6).toFixed(2))}M`;
|
|
47554
47868
|
}
|
|
47869
|
+
function contextEstimated(stats) {
|
|
47870
|
+
const source = stats.context?.source;
|
|
47871
|
+
return source !== void 0 && source !== "usage";
|
|
47872
|
+
}
|
|
47873
|
+
function autoCompactText(stats) {
|
|
47874
|
+
const m = msg().report.session;
|
|
47875
|
+
if (stats.context === void 0 || stats.contextWindow === void 0) return void 0;
|
|
47876
|
+
const at = stats.context.autoCompactAt;
|
|
47877
|
+
if (at === void 0) return m.autoCompactOff;
|
|
47878
|
+
return m.toAutoCompact(formatTokenCount(Math.max(0, at - (stats.contextTokens ?? 0))));
|
|
47879
|
+
}
|
|
47555
47880
|
function formatUsd2(cost2) {
|
|
47556
47881
|
if (cost2 === void 0) return "$?";
|
|
47557
47882
|
return cost2 >= 0.01 || cost2 === 0 ? `$${cost2.toFixed(2)}` : `$${cost2.toFixed(3)}`;
|
|
@@ -47788,11 +48113,14 @@ function describeSession(session, now = Date.now()) {
|
|
|
47788
48113
|
},
|
|
47789
48114
|
{
|
|
47790
48115
|
key: m.keyContext,
|
|
47791
|
-
value:
|
|
47792
|
-
|
|
47793
|
-
|
|
47794
|
-
|
|
47795
|
-
|
|
48116
|
+
value: [
|
|
48117
|
+
m.context(
|
|
48118
|
+
`${contextEstimated(stats) ? "≈" : ""}${stats.contextTokens ?? "?"}`,
|
|
48119
|
+
String(stats.contextWindow ?? "?"),
|
|
48120
|
+
percent3
|
|
48121
|
+
),
|
|
48122
|
+
autoCompactText(stats)
|
|
48123
|
+
].filter((part) => part !== void 0).join(" · ")
|
|
47796
48124
|
}
|
|
47797
48125
|
];
|
|
47798
48126
|
const tasks = taskStatsText(session);
|
|
@@ -47961,6 +48289,111 @@ var init_status_quota = __esm({
|
|
|
47961
48289
|
}
|
|
47962
48290
|
});
|
|
47963
48291
|
|
|
48292
|
+
// src/modes/interactive/status-ctx.ts
|
|
48293
|
+
function ctxPercentText(percent3, decimal) {
|
|
48294
|
+
return decimal || percent3 > 0 && percent3 < 1 ? `${percent3.toFixed(1)}%` : `${Math.round(percent3)}%`;
|
|
48295
|
+
}
|
|
48296
|
+
function ctxWarnAt(stats) {
|
|
48297
|
+
const at = stats.context?.pruneAt;
|
|
48298
|
+
const window2 = stats.contextWindow;
|
|
48299
|
+
return at === void 0 || window2 === void 0 || window2 <= 0 ? 0.7 : Math.min(0.9, at / window2);
|
|
48300
|
+
}
|
|
48301
|
+
function ctxApprox(stats, ascii = false) {
|
|
48302
|
+
return contextEstimated(stats) ? ascii ? "~" : "≈" : "";
|
|
48303
|
+
}
|
|
48304
|
+
function compactCtxText(ctx, width2, theme) {
|
|
48305
|
+
const { percent: percent3 } = ctx;
|
|
48306
|
+
if (percent3 === void 0) return theme.fg("dim", "ctx ?");
|
|
48307
|
+
if (width2 >= METER_WIDTH) {
|
|
48308
|
+
const meter = new Meter(percent3 / 100, {
|
|
48309
|
+
label: theme.fg("dim", "ctx"),
|
|
48310
|
+
theme,
|
|
48311
|
+
warnAt: ctx.warnAt,
|
|
48312
|
+
percent: (ratio) => ctx.approx + ctxPercentText(ratio * 100, false)
|
|
48313
|
+
});
|
|
48314
|
+
return meter.render(80)[0] ?? "";
|
|
48315
|
+
}
|
|
48316
|
+
const color = levelColor(percent3 / 100, { warnAt: ctx.warnAt });
|
|
48317
|
+
return theme.fg("dim", "ctx ") + theme.fg(color, ctx.approx + ctxPercentText(percent3, false));
|
|
48318
|
+
}
|
|
48319
|
+
function fullCtxParts(ctx, theme, p) {
|
|
48320
|
+
const dim = (text) => theme.fg("dim", text);
|
|
48321
|
+
const out = [];
|
|
48322
|
+
const add3 = (text, priority, reserve) => void out.push({
|
|
48323
|
+
text,
|
|
48324
|
+
priority,
|
|
48325
|
+
zone: "right",
|
|
48326
|
+
group: "ctx",
|
|
48327
|
+
...reserve === void 0 ? {} : { reserve }
|
|
48328
|
+
});
|
|
48329
|
+
const { percent: percent3 } = ctx;
|
|
48330
|
+
if (percent3 === void 0) add3(dim("Ctx ?"), p.ctx, 10);
|
|
48331
|
+
else {
|
|
48332
|
+
const color = levelColor(percent3 / 100, { warnAt: ctx.warnAt });
|
|
48333
|
+
add3(dim("Ctx ") + theme.fg(color, ctx.approx + ctxPercentText(percent3, true)), p.ctx, 10);
|
|
48334
|
+
}
|
|
48335
|
+
if (ctx.tokens !== void 0) add3(dim(` ${formatTokens3(ctx.tokens)}`), p.ctxUsed, 5);
|
|
48336
|
+
if (ctx.tokens !== void 0 && ctx.window !== void 0)
|
|
48337
|
+
add3(dim(`/${formatTokens3(ctx.window)}`), p.ctxWindow, 5);
|
|
48338
|
+
if (ctx.auto) add3(dim(` ${msg().interactive.statusLine.autoCompact}`), p.ctxAuto);
|
|
48339
|
+
return out;
|
|
48340
|
+
}
|
|
48341
|
+
var LIVE_CTX_INTERVAL_MS, METER_WIDTH, LiveContext;
|
|
48342
|
+
var init_status_ctx = __esm({
|
|
48343
|
+
"src/modes/interactive/status-ctx.ts"() {
|
|
48344
|
+
"use strict";
|
|
48345
|
+
init_estimate();
|
|
48346
|
+
init_i18n();
|
|
48347
|
+
init_tui2();
|
|
48348
|
+
init_session_report();
|
|
48349
|
+
init_status_bar();
|
|
48350
|
+
LIVE_CTX_INTERVAL_MS = 500;
|
|
48351
|
+
METER_WIDTH = 110;
|
|
48352
|
+
LiveContext = class {
|
|
48353
|
+
constructor(now) {
|
|
48354
|
+
this.now = now;
|
|
48355
|
+
}
|
|
48356
|
+
now;
|
|
48357
|
+
tokens;
|
|
48358
|
+
at = Number.NEGATIVE_INFINITY;
|
|
48359
|
+
/** 记下 usage 给出的上下文量;距上次采样 < 500 ms 时不更新。返回是否更新了。 */
|
|
48360
|
+
note(usage) {
|
|
48361
|
+
if (usage === void 0) return false;
|
|
48362
|
+
const tokens = calculateContextTokens(usage);
|
|
48363
|
+
if (tokens <= 0) return false;
|
|
48364
|
+
const now = this.now();
|
|
48365
|
+
if (this.tokens !== void 0 && now - this.at < LIVE_CTX_INTERVAL_MS) return false;
|
|
48366
|
+
this.tokens = tokens;
|
|
48367
|
+
this.at = now;
|
|
48368
|
+
return true;
|
|
48369
|
+
}
|
|
48370
|
+
clear() {
|
|
48371
|
+
this.tokens = void 0;
|
|
48372
|
+
this.at = Number.NEGATIVE_INFINITY;
|
|
48373
|
+
}
|
|
48374
|
+
/** 统计值 → 显示值(有在途值时以它为准,不再是估算)。 */
|
|
48375
|
+
view(stats, ascii) {
|
|
48376
|
+
const view = {
|
|
48377
|
+
tokens: stats.contextTokens,
|
|
48378
|
+
window: stats.contextWindow,
|
|
48379
|
+
percent: stats.contextPercent,
|
|
48380
|
+
approx: ctxApprox(stats, ascii),
|
|
48381
|
+
warnAt: ctxWarnAt(stats),
|
|
48382
|
+
auto: stats.context?.autoCompactAt !== void 0
|
|
48383
|
+
};
|
|
48384
|
+
const window2 = stats.contextWindow;
|
|
48385
|
+
if (this.tokens !== void 0) {
|
|
48386
|
+
view.tokens = this.tokens;
|
|
48387
|
+
view.approx = "";
|
|
48388
|
+
if (window2 !== void 0 && window2 > 0)
|
|
48389
|
+
view.percent = Math.min(100, Math.round(this.tokens / window2 * 1e3) / 10);
|
|
48390
|
+
}
|
|
48391
|
+
return view;
|
|
48392
|
+
}
|
|
48393
|
+
};
|
|
48394
|
+
}
|
|
48395
|
+
});
|
|
48396
|
+
|
|
47964
48397
|
// src/modes/interactive/status-bar.ts
|
|
47965
48398
|
function formatTokens3(count2) {
|
|
47966
48399
|
if (count2 < 1e3) return String(count2);
|
|
@@ -47984,6 +48417,16 @@ function cacheText(cache3, warm = "♨") {
|
|
|
47984
48417
|
const value = cache3.reporting === "silent" ? msg().interactive.statusLine.cacheSilent : cache3.reporting === "reported" && rate !== void 0 ? `${Math.round(rate * 100)}%` : "—";
|
|
47985
48418
|
return `cache ${value}${cache3.warming.state === "scheduled" ? ` ${warm}` : ""}`;
|
|
47986
48419
|
}
|
|
48420
|
+
function tokensText(t, g) {
|
|
48421
|
+
const prompt = t.input + t.cacheRead + t.cacheWrite;
|
|
48422
|
+
const parts = [
|
|
48423
|
+
`${g.ascii ? "sum " : "Σ"}${g.arrowUp}${formatTokens3(prompt)}`,
|
|
48424
|
+
`${g.arrowDown}${formatTokens3(t.output)}`
|
|
48425
|
+
];
|
|
48426
|
+
if (t.cacheRead > 0) parts.push(`R${formatTokens3(t.cacheRead)}`);
|
|
48427
|
+
if (t.cacheWrite > 0) parts.push(`W${formatTokens3(t.cacheWrite)}`);
|
|
48428
|
+
return parts.join(" ");
|
|
48429
|
+
}
|
|
47987
48430
|
function statusCost(stats) {
|
|
47988
48431
|
if (stats.cost === void 0) return void 0;
|
|
47989
48432
|
let external = 0;
|
|
@@ -48048,7 +48491,7 @@ function abbreviateModel(ref, width2) {
|
|
|
48048
48491
|
if (width2 < 48) out = out.replace(/-\d.*$/, "");
|
|
48049
48492
|
return out;
|
|
48050
48493
|
}
|
|
48051
|
-
function usageItems(stats, queue, source, theme) {
|
|
48494
|
+
function usageItems(stats, queue, source, theme, cumulative = false) {
|
|
48052
48495
|
const g = theme.glyphs;
|
|
48053
48496
|
const dim = (text) => theme.fg("dim", text);
|
|
48054
48497
|
const out = {};
|
|
@@ -48056,7 +48499,9 @@ function usageItems(stats, queue, source, theme) {
|
|
|
48056
48499
|
const prompt = t.input + t.cacheRead + t.cacheWrite;
|
|
48057
48500
|
const cache3 = stats.cache;
|
|
48058
48501
|
if (prompt + t.output > 0) {
|
|
48059
|
-
out.tokens = dim(
|
|
48502
|
+
out.tokens = dim(
|
|
48503
|
+
cumulative ? tokensText(t, g) : `${g.arrowUp}${formatTokens3(prompt)} ${g.arrowDown}${formatTokens3(t.output)}`
|
|
48504
|
+
);
|
|
48060
48505
|
if (cache3 !== void 0) out.cache = dim(cacheText(cache3, g.warm));
|
|
48061
48506
|
else if (stats.cacheHitRate !== void 0) {
|
|
48062
48507
|
out.cache = dim(`cache ${Math.round(stats.cacheHitRate * 100)}%`);
|
|
@@ -48086,7 +48531,7 @@ function usageItems(stats, queue, source, theme) {
|
|
|
48086
48531
|
}
|
|
48087
48532
|
return out;
|
|
48088
48533
|
}
|
|
48089
|
-
var MIN_GAP,
|
|
48534
|
+
var MIN_GAP, COMPACT, FULL, FULL_HINT, FULL_STYLE, StatusBar;
|
|
48090
48535
|
var init_status_bar = __esm({
|
|
48091
48536
|
"src/modes/interactive/status-bar.ts"() {
|
|
48092
48537
|
"use strict";
|
|
@@ -48094,9 +48539,9 @@ var init_status_bar = __esm({
|
|
|
48094
48539
|
init_modes();
|
|
48095
48540
|
init_channels();
|
|
48096
48541
|
init_status_quota();
|
|
48542
|
+
init_status_ctx();
|
|
48097
48543
|
init_tui2();
|
|
48098
48544
|
MIN_GAP = 4;
|
|
48099
|
-
METER_WIDTH = 110;
|
|
48100
48545
|
COMPACT = {
|
|
48101
48546
|
model: 0,
|
|
48102
48547
|
ctx: 1,
|
|
@@ -48116,9 +48561,21 @@ var init_status_bar = __esm({
|
|
|
48116
48561
|
hint: 16,
|
|
48117
48562
|
quota: 17
|
|
48118
48563
|
};
|
|
48119
|
-
FULL = {
|
|
48564
|
+
FULL = {
|
|
48565
|
+
model: 0,
|
|
48566
|
+
ctx: 1,
|
|
48567
|
+
cost: 2,
|
|
48568
|
+
duration: 3,
|
|
48569
|
+
ctxUsed: 4,
|
|
48570
|
+
branch: 5,
|
|
48571
|
+
dir: 6,
|
|
48572
|
+
diff: 7,
|
|
48573
|
+
ctxWindow: 8,
|
|
48574
|
+
thinking: 9,
|
|
48575
|
+
ctxAuto: 13
|
|
48576
|
+
};
|
|
48120
48577
|
FULL_HINT = 12;
|
|
48121
|
-
FULL_STYLE = { sep: " | " };
|
|
48578
|
+
FULL_STYLE = { sep: " | ", groups: { ctx: { glue: "" } } };
|
|
48122
48579
|
StatusBar = class {
|
|
48123
48580
|
constructor(source, theme) {
|
|
48124
48581
|
this.source = source;
|
|
@@ -48128,10 +48585,23 @@ var init_status_bar = __esm({
|
|
|
48128
48585
|
theme;
|
|
48129
48586
|
stats;
|
|
48130
48587
|
queue = 0;
|
|
48588
|
+
/** 在途请求的上下文量(message_update 的 usage,≤ 2 Hz 采样);该消息结束后清掉。 */
|
|
48589
|
+
live = new LiveContext(() => this.source.now?.() ?? Date.now());
|
|
48131
48590
|
/** 用量、模型等变化后调用(事件驱动;流式期间不必每帧算)。 */
|
|
48132
48591
|
refresh() {
|
|
48133
48592
|
this.stats = this.source.session().getStats();
|
|
48134
48593
|
}
|
|
48594
|
+
/**
|
|
48595
|
+
* 流式中的助手消息带了 usage(有的协议在开头就给输入量):记下在途请求的上下文量,距上次采样
|
|
48596
|
+
* ≥ 500 ms 才更新(≤ 2 Hz)。返回是否更新了。
|
|
48597
|
+
*/
|
|
48598
|
+
noteStreaming(usage) {
|
|
48599
|
+
return this.live.note(usage);
|
|
48600
|
+
}
|
|
48601
|
+
/** 助手消息结束:丢掉在途值,回到统计值。 */
|
|
48602
|
+
clearStreaming() {
|
|
48603
|
+
this.live.clear();
|
|
48604
|
+
}
|
|
48135
48605
|
setQueue(steering, followUp) {
|
|
48136
48606
|
this.queue = steering + followUp;
|
|
48137
48607
|
}
|
|
@@ -48182,7 +48652,9 @@ var init_status_bar = __esm({
|
|
|
48182
48652
|
if (usage.cache !== void 0) right(usage.cache, COMPACT.cache);
|
|
48183
48653
|
if (usage.cost !== void 0) right(usage.cost, COMPACT.cost);
|
|
48184
48654
|
if (usage.rebill !== void 0) right(usage.rebill, COMPACT.rebill);
|
|
48185
|
-
|
|
48655
|
+
const ctx = this.live.view(stats, g.ascii);
|
|
48656
|
+
if (full) fullCtxParts(ctx, theme, FULL).forEach((part) => parts.push(part));
|
|
48657
|
+
else right(compactCtxText(ctx, width2, theme), p.ctx);
|
|
48186
48658
|
this.gitParts(p, full).forEach((part) => parts.push(part));
|
|
48187
48659
|
if (full) {
|
|
48188
48660
|
const cost2 = statusCost(stats);
|
|
@@ -48243,17 +48715,6 @@ var init_status_bar = __esm({
|
|
|
48243
48715
|
}
|
|
48244
48716
|
return out;
|
|
48245
48717
|
}
|
|
48246
|
-
ctxText(percent3, width2, decimal) {
|
|
48247
|
-
const theme = this.theme;
|
|
48248
|
-
if (percent3 === void 0) return theme.fg("dim", decimal ? "Ctx ?" : "ctx ?");
|
|
48249
|
-
const color = levelColor(percent3 / 100);
|
|
48250
|
-
if (!decimal && width2 >= METER_WIDTH) {
|
|
48251
|
-
const meter = new Meter(percent3 / 100, { label: theme.fg("dim", "ctx"), theme });
|
|
48252
|
-
return meter.render(80)[0] ?? "";
|
|
48253
|
-
}
|
|
48254
|
-
if (decimal) return theme.fg("dim", "Ctx ") + theme.fg(color, `${percent3.toFixed(1)}%`);
|
|
48255
|
-
return theme.fg("dim", "ctx ") + theme.fg(color, `${Math.round(percent3)}%`);
|
|
48256
|
-
}
|
|
48257
48718
|
render(width2) {
|
|
48258
48719
|
const style = this.layout() === "full" ? FULL_STYLE : {};
|
|
48259
48720
|
return [layoutRow(this.parts(width2), width2, this.theme, style)];
|
|
@@ -48611,7 +49072,7 @@ function usageOf(node) {
|
|
|
48611
49072
|
return void 0;
|
|
48612
49073
|
}
|
|
48613
49074
|
}
|
|
48614
|
-
function
|
|
49075
|
+
function tokensText2(node, theme) {
|
|
48615
49076
|
const { arrowUp, arrowDown } = theme.glyphs;
|
|
48616
49077
|
if (node.kind === "turn") {
|
|
48617
49078
|
const u = node.usage;
|
|
@@ -48755,7 +49216,7 @@ function formatRow(row3, width2, ctx, selected = false) {
|
|
|
48755
49216
|
if (width2 < NARROW_WIDTH) right = ` ${duration}`;
|
|
48756
49217
|
else {
|
|
48757
49218
|
const bar = barText(row3, barWidth(width2), theme);
|
|
48758
|
-
const tokens = padToWidth(
|
|
49219
|
+
const tokens = padToWidth(tokensText2(row3.node, theme), TOKENS_WIDTH);
|
|
48759
49220
|
const cache3 = cacheText2(row3.node).padStart(CACHE_WIDTH);
|
|
48760
49221
|
right = ` ${duration} ${bar} ${tokens} ${cache3}`;
|
|
48761
49222
|
}
|
|
@@ -48806,7 +49267,7 @@ function formatTraceText(trace, ctx, rows = expandAll((expanded) => flattenTrace
|
|
|
48806
49267
|
for (const row3 of rows) {
|
|
48807
49268
|
const indent2 = " ".repeat(row3.depth);
|
|
48808
49269
|
const mark = statusMark(row3.node, theme);
|
|
48809
|
-
const cols = [durationText(row3.node, theme),
|
|
49270
|
+
const cols = [durationText(row3.node, theme), tokensText2(row3.node, theme), cacheText2(row3.node)].filter((c) => c !== "").join(" ");
|
|
48810
49271
|
const label2 = `${indent2}${mark === "" ? "" : `${mark} `}${rowLabel(row3, ctx)}`;
|
|
48811
49272
|
lines2.push(cols === "" ? label2 : `${label2} ${cols}`);
|
|
48812
49273
|
}
|
|
@@ -50884,6 +51345,7 @@ async function runPrintMode(runtime, context) {
|
|
|
50884
51345
|
usage: stats.tokens,
|
|
50885
51346
|
cost: stats.cost,
|
|
50886
51347
|
cacheHitRate: stats.cacheHitRate,
|
|
51348
|
+
...contextOf(stats),
|
|
50887
51349
|
...stats.cache !== void 0 ? { cache: stats.cache } : {},
|
|
50888
51350
|
...stats.tasks !== void 0 ? { tasks: stats.tasks } : {},
|
|
50889
51351
|
...denied.length > 0 ? { deniedTools: denied } : {},
|
|
@@ -50966,6 +51428,13 @@ function describeDenied(denied) {
|
|
|
50966
51428
|
const tools = [...counts].map(([name, n]) => `${name} ×${n}`);
|
|
50967
51429
|
return msg().print.print.denied(denied.length, tools, denied[0]?.reason ?? "");
|
|
50968
51430
|
}
|
|
51431
|
+
function contextOf(stats) {
|
|
51432
|
+
const context = {};
|
|
51433
|
+
if (stats.contextTokens !== void 0) context["tokens"] = stats.contextTokens;
|
|
51434
|
+
if (stats.contextWindow !== void 0) context["window"] = stats.contextWindow;
|
|
51435
|
+
if (stats.contextPercent !== void 0) context["percent"] = stats.contextPercent;
|
|
51436
|
+
return Object.keys(context).length > 0 ? { context } : {};
|
|
51437
|
+
}
|
|
50969
51438
|
var STDIN_WAIT_HINT_MS, STDIN_FIRST_BYTE_MS;
|
|
50970
51439
|
var init_print_mode = __esm({
|
|
50971
51440
|
"src/modes/print/print-mode.ts"() {
|
|
@@ -51593,6 +52062,8 @@ function taskFacts(task, now) {
|
|
|
51593
52062
|
facts.push(
|
|
51594
52063
|
`↑${formatTokenCount(usage.input + usage.cacheRead + usage.cacheWrite)} ↓${formatTokenCount(usage.output)}`
|
|
51595
52064
|
);
|
|
52065
|
+
const context = formatTaskContext(task);
|
|
52066
|
+
if (context !== void 0) facts.push(msg().panels.tasks.context(context));
|
|
51596
52067
|
if (task.costUsd !== void 0 && task.costUsd > 0) facts.push(formatUsd2(task.costUsd));
|
|
51597
52068
|
return facts;
|
|
51598
52069
|
}
|
|
@@ -51659,6 +52130,7 @@ var init_tasks_report = __esm({
|
|
|
51659
52130
|
"src/modes/interactive/tasks-report.ts"() {
|
|
51660
52131
|
"use strict";
|
|
51661
52132
|
init_external();
|
|
52133
|
+
init_task_record();
|
|
51662
52134
|
init_subagent_registry();
|
|
51663
52135
|
init_i18n();
|
|
51664
52136
|
init_session_report();
|
|
@@ -51719,6 +52191,514 @@ var init_task_background = __esm({
|
|
|
51719
52191
|
}
|
|
51720
52192
|
});
|
|
51721
52193
|
|
|
52194
|
+
// src/compaction/breakdown.ts
|
|
52195
|
+
function textPiece(category, name, text) {
|
|
52196
|
+
const count2 = countText(text, { wide: 0, narrow: 0 });
|
|
52197
|
+
return { category, name, wide: count2.wide, narrow: count2.narrow, fixed: 0 };
|
|
52198
|
+
}
|
|
52199
|
+
function imagePiece(name) {
|
|
52200
|
+
return { category: "images", name, wide: 0, narrow: 0, fixed: IMAGE_TOKENS };
|
|
52201
|
+
}
|
|
52202
|
+
function contentPieces(content, category, name, imageSource) {
|
|
52203
|
+
if (typeof content === "string") return [textPiece(category, name, content)];
|
|
52204
|
+
return content.map(
|
|
52205
|
+
(block) => block.type === "text" ? textPiece(category, name, block.text) : imagePiece(imageSource)
|
|
52206
|
+
);
|
|
52207
|
+
}
|
|
52208
|
+
function messagePieces(message) {
|
|
52209
|
+
switch (message.role) {
|
|
52210
|
+
case "system": {
|
|
52211
|
+
const pieces2 = Object.entries(message.sections).map(
|
|
52212
|
+
([name, text]) => textPiece("system", name, text ?? "")
|
|
52213
|
+
);
|
|
52214
|
+
const tools = message.toolsAdded;
|
|
52215
|
+
if (tools !== void 0) {
|
|
52216
|
+
for (const tool of tools) pieces2.push(textPiece("tools", tool.name, JSON.stringify(tool)));
|
|
52217
|
+
pieces2.push({
|
|
52218
|
+
category: "tools",
|
|
52219
|
+
name: void 0,
|
|
52220
|
+
wide: 0,
|
|
52221
|
+
narrow: 2 + Math.max(0, tools.length - 1),
|
|
52222
|
+
fixed: 0
|
|
52223
|
+
});
|
|
52224
|
+
}
|
|
52225
|
+
return pieces2;
|
|
52226
|
+
}
|
|
52227
|
+
case "user":
|
|
52228
|
+
return contentPieces(message.content, "user", void 0, "user");
|
|
52229
|
+
case "toolResult":
|
|
52230
|
+
return contentPieces(message.content, "toolResults", message.toolName, "toolResult");
|
|
52231
|
+
case "custom":
|
|
52232
|
+
return contentPieces(message.content, "custom", message.customType, "custom");
|
|
52233
|
+
case "assistant":
|
|
52234
|
+
return message.content.map(
|
|
52235
|
+
(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))
|
|
52236
|
+
);
|
|
52237
|
+
case "compactionSummary":
|
|
52238
|
+
return [textPiece("summaries", "compaction", message.summary)];
|
|
52239
|
+
case "branchSummary":
|
|
52240
|
+
return [textPiece("summaries", "branch", message.summary)];
|
|
52241
|
+
}
|
|
52242
|
+
}
|
|
52243
|
+
function allocate(pieces2, total) {
|
|
52244
|
+
const tokens = pieces2.map((p) => p.fixed + p.wide + Math.floor(p.narrow / CHARS_PER_TOKEN2));
|
|
52245
|
+
let left = total - tokens.reduce((sum, n) => sum + n, 0);
|
|
52246
|
+
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);
|
|
52247
|
+
for (const { i } of order) {
|
|
52248
|
+
if (left <= 0) break;
|
|
52249
|
+
tokens[i] = (tokens[i] ?? 0) + 1;
|
|
52250
|
+
left--;
|
|
52251
|
+
}
|
|
52252
|
+
if (left !== 0 && tokens.length > 0) {
|
|
52253
|
+
let max = 0;
|
|
52254
|
+
for (let i = 1; i < tokens.length; i++) if ((tokens[i] ?? 0) > (tokens[max] ?? 0)) max = i;
|
|
52255
|
+
tokens[max] = (tokens[max] ?? 0) + left;
|
|
52256
|
+
}
|
|
52257
|
+
return tokens;
|
|
52258
|
+
}
|
|
52259
|
+
function breakdownMessages(messages) {
|
|
52260
|
+
const totals2 = /* @__PURE__ */ new Map();
|
|
52261
|
+
const parts = /* @__PURE__ */ new Map();
|
|
52262
|
+
for (const category of BREAKDOWN_CATEGORIES) {
|
|
52263
|
+
totals2.set(category, { tokens: 0, count: 0 });
|
|
52264
|
+
parts.set(category, /* @__PURE__ */ new Map());
|
|
52265
|
+
}
|
|
52266
|
+
const toolResults = [];
|
|
52267
|
+
let total = 0;
|
|
52268
|
+
let hasSystem = false;
|
|
52269
|
+
for (const message of messages) {
|
|
52270
|
+
const messageTokens = estimateMessageTokens(message);
|
|
52271
|
+
total += messageTokens;
|
|
52272
|
+
if (message.role === "system") hasSystem = true;
|
|
52273
|
+
if (message.role === "toolResult") {
|
|
52274
|
+
toolResults.push({
|
|
52275
|
+
ordinal: toolResults.length + 1,
|
|
52276
|
+
toolName: message.toolName,
|
|
52277
|
+
tokens: messageTokens
|
|
52278
|
+
});
|
|
52279
|
+
}
|
|
52280
|
+
const pieces2 = messagePieces(message);
|
|
52281
|
+
const allocated = allocate(pieces2, messageTokens);
|
|
52282
|
+
pieces2.forEach((piece, i) => {
|
|
52283
|
+
const tokens = allocated[i] ?? 0;
|
|
52284
|
+
const entry = totals2.get(piece.category);
|
|
52285
|
+
if (entry === void 0) return;
|
|
52286
|
+
entry.tokens += tokens;
|
|
52287
|
+
if (piece.name !== void 0 || piece.category !== "tools") entry.count++;
|
|
52288
|
+
if (piece.name !== void 0) {
|
|
52289
|
+
const named = parts.get(piece.category);
|
|
52290
|
+
named?.set(piece.name, (named.get(piece.name) ?? 0) + tokens);
|
|
52291
|
+
}
|
|
52292
|
+
});
|
|
52293
|
+
}
|
|
52294
|
+
const entries = BREAKDOWN_CATEGORIES.map((category) => {
|
|
52295
|
+
const entry = totals2.get(category) ?? { tokens: 0, count: 0 };
|
|
52296
|
+
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));
|
|
52297
|
+
return { category, tokens: entry.tokens, count: entry.count, parts: named };
|
|
52298
|
+
});
|
|
52299
|
+
const prefixTokens = entries.filter((e) => e.category === "system" || e.category === "tools").reduce((sum, e) => sum + e.tokens, 0);
|
|
52300
|
+
return { entries, total, prefixTokens, hasSystem, toolResults };
|
|
52301
|
+
}
|
|
52302
|
+
function largestToolResults(breakdown, n) {
|
|
52303
|
+
return [...breakdown.toolResults].sort((a, b) => b.tokens - a.tokens || a.ordinal - b.ordinal).slice(0, Math.max(0, n));
|
|
52304
|
+
}
|
|
52305
|
+
var CHARS_PER_TOKEN2, BREAKDOWN_CATEGORIES;
|
|
52306
|
+
var init_breakdown = __esm({
|
|
52307
|
+
"src/compaction/breakdown.ts"() {
|
|
52308
|
+
"use strict";
|
|
52309
|
+
init_estimate();
|
|
52310
|
+
CHARS_PER_TOKEN2 = 4;
|
|
52311
|
+
BREAKDOWN_CATEGORIES = [
|
|
52312
|
+
"system",
|
|
52313
|
+
"tools",
|
|
52314
|
+
"user",
|
|
52315
|
+
"assistant",
|
|
52316
|
+
"reasoning",
|
|
52317
|
+
"toolCalls",
|
|
52318
|
+
"toolResults",
|
|
52319
|
+
"images",
|
|
52320
|
+
"summaries",
|
|
52321
|
+
"custom"
|
|
52322
|
+
];
|
|
52323
|
+
}
|
|
52324
|
+
});
|
|
52325
|
+
|
|
52326
|
+
// src/cli/startup-screen.ts
|
|
52327
|
+
function startupScreenLevel(runtime) {
|
|
52328
|
+
return runtime.config.ui?.quietStartup ?? "normal";
|
|
52329
|
+
}
|
|
52330
|
+
function trustSourceLabel(source) {
|
|
52331
|
+
const labels2 = msg().cli.startupScreen.trustSource;
|
|
52332
|
+
return source === "trust-file" ? labels2.trustFile : labels2[source];
|
|
52333
|
+
}
|
|
52334
|
+
function tildePath(path, home) {
|
|
52335
|
+
if (home === void 0 || home === "") return path;
|
|
52336
|
+
const trimmed = /[\\/]$/.test(home) ? home.slice(0, -1) : home;
|
|
52337
|
+
if (path === trimmed) return "~";
|
|
52338
|
+
const next = path[trimmed.length];
|
|
52339
|
+
return path.startsWith(trimmed) && (next === "/" || next === "\\") ? `~${path.slice(trimmed.length)}` : path;
|
|
52340
|
+
}
|
|
52341
|
+
function startupInfo(runtime, home) {
|
|
52342
|
+
const { resources } = runtime;
|
|
52343
|
+
const info2 = {
|
|
52344
|
+
version: AMA_VERSION,
|
|
52345
|
+
model: formatModelRef(runtime.model),
|
|
52346
|
+
thinking: runtime.thinkingLevel,
|
|
52347
|
+
cwd: tildePath(runtime.paths.cwd, home),
|
|
52348
|
+
trusted: runtime.trust.trusted,
|
|
52349
|
+
trustSource: trustSourceLabel(runtime.trust.source),
|
|
52350
|
+
permissionMode: runtime.session.state.permissionMode,
|
|
52351
|
+
preset: runtime.config.tools?.preset ?? "default",
|
|
52352
|
+
codemode: effectiveCodemodeMode(runtime.config),
|
|
52353
|
+
contextFiles: resources.contextFiles.map((f) => (0, import_node_path93.basename)(f.path)),
|
|
52354
|
+
skills: resources.skills.filter((s2) => !isBuiltinSkill(s2)).length,
|
|
52355
|
+
prompts: resources.prompts.length,
|
|
52356
|
+
hooks: runtime.hooks.list().length,
|
|
52357
|
+
warnings: runtime.warnings.length
|
|
52358
|
+
};
|
|
52359
|
+
if (runtime.host !== void 0) info2.host = runtime.host.adapter.id;
|
|
52360
|
+
return info2;
|
|
52361
|
+
}
|
|
52362
|
+
var import_node_path93;
|
|
52363
|
+
var init_startup_screen = __esm({
|
|
52364
|
+
"src/cli/startup-screen.ts"() {
|
|
52365
|
+
"use strict";
|
|
52366
|
+
init_builtin3();
|
|
52367
|
+
import_node_path93 = require("node:path");
|
|
52368
|
+
init_channels();
|
|
52369
|
+
init_presets2();
|
|
52370
|
+
init_i18n();
|
|
52371
|
+
init_version();
|
|
52372
|
+
}
|
|
52373
|
+
});
|
|
52374
|
+
|
|
52375
|
+
// src/modes/interactive/panels.ts
|
|
52376
|
+
function keyValue(rows, theme, wrap2 = false) {
|
|
52377
|
+
return new KeyValue(rows, { theme, maxKeyRatio: 0.3, ...wrap2 ? { wrap: true } : {} });
|
|
52378
|
+
}
|
|
52379
|
+
function cacheSection(session, theme, now) {
|
|
52380
|
+
return [
|
|
52381
|
+
theme.bold(msg().panels.cache.title),
|
|
52382
|
+
new Indent(keyValue(cacheRows(session, now), theme), 2)
|
|
52383
|
+
];
|
|
52384
|
+
}
|
|
52385
|
+
function sessionPanel(session, theme, options = {}) {
|
|
52386
|
+
const m = msg().panels.session;
|
|
52387
|
+
const now = options.now ?? Date.now();
|
|
52388
|
+
const state = session.state;
|
|
52389
|
+
const stats = session.getStats();
|
|
52390
|
+
const t = stats.tokens;
|
|
52391
|
+
const sep5 = theme.fg("dim", " · ");
|
|
52392
|
+
const model = state.model === void 0 ? "?" : `${state.model.provider}/${state.model.id}`;
|
|
52393
|
+
const ratio = stats.contextPercent === void 0 ? void 0 : stats.contextPercent / 100;
|
|
52394
|
+
const approx = contextEstimated(stats) ? "≈" : "";
|
|
52395
|
+
const meter = new Meter(ratio, {
|
|
52396
|
+
theme,
|
|
52397
|
+
warnAt: ctxWarnAt(stats),
|
|
52398
|
+
percent: (r) => approx + ctxPercentText(r * 100, false)
|
|
52399
|
+
}).render(40)[0] ?? "";
|
|
52400
|
+
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)}`;
|
|
52401
|
+
const auto = autoCompactText(stats);
|
|
52402
|
+
const rows = [
|
|
52403
|
+
{
|
|
52404
|
+
key: m.model,
|
|
52405
|
+
value: theme.fg("accent", model) + sep5 + m.thinking(state.thinkingLevel) + sep5 + m.permission(permissionModeLabel(state.permissionMode))
|
|
52406
|
+
},
|
|
52407
|
+
{
|
|
52408
|
+
key: m.messages,
|
|
52409
|
+
value: [
|
|
52410
|
+
m.user(stats.userMessages),
|
|
52411
|
+
m.assistant(stats.assistantMessages),
|
|
52412
|
+
m.toolCalls(stats.toolCalls)
|
|
52413
|
+
].join(sep5)
|
|
52414
|
+
},
|
|
52415
|
+
{
|
|
52416
|
+
key: m.usage,
|
|
52417
|
+
value: [
|
|
52418
|
+
m.input(formatTokenCount(t.input)),
|
|
52419
|
+
m.output(formatTokenCount(t.output)),
|
|
52420
|
+
m.cacheRead(formatTokenCount(t.cacheRead)),
|
|
52421
|
+
m.cacheWrite(formatTokenCount(t.cacheWrite)),
|
|
52422
|
+
formatUsd2(stats.cost)
|
|
52423
|
+
].join(sep5)
|
|
52424
|
+
},
|
|
52425
|
+
{ key: m.context, value: meter + window2 + (auto === void 0 ? "" : sep5 + auto) }
|
|
52426
|
+
];
|
|
52427
|
+
const tasks = taskStatsText(session);
|
|
52428
|
+
if (tasks !== void 0) rows.push({ key: m.subagents, value: tasks });
|
|
52429
|
+
const external = externalRows(session);
|
|
52430
|
+
const externalSection = external.length > 0 ? ["", theme.bold(m.external), new Indent(keyValue(external, theme), 2)] : [];
|
|
52431
|
+
const file = state.sessionFile === void 0 ? m.notSaved : tildePath(state.sessionFile, options.home);
|
|
52432
|
+
const parts = [
|
|
52433
|
+
keyValue(rows, theme),
|
|
52434
|
+
"",
|
|
52435
|
+
...cacheSection(session, theme, now),
|
|
52436
|
+
...externalSection
|
|
52437
|
+
];
|
|
52438
|
+
return new Card(new Stack(parts), {
|
|
52439
|
+
theme,
|
|
52440
|
+
title: m.title(state.sessionId.slice(0, 8)),
|
|
52441
|
+
subtitle: file
|
|
52442
|
+
});
|
|
52443
|
+
}
|
|
52444
|
+
function cachePanel(session, theme, now = Date.now()) {
|
|
52445
|
+
return new Card(keyValue(cacheRows(session, now), theme), {
|
|
52446
|
+
theme,
|
|
52447
|
+
title: msg().panels.cache.title
|
|
52448
|
+
});
|
|
52449
|
+
}
|
|
52450
|
+
function permissionsPanel(runtime, session, theme) {
|
|
52451
|
+
const m = msg().panels.permissions;
|
|
52452
|
+
const rules = runtime.permission.rules;
|
|
52453
|
+
const mode = session.state.permissionMode;
|
|
52454
|
+
const order = mode === "auto" ? m.orderAuto : mode === "allowlist" ? m.orderAllowlist : m.orderDefault;
|
|
52455
|
+
const effect = (decision) => theme.fg(DECISION_COLOR[decision] ?? "text", decision.padEnd(5));
|
|
52456
|
+
const parts = [
|
|
52457
|
+
keyValue(
|
|
52458
|
+
[
|
|
52459
|
+
{
|
|
52460
|
+
key: m.mode,
|
|
52461
|
+
value: m.modeValue(permissionModeLabel(mode), mode, (t) => theme.fg("dim", t))
|
|
52462
|
+
},
|
|
52463
|
+
{ key: m.order, value: order }
|
|
52464
|
+
],
|
|
52465
|
+
theme,
|
|
52466
|
+
true
|
|
52467
|
+
),
|
|
52468
|
+
theme.bold(rules.length === 0 ? m.rulesNone : m.rules(rules.length))
|
|
52469
|
+
];
|
|
52470
|
+
if (rules.length > 0) {
|
|
52471
|
+
parts.push(
|
|
52472
|
+
new Indent(
|
|
52473
|
+
keyValue(
|
|
52474
|
+
rules.map((r) => ({
|
|
52475
|
+
key: effect(r.effect),
|
|
52476
|
+
value: `${r.raw} ${theme.fg("dim", `[${r.source}]`)}`
|
|
52477
|
+
})),
|
|
52478
|
+
theme
|
|
52479
|
+
),
|
|
52480
|
+
2
|
|
52481
|
+
)
|
|
52482
|
+
);
|
|
52483
|
+
}
|
|
52484
|
+
const recent = runtime.permission.autoDecisions?.() ?? [];
|
|
52485
|
+
if (recent.length > 0) {
|
|
52486
|
+
parts.push(theme.bold(m.recentAuto(recent.length)));
|
|
52487
|
+
parts.push(
|
|
52488
|
+
new Indent(
|
|
52489
|
+
keyValue(
|
|
52490
|
+
recent.map((d) => ({
|
|
52491
|
+
key: autoLayerText(d.layer),
|
|
52492
|
+
value: `${effect(d.decision)} ${d.toolName} ${d.summary} — ${d.reason}` + (d.cached === true ? theme.fg("dim", m.cached) : "")
|
|
52493
|
+
})),
|
|
52494
|
+
theme
|
|
52495
|
+
),
|
|
52496
|
+
2
|
|
52497
|
+
)
|
|
52498
|
+
);
|
|
52499
|
+
}
|
|
52500
|
+
return new Card(new Stack(parts), { theme });
|
|
52501
|
+
}
|
|
52502
|
+
var Stack, Indent, DECISION_COLOR;
|
|
52503
|
+
var init_panels2 = __esm({
|
|
52504
|
+
"src/modes/interactive/panels.ts"() {
|
|
52505
|
+
"use strict";
|
|
52506
|
+
init_i18n();
|
|
52507
|
+
init_modes();
|
|
52508
|
+
init_tui2();
|
|
52509
|
+
init_status_ctx();
|
|
52510
|
+
init_session_report();
|
|
52511
|
+
init_startup_screen();
|
|
52512
|
+
Stack = class {
|
|
52513
|
+
constructor(parts) {
|
|
52514
|
+
this.parts = parts;
|
|
52515
|
+
}
|
|
52516
|
+
parts;
|
|
52517
|
+
render(width2) {
|
|
52518
|
+
return this.parts.flatMap((part) => typeof part === "string" ? [part] : part.render(width2));
|
|
52519
|
+
}
|
|
52520
|
+
invalidate() {
|
|
52521
|
+
for (const part of this.parts) if (typeof part !== "string") part.invalidate();
|
|
52522
|
+
}
|
|
52523
|
+
};
|
|
52524
|
+
Indent = class {
|
|
52525
|
+
constructor(child, columns) {
|
|
52526
|
+
this.child = child;
|
|
52527
|
+
this.columns = columns;
|
|
52528
|
+
}
|
|
52529
|
+
child;
|
|
52530
|
+
columns;
|
|
52531
|
+
render(width2) {
|
|
52532
|
+
const pad3 = " ".repeat(this.columns);
|
|
52533
|
+
return this.child.render(Math.max(1, width2 - this.columns)).map((line2) => line2 === "" ? "" : pad3 + line2);
|
|
52534
|
+
}
|
|
52535
|
+
invalidate() {
|
|
52536
|
+
this.child.invalidate();
|
|
52537
|
+
}
|
|
52538
|
+
};
|
|
52539
|
+
DECISION_COLOR = {
|
|
52540
|
+
allow: "success",
|
|
52541
|
+
deny: "error",
|
|
52542
|
+
ask: "warning"
|
|
52543
|
+
};
|
|
52544
|
+
}
|
|
52545
|
+
});
|
|
52546
|
+
|
|
52547
|
+
// src/modes/context-report.ts
|
|
52548
|
+
function contextSnapshot(session) {
|
|
52549
|
+
let messages = session.messages;
|
|
52550
|
+
let estimate;
|
|
52551
|
+
let compaction = {};
|
|
52552
|
+
if (session instanceof AgentSessionImpl) {
|
|
52553
|
+
const branch = session.manager.branch();
|
|
52554
|
+
const items = buildProjection(branch).items;
|
|
52555
|
+
messages = items.map((item) => item.message);
|
|
52556
|
+
estimate = estimateProjectedTokens(items, branch);
|
|
52557
|
+
compaction = session.options.compaction ?? {};
|
|
52558
|
+
} else estimate = estimateContextTokens(messages);
|
|
52559
|
+
const window2 = session.getStats().contextWindow;
|
|
52560
|
+
const reserve = compaction.reserveTokens ?? DEFAULT_COMPACTION_SETTINGS.reserveTokens;
|
|
52561
|
+
const budget = window2 === void 0 ? void 0 : Math.max(0, window2 - reserve);
|
|
52562
|
+
const percent3 = window2 === void 0 || window2 <= 0 ? void 0 : Math.min(100, Math.round(estimate.tokens / window2 * 1e3) / 10);
|
|
52563
|
+
return {
|
|
52564
|
+
breakdown: breakdownMessages(messages),
|
|
52565
|
+
estimate,
|
|
52566
|
+
window: window2,
|
|
52567
|
+
percent: percent3,
|
|
52568
|
+
autoCompaction: session.state.autoCompaction,
|
|
52569
|
+
compactAt: budget,
|
|
52570
|
+
pruneAt: budget === void 0 ? void 0 : prunePolicy(budget, compaction.prune).triggerTokens
|
|
52571
|
+
};
|
|
52572
|
+
}
|
|
52573
|
+
function headerRows(snap) {
|
|
52574
|
+
const m = msg().report.contextReport;
|
|
52575
|
+
const { estimate, window: window2 } = snap;
|
|
52576
|
+
const rows = [
|
|
52577
|
+
{
|
|
52578
|
+
key: m.keyUsed,
|
|
52579
|
+
value: m.used(
|
|
52580
|
+
formatTokenCount(estimate.tokens),
|
|
52581
|
+
window2 === void 0 ? "?" : formatTokenCount(window2),
|
|
52582
|
+
snap.percent === void 0 ? void 0 : `${snap.percent.toFixed(1)}%`
|
|
52583
|
+
)
|
|
52584
|
+
}
|
|
52585
|
+
];
|
|
52586
|
+
if (window2 !== void 0)
|
|
52587
|
+
rows.push({
|
|
52588
|
+
key: m.keyLeft,
|
|
52589
|
+
value: m.left(formatTokenCount(Math.max(0, window2 - estimate.tokens)))
|
|
52590
|
+
});
|
|
52591
|
+
rows.push({
|
|
52592
|
+
key: m.keySource,
|
|
52593
|
+
value: estimate.lastUsageIndex === null ? m.sourceEstimate : m.sourceUsage(
|
|
52594
|
+
formatTokenCount(estimate.usageTokens),
|
|
52595
|
+
formatTokenCount(estimate.trailingTokens)
|
|
52596
|
+
)
|
|
52597
|
+
});
|
|
52598
|
+
let auto;
|
|
52599
|
+
if (!snap.autoCompaction) auto = m.autoCompactOff;
|
|
52600
|
+
else if (snap.compactAt === void 0) auto = m.windowUnknown;
|
|
52601
|
+
else if (estimate.tokens >= snap.compactAt)
|
|
52602
|
+
auto = m.autoCompactReached(formatTokenCount(snap.compactAt));
|
|
52603
|
+
else
|
|
52604
|
+
auto = m.autoCompact(
|
|
52605
|
+
formatTokenCount(snap.compactAt),
|
|
52606
|
+
formatTokenCount(snap.compactAt - estimate.tokens)
|
|
52607
|
+
);
|
|
52608
|
+
rows.push({ key: m.keyAutoCompact, value: auto });
|
|
52609
|
+
if (snap.autoCompaction && snap.pruneAt !== void 0)
|
|
52610
|
+
rows.push({ key: m.keyPrune, value: m.prune(formatTokenCount(Math.floor(snap.pruneAt))) });
|
|
52611
|
+
return rows;
|
|
52612
|
+
}
|
|
52613
|
+
function partName(entry, name) {
|
|
52614
|
+
const names = msg().report.contextReport.partNames;
|
|
52615
|
+
if (entry.category === "summaries" || entry.category === "images")
|
|
52616
|
+
return names[name] ?? name;
|
|
52617
|
+
return name;
|
|
52618
|
+
}
|
|
52619
|
+
function partsText(entry) {
|
|
52620
|
+
const m = msg().report.contextReport;
|
|
52621
|
+
const shown2 = entry.parts.slice(0, MAX_PARTS).map((part) => `${partName(entry, part.name)} ${formatTokenCount(part.tokens)}`);
|
|
52622
|
+
if (entry.parts.length > MAX_PARTS) shown2.push(m.more(entry.parts.length - MAX_PARTS));
|
|
52623
|
+
if (entry.category === "images" && entry.count > 0) shown2.unshift(m.images(entry.count));
|
|
52624
|
+
return shown2.join(" · ");
|
|
52625
|
+
}
|
|
52626
|
+
function categoryRows(breakdown, theme) {
|
|
52627
|
+
const m = msg().report.contextReport;
|
|
52628
|
+
const dim = (text) => theme === void 0 ? text : theme.fg("dim", text);
|
|
52629
|
+
return breakdown.entries.map((entry) => {
|
|
52630
|
+
const ratio = breakdown.total > 0 ? entry.tokens / breakdown.total : void 0;
|
|
52631
|
+
const meter = new Meter(ratio, { warnAt: 2, dangerAt: 2, ...theme ? { theme } : {} });
|
|
52632
|
+
const parts = partsText(entry);
|
|
52633
|
+
return {
|
|
52634
|
+
key: m.categories[entry.category],
|
|
52635
|
+
value: `${formatTokenCount(entry.tokens).padStart(6)} ${meter.render(40)[0] ?? ""}` + (parts === "" ? "" : ` ${dim(parts)}`)
|
|
52636
|
+
};
|
|
52637
|
+
});
|
|
52638
|
+
}
|
|
52639
|
+
function largestRows(breakdown) {
|
|
52640
|
+
return largestToolResults(breakdown, CONTEXT_TOP_RESULTS).map((result) => ({
|
|
52641
|
+
key: `#${result.ordinal}`,
|
|
52642
|
+
value: `${formatTokenCount(result.tokens).padStart(6)} ${result.toolName}`
|
|
52643
|
+
}));
|
|
52644
|
+
}
|
|
52645
|
+
function describeContext(session) {
|
|
52646
|
+
const m = msg().report.contextReport;
|
|
52647
|
+
const snap = contextSnapshot(session);
|
|
52648
|
+
const { breakdown } = snap;
|
|
52649
|
+
const lines2 = [m.title, ...renderRows(headerRows(snap), " "), ""];
|
|
52650
|
+
lines2.push(m.breakdown(formatTokenCount(breakdown.total)));
|
|
52651
|
+
lines2.push(` ${breakdown.hasSystem ? m.prefixCounted : m.prefixPending}`);
|
|
52652
|
+
if (breakdown.total === 0) lines2.push(` ${m.empty}`);
|
|
52653
|
+
else lines2.push(...renderRows(categoryRows(breakdown, void 0), " "));
|
|
52654
|
+
lines2.push("", m.largest(CONTEXT_TOP_RESULTS));
|
|
52655
|
+
const largest = largestRows(breakdown);
|
|
52656
|
+
if (largest.length === 0) lines2.push(` ${m.noToolResults}`);
|
|
52657
|
+
else lines2.push(...renderRows(largest, " "));
|
|
52658
|
+
return lines2.join("\n");
|
|
52659
|
+
}
|
|
52660
|
+
function contextPanel(session, theme) {
|
|
52661
|
+
const m = msg().report.contextReport;
|
|
52662
|
+
const snap = contextSnapshot(session);
|
|
52663
|
+
const { breakdown } = snap;
|
|
52664
|
+
const table2 = (rows, wrap2 = false) => new KeyValue(rows, { theme, maxKeyRatio: 0.3, ...wrap2 ? { wrap: true } : {} });
|
|
52665
|
+
const largest = largestRows(breakdown);
|
|
52666
|
+
const parts = [
|
|
52667
|
+
table2(headerRows(snap)),
|
|
52668
|
+
"",
|
|
52669
|
+
theme.bold(m.breakdown(formatTokenCount(breakdown.total))),
|
|
52670
|
+
new Indent(
|
|
52671
|
+
new Stack([
|
|
52672
|
+
new Text(theme.fg("dim", breakdown.hasSystem ? m.prefixCounted : m.prefixPending)),
|
|
52673
|
+
breakdown.total === 0 ? theme.fg("dim", m.empty) : table2(categoryRows(breakdown, theme), true)
|
|
52674
|
+
]),
|
|
52675
|
+
2
|
|
52676
|
+
),
|
|
52677
|
+
"",
|
|
52678
|
+
theme.bold(m.largest(CONTEXT_TOP_RESULTS)),
|
|
52679
|
+
largest.length === 0 ? new Indent(new Stack([theme.fg("dim", m.noToolResults)]), 2) : new Indent(table2(largest), 2)
|
|
52680
|
+
];
|
|
52681
|
+
return new Card(new Stack(parts), { theme, title: m.title });
|
|
52682
|
+
}
|
|
52683
|
+
var CONTEXT_TOP_RESULTS, MAX_PARTS;
|
|
52684
|
+
var init_context_report = __esm({
|
|
52685
|
+
"src/modes/context-report.ts"() {
|
|
52686
|
+
"use strict";
|
|
52687
|
+
init_session2();
|
|
52688
|
+
init_session_compaction();
|
|
52689
|
+
init_breakdown();
|
|
52690
|
+
init_estimate();
|
|
52691
|
+
init_prune_tier();
|
|
52692
|
+
init_i18n();
|
|
52693
|
+
init_projection();
|
|
52694
|
+
init_tui2();
|
|
52695
|
+
init_panels2();
|
|
52696
|
+
init_session_report();
|
|
52697
|
+
CONTEXT_TOP_RESULTS = 5;
|
|
52698
|
+
MAX_PARTS = 6;
|
|
52699
|
+
}
|
|
52700
|
+
});
|
|
52701
|
+
|
|
51722
52702
|
// src/modes/commands-core.ts
|
|
51723
52703
|
function command(name, key, args) {
|
|
51724
52704
|
const info2 = {
|
|
@@ -51890,6 +52870,8 @@ async function runSlashCommand(line2, ctx) {
|
|
|
51890
52870
|
}
|
|
51891
52871
|
case "session":
|
|
51892
52872
|
return { kind: "handled", message: describeSession(session) };
|
|
52873
|
+
case "context":
|
|
52874
|
+
return { kind: "handled", message: describeContext(session) };
|
|
51893
52875
|
case "cache":
|
|
51894
52876
|
return { kind: "handled", message: cacheCommand(session, args) };
|
|
51895
52877
|
case "rewind":
|
|
@@ -51940,6 +52922,7 @@ var init_commands_core = __esm({
|
|
|
51940
52922
|
init_tasks_report();
|
|
51941
52923
|
init_task_background();
|
|
51942
52924
|
init_session_report();
|
|
52925
|
+
init_context_report();
|
|
51943
52926
|
init_i18n();
|
|
51944
52927
|
BUILTIN_COMMANDS = [
|
|
51945
52928
|
command("help", "help"),
|
|
@@ -51954,6 +52937,7 @@ var init_commands_core = __esm({
|
|
|
51954
52937
|
command("tools", "tools", { key: "toolsArgs" }),
|
|
51955
52938
|
command("hooks", "hooks"),
|
|
51956
52939
|
command("session", "session"),
|
|
52940
|
+
command("context", "context"),
|
|
51957
52941
|
command("cache", "cache", "[warm off|streaming|idle | fingerprint]"),
|
|
51958
52942
|
command("statusline", "statusline", "[full|compact]"),
|
|
51959
52943
|
command("plan", "plan", { key: "planArgs" }),
|
|
@@ -52502,55 +53486,6 @@ var init_bypass = __esm({
|
|
|
52502
53486
|
}
|
|
52503
53487
|
});
|
|
52504
53488
|
|
|
52505
|
-
// src/cli/startup-screen.ts
|
|
52506
|
-
function startupScreenLevel(runtime) {
|
|
52507
|
-
return runtime.config.ui?.quietStartup ?? "normal";
|
|
52508
|
-
}
|
|
52509
|
-
function trustSourceLabel(source) {
|
|
52510
|
-
const labels2 = msg().cli.startupScreen.trustSource;
|
|
52511
|
-
return source === "trust-file" ? labels2.trustFile : labels2[source];
|
|
52512
|
-
}
|
|
52513
|
-
function tildePath(path, home) {
|
|
52514
|
-
if (home === void 0 || home === "") return path;
|
|
52515
|
-
const trimmed = /[\\/]$/.test(home) ? home.slice(0, -1) : home;
|
|
52516
|
-
if (path === trimmed) return "~";
|
|
52517
|
-
const next = path[trimmed.length];
|
|
52518
|
-
return path.startsWith(trimmed) && (next === "/" || next === "\\") ? `~${path.slice(trimmed.length)}` : path;
|
|
52519
|
-
}
|
|
52520
|
-
function startupInfo(runtime, home) {
|
|
52521
|
-
const { resources } = runtime;
|
|
52522
|
-
const info2 = {
|
|
52523
|
-
version: AMA_VERSION,
|
|
52524
|
-
model: formatModelRef(runtime.model),
|
|
52525
|
-
thinking: runtime.thinkingLevel,
|
|
52526
|
-
cwd: tildePath(runtime.paths.cwd, home),
|
|
52527
|
-
trusted: runtime.trust.trusted,
|
|
52528
|
-
trustSource: trustSourceLabel(runtime.trust.source),
|
|
52529
|
-
permissionMode: runtime.session.state.permissionMode,
|
|
52530
|
-
preset: runtime.config.tools?.preset ?? "default",
|
|
52531
|
-
codemode: effectiveCodemodeMode(runtime.config),
|
|
52532
|
-
contextFiles: resources.contextFiles.map((f) => (0, import_node_path93.basename)(f.path)),
|
|
52533
|
-
skills: resources.skills.filter((s2) => !isBuiltinSkill(s2)).length,
|
|
52534
|
-
prompts: resources.prompts.length,
|
|
52535
|
-
hooks: runtime.hooks.list().length,
|
|
52536
|
-
warnings: runtime.warnings.length
|
|
52537
|
-
};
|
|
52538
|
-
if (runtime.host !== void 0) info2.host = runtime.host.adapter.id;
|
|
52539
|
-
return info2;
|
|
52540
|
-
}
|
|
52541
|
-
var import_node_path93;
|
|
52542
|
-
var init_startup_screen = __esm({
|
|
52543
|
-
"src/cli/startup-screen.ts"() {
|
|
52544
|
-
"use strict";
|
|
52545
|
-
init_builtin3();
|
|
52546
|
-
import_node_path93 = require("node:path");
|
|
52547
|
-
init_channels();
|
|
52548
|
-
init_presets2();
|
|
52549
|
-
init_i18n();
|
|
52550
|
-
init_version();
|
|
52551
|
-
}
|
|
52552
|
-
});
|
|
52553
|
-
|
|
52554
53489
|
// src/modes/interactive/config-panel.ts
|
|
52555
53490
|
function settingValueText(spec2, value, theme) {
|
|
52556
53491
|
if (value.value === void 0 && spec2.key === "ui.ascii")
|
|
@@ -52813,8 +53748,8 @@ var init_config_panel = __esm({
|
|
|
52813
53748
|
const dynamic = value.value === void 0 ? settingDynamicDefault(row3.id) : void 0;
|
|
52814
53749
|
const text = dynamic === void 0 ? doc : `${doc} · ${dynamic}`;
|
|
52815
53750
|
const spec2 = settingsRegistry().find((x) => x.key === row3.id);
|
|
52816
|
-
const
|
|
52817
|
-
const lines2 =
|
|
53751
|
+
const blocked2 = spec2 === void 0 ? void 0 : blockedReason(spec2, value, this.scope);
|
|
53752
|
+
const lines2 = blocked2 === void 0 ? [] : [theme.fg("warning", truncateToWidth(blocked2, width2))];
|
|
52818
53753
|
if (text !== "") lines2.push(...wrapTextWithAnsi(theme.fg("dim", text), width2));
|
|
52819
53754
|
return lines2.slice(0, 3);
|
|
52820
53755
|
}
|
|
@@ -53857,8 +54792,8 @@ var init_config_ui = __esm({
|
|
|
53857
54792
|
const spec2 = settingSpec(key);
|
|
53858
54793
|
if (panel === void 0 || spec2 === void 0) return;
|
|
53859
54794
|
const current3 = getConfigValue(readSnapshot(this.input()), key);
|
|
53860
|
-
const
|
|
53861
|
-
if (
|
|
54795
|
+
const blocked2 = blockedReason(spec2, current3, scope);
|
|
54796
|
+
if (blocked2 !== void 0) return panel.setNotice(blocked2, "warning");
|
|
53862
54797
|
const value = current3.value;
|
|
53863
54798
|
switch (spec2.kind) {
|
|
53864
54799
|
case "bool":
|
|
@@ -55968,6 +56903,8 @@ function taskRow(info2, ctx) {
|
|
|
55968
56903
|
status,
|
|
55969
56904
|
turns: Math.max(state?.turns ?? 0, info2.turns ?? 0)
|
|
55970
56905
|
};
|
|
56906
|
+
const context = formatTaskContext(info2);
|
|
56907
|
+
if (context !== void 0) row3.context = context;
|
|
55971
56908
|
const tool = state?.tools.at(-1);
|
|
55972
56909
|
if (tool !== void 0 && status !== "queued") row3.tool = tool;
|
|
55973
56910
|
if (status !== "queued") {
|
|
@@ -55983,6 +56920,7 @@ function rowFacts(row3, withTool = true) {
|
|
|
55983
56920
|
const facts = [statusLabel(row3.status)];
|
|
55984
56921
|
if (row3.elapsedMs !== void 0) facts[0] += ` ${formatElapsed(row3.elapsedMs)}`;
|
|
55985
56922
|
if (row3.turns > 0) facts.push(msg().agents.turns(row3.turns));
|
|
56923
|
+
if (row3.context !== void 0) facts.push(msg().agents.context(row3.context));
|
|
55986
56924
|
if (withTool && row3.tool !== void 0 && row3.status === "running") facts.push(row3.tool);
|
|
55987
56925
|
return facts.join(" · ");
|
|
55988
56926
|
}
|
|
@@ -55990,6 +56928,7 @@ var BAR_ROWS, BAR_RETAIN_MS, ACTIVE, AgentBar;
|
|
|
55990
56928
|
var init_agent_bar = __esm({
|
|
55991
56929
|
"src/modes/interactive/agent-bar.ts"() {
|
|
55992
56930
|
"use strict";
|
|
56931
|
+
init_task_record();
|
|
55993
56932
|
init_i18n();
|
|
55994
56933
|
init_tui2();
|
|
55995
56934
|
BAR_ROWS = 3;
|
|
@@ -56574,171 +57513,6 @@ var init_agent_view = __esm({
|
|
|
56574
57513
|
}
|
|
56575
57514
|
});
|
|
56576
57515
|
|
|
56577
|
-
// src/modes/interactive/panels.ts
|
|
56578
|
-
function keyValue(rows, theme, wrap2 = false) {
|
|
56579
|
-
return new KeyValue(rows, { theme, maxKeyRatio: 0.3, ...wrap2 ? { wrap: true } : {} });
|
|
56580
|
-
}
|
|
56581
|
-
function cacheSection(session, theme, now) {
|
|
56582
|
-
return [
|
|
56583
|
-
theme.bold(msg().panels.cache.title),
|
|
56584
|
-
new Indent(keyValue(cacheRows(session, now), theme), 2)
|
|
56585
|
-
];
|
|
56586
|
-
}
|
|
56587
|
-
function sessionPanel(session, theme, options = {}) {
|
|
56588
|
-
const m = msg().panels.session;
|
|
56589
|
-
const now = options.now ?? Date.now();
|
|
56590
|
-
const state = session.state;
|
|
56591
|
-
const stats = session.getStats();
|
|
56592
|
-
const t = stats.tokens;
|
|
56593
|
-
const sep5 = theme.fg("dim", " · ");
|
|
56594
|
-
const model = state.model === void 0 ? "?" : `${state.model.provider}/${state.model.id}`;
|
|
56595
|
-
const ratio = stats.contextPercent === void 0 ? void 0 : stats.contextPercent / 100;
|
|
56596
|
-
const meter = new Meter(ratio, { theme }).render(40)[0] ?? "";
|
|
56597
|
-
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)}`;
|
|
56598
|
-
const rows = [
|
|
56599
|
-
{
|
|
56600
|
-
key: m.model,
|
|
56601
|
-
value: theme.fg("accent", model) + sep5 + m.thinking(state.thinkingLevel) + sep5 + m.permission(permissionModeLabel(state.permissionMode))
|
|
56602
|
-
},
|
|
56603
|
-
{
|
|
56604
|
-
key: m.messages,
|
|
56605
|
-
value: [
|
|
56606
|
-
m.user(stats.userMessages),
|
|
56607
|
-
m.assistant(stats.assistantMessages),
|
|
56608
|
-
m.toolCalls(stats.toolCalls)
|
|
56609
|
-
].join(sep5)
|
|
56610
|
-
},
|
|
56611
|
-
{
|
|
56612
|
-
key: m.usage,
|
|
56613
|
-
value: [
|
|
56614
|
-
m.input(formatTokenCount(t.input)),
|
|
56615
|
-
m.output(formatTokenCount(t.output)),
|
|
56616
|
-
m.cacheRead(formatTokenCount(t.cacheRead)),
|
|
56617
|
-
m.cacheWrite(formatTokenCount(t.cacheWrite)),
|
|
56618
|
-
formatUsd2(stats.cost)
|
|
56619
|
-
].join(sep5)
|
|
56620
|
-
},
|
|
56621
|
-
{ key: m.context, value: meter + window2 }
|
|
56622
|
-
];
|
|
56623
|
-
const tasks = taskStatsText(session);
|
|
56624
|
-
if (tasks !== void 0) rows.push({ key: m.subagents, value: tasks });
|
|
56625
|
-
const external = externalRows(session);
|
|
56626
|
-
const externalSection = external.length > 0 ? ["", theme.bold(m.external), new Indent(keyValue(external, theme), 2)] : [];
|
|
56627
|
-
const file = state.sessionFile === void 0 ? m.notSaved : tildePath(state.sessionFile, options.home);
|
|
56628
|
-
const parts = [
|
|
56629
|
-
keyValue(rows, theme),
|
|
56630
|
-
"",
|
|
56631
|
-
...cacheSection(session, theme, now),
|
|
56632
|
-
...externalSection
|
|
56633
|
-
];
|
|
56634
|
-
return new Card(new Stack(parts), {
|
|
56635
|
-
theme,
|
|
56636
|
-
title: m.title(state.sessionId.slice(0, 8)),
|
|
56637
|
-
subtitle: file
|
|
56638
|
-
});
|
|
56639
|
-
}
|
|
56640
|
-
function cachePanel(session, theme, now = Date.now()) {
|
|
56641
|
-
return new Card(keyValue(cacheRows(session, now), theme), {
|
|
56642
|
-
theme,
|
|
56643
|
-
title: msg().panels.cache.title
|
|
56644
|
-
});
|
|
56645
|
-
}
|
|
56646
|
-
function permissionsPanel(runtime, session, theme) {
|
|
56647
|
-
const m = msg().panels.permissions;
|
|
56648
|
-
const rules = runtime.permission.rules;
|
|
56649
|
-
const mode = session.state.permissionMode;
|
|
56650
|
-
const order = mode === "auto" ? m.orderAuto : mode === "allowlist" ? m.orderAllowlist : m.orderDefault;
|
|
56651
|
-
const effect = (decision) => theme.fg(DECISION_COLOR[decision] ?? "text", decision.padEnd(5));
|
|
56652
|
-
const parts = [
|
|
56653
|
-
keyValue(
|
|
56654
|
-
[
|
|
56655
|
-
{
|
|
56656
|
-
key: m.mode,
|
|
56657
|
-
value: m.modeValue(permissionModeLabel(mode), mode, (t) => theme.fg("dim", t))
|
|
56658
|
-
},
|
|
56659
|
-
{ key: m.order, value: order }
|
|
56660
|
-
],
|
|
56661
|
-
theme,
|
|
56662
|
-
true
|
|
56663
|
-
),
|
|
56664
|
-
theme.bold(rules.length === 0 ? m.rulesNone : m.rules(rules.length))
|
|
56665
|
-
];
|
|
56666
|
-
if (rules.length > 0) {
|
|
56667
|
-
parts.push(
|
|
56668
|
-
new Indent(
|
|
56669
|
-
keyValue(
|
|
56670
|
-
rules.map((r) => ({
|
|
56671
|
-
key: effect(r.effect),
|
|
56672
|
-
value: `${r.raw} ${theme.fg("dim", `[${r.source}]`)}`
|
|
56673
|
-
})),
|
|
56674
|
-
theme
|
|
56675
|
-
),
|
|
56676
|
-
2
|
|
56677
|
-
)
|
|
56678
|
-
);
|
|
56679
|
-
}
|
|
56680
|
-
const recent = runtime.permission.autoDecisions?.() ?? [];
|
|
56681
|
-
if (recent.length > 0) {
|
|
56682
|
-
parts.push(theme.bold(m.recentAuto(recent.length)));
|
|
56683
|
-
parts.push(
|
|
56684
|
-
new Indent(
|
|
56685
|
-
keyValue(
|
|
56686
|
-
recent.map((d) => ({
|
|
56687
|
-
key: autoLayerText(d.layer),
|
|
56688
|
-
value: `${effect(d.decision)} ${d.toolName} ${d.summary} — ${d.reason}` + (d.cached === true ? theme.fg("dim", m.cached) : "")
|
|
56689
|
-
})),
|
|
56690
|
-
theme
|
|
56691
|
-
),
|
|
56692
|
-
2
|
|
56693
|
-
)
|
|
56694
|
-
);
|
|
56695
|
-
}
|
|
56696
|
-
return new Card(new Stack(parts), { theme });
|
|
56697
|
-
}
|
|
56698
|
-
var Stack, Indent, DECISION_COLOR;
|
|
56699
|
-
var init_panels2 = __esm({
|
|
56700
|
-
"src/modes/interactive/panels.ts"() {
|
|
56701
|
-
"use strict";
|
|
56702
|
-
init_i18n();
|
|
56703
|
-
init_modes();
|
|
56704
|
-
init_tui2();
|
|
56705
|
-
init_session_report();
|
|
56706
|
-
init_startup_screen();
|
|
56707
|
-
Stack = class {
|
|
56708
|
-
constructor(parts) {
|
|
56709
|
-
this.parts = parts;
|
|
56710
|
-
}
|
|
56711
|
-
parts;
|
|
56712
|
-
render(width2) {
|
|
56713
|
-
return this.parts.flatMap((part) => typeof part === "string" ? [part] : part.render(width2));
|
|
56714
|
-
}
|
|
56715
|
-
invalidate() {
|
|
56716
|
-
for (const part of this.parts) if (typeof part !== "string") part.invalidate();
|
|
56717
|
-
}
|
|
56718
|
-
};
|
|
56719
|
-
Indent = class {
|
|
56720
|
-
constructor(child, columns) {
|
|
56721
|
-
this.child = child;
|
|
56722
|
-
this.columns = columns;
|
|
56723
|
-
}
|
|
56724
|
-
child;
|
|
56725
|
-
columns;
|
|
56726
|
-
render(width2) {
|
|
56727
|
-
const pad3 = " ".repeat(this.columns);
|
|
56728
|
-
return this.child.render(Math.max(1, width2 - this.columns)).map((line2) => line2 === "" ? "" : pad3 + line2);
|
|
56729
|
-
}
|
|
56730
|
-
invalidate() {
|
|
56731
|
-
this.child.invalidate();
|
|
56732
|
-
}
|
|
56733
|
-
};
|
|
56734
|
-
DECISION_COLOR = {
|
|
56735
|
-
allow: "success",
|
|
56736
|
-
deny: "error",
|
|
56737
|
-
ask: "warning"
|
|
56738
|
-
};
|
|
56739
|
-
}
|
|
56740
|
-
});
|
|
56741
|
-
|
|
56742
57516
|
// src/modes/interactive/agent-panels.ts
|
|
56743
57517
|
function planPanel(controller, session, theme, displayPath3 = (p) => p) {
|
|
56744
57518
|
const m = msg().panels.plan;
|
|
@@ -58104,6 +58878,7 @@ var init_commands2 = __esm({
|
|
|
58104
58878
|
init_fake_visibility();
|
|
58105
58879
|
init_modes();
|
|
58106
58880
|
init_commands_core();
|
|
58881
|
+
init_context_report();
|
|
58107
58882
|
init_message_view();
|
|
58108
58883
|
init_panels2();
|
|
58109
58884
|
init_pickers();
|
|
@@ -58123,6 +58898,12 @@ var init_commands2 = __esm({
|
|
|
58123
58898
|
await ui.traceView(args === "" ? void 0 : args);
|
|
58124
58899
|
return true;
|
|
58125
58900
|
},
|
|
58901
|
+
context: async (ui) => {
|
|
58902
|
+
const theme = ui.theme?.();
|
|
58903
|
+
if (ui.panel === void 0 || theme === void 0) return false;
|
|
58904
|
+
ui.panel(contextPanel(ui.session(), theme));
|
|
58905
|
+
return true;
|
|
58906
|
+
},
|
|
58126
58907
|
memory: async (ui, args) => {
|
|
58127
58908
|
if (ui.memoryPanel === void 0) return false;
|
|
58128
58909
|
await ui.memoryPanel(args);
|
|
@@ -58620,7 +59401,7 @@ var init_status_line = __esm({
|
|
|
58620
59401
|
stat16
|
|
58621
59402
|
);
|
|
58622
59403
|
}
|
|
58623
|
-
const usage = usageItems(stats, this.bar.queued(), this.source, theme);
|
|
59404
|
+
const usage = usageItems(stats, this.bar.queued(), this.source, theme, true);
|
|
58624
59405
|
add3("right", usage.tokens, PRIORITY.tokens);
|
|
58625
59406
|
add3("right", usage.cache, PRIORITY.cache);
|
|
58626
59407
|
add3("right", usage.rebill, PRIORITY.rebill);
|
|
@@ -60680,6 +61461,16 @@ var init_run_indicator = __esm({
|
|
|
60680
61461
|
function createSessionEventHandler(deps) {
|
|
60681
61462
|
const { view, tools, status, area, agentUi, indicator, session, setQueue, notice, render } = deps;
|
|
60682
61463
|
const images = new ImageBudgetNotices((text) => notice("info", text));
|
|
61464
|
+
const windowHinted = /* @__PURE__ */ new Set();
|
|
61465
|
+
const refresh = () => {
|
|
61466
|
+
status.refresh();
|
|
61467
|
+
if (status.current().contextWindow !== void 0) return;
|
|
61468
|
+
const model = session().state.model;
|
|
61469
|
+
const ref = model === void 0 ? void 0 : formatModelRef(model);
|
|
61470
|
+
if (ref === void 0 || windowHinted.has(ref)) return;
|
|
61471
|
+
windowHinted.add(ref);
|
|
61472
|
+
view.addNotice("info", msg().interactive.statusLine.noWindow(ref));
|
|
61473
|
+
};
|
|
60683
61474
|
return (event) => {
|
|
60684
61475
|
if (area.onEvent(event) || agentUi().onEvent(event)) {
|
|
60685
61476
|
if (event.type === "subagent_start" || event.type === "subagent_end") indicator.sync();
|
|
@@ -60690,7 +61481,7 @@ function createSessionEventHandler(deps) {
|
|
|
60690
61481
|
case "agent_settled":
|
|
60691
61482
|
if (event.warning !== void 0 && event.warning !== LIMIT_WARNING)
|
|
60692
61483
|
view.addNotice("warn", event.warning);
|
|
60693
|
-
|
|
61484
|
+
refresh();
|
|
60694
61485
|
break;
|
|
60695
61486
|
case "message_start": {
|
|
60696
61487
|
const message = event.message;
|
|
@@ -60703,12 +61494,14 @@ function createSessionEventHandler(deps) {
|
|
|
60703
61494
|
}
|
|
60704
61495
|
case "message_update":
|
|
60705
61496
|
view.updateAssistant(event.message);
|
|
61497
|
+
status.noteStreaming(event.message.usage);
|
|
60706
61498
|
break;
|
|
60707
61499
|
case "message_end":
|
|
60708
61500
|
if (event.message.role === "assistant") {
|
|
60709
61501
|
view.endAssistant(event.message);
|
|
61502
|
+
status.clearStreaming();
|
|
60710
61503
|
status.refresh();
|
|
60711
|
-
}
|
|
61504
|
+
} else if (event.message.role === "user") refresh();
|
|
60712
61505
|
break;
|
|
60713
61506
|
case "tool_execution_start": {
|
|
60714
61507
|
const started = tools.start(event);
|
|
@@ -60755,7 +61548,7 @@ function createSessionEventHandler(deps) {
|
|
|
60755
61548
|
case "model_changed":
|
|
60756
61549
|
case "thinking_level_changed":
|
|
60757
61550
|
case "session_changed":
|
|
60758
|
-
|
|
61551
|
+
refresh();
|
|
60759
61552
|
render();
|
|
60760
61553
|
return;
|
|
60761
61554
|
default:
|
|
@@ -60769,11 +61562,407 @@ var init_session_events = __esm({
|
|
|
60769
61562
|
"src/modes/interactive/session-events.ts"() {
|
|
60770
61563
|
"use strict";
|
|
60771
61564
|
init_i18n();
|
|
61565
|
+
init_channels();
|
|
60772
61566
|
init_session_report();
|
|
60773
61567
|
init_event_notices();
|
|
60774
61568
|
}
|
|
60775
61569
|
});
|
|
60776
61570
|
|
|
61571
|
+
// src/tui/program-status.ts
|
|
61572
|
+
function sanitizeLine(text) {
|
|
61573
|
+
return text.replace(/[\x00-\x1f\x7f-\x9f]/g, " ").replace(/\s+/g, " ").trim();
|
|
61574
|
+
}
|
|
61575
|
+
function truncateUtf8(text, maxBytes) {
|
|
61576
|
+
if (Buffer.byteLength(text, "utf8") <= maxBytes) return text;
|
|
61577
|
+
const budget = maxBytes - Buffer.byteLength(ELLIPSIS, "utf8");
|
|
61578
|
+
let used = 0;
|
|
61579
|
+
let out = "";
|
|
61580
|
+
for (const ch2 of text) {
|
|
61581
|
+
const n = Buffer.byteLength(ch2, "utf8");
|
|
61582
|
+
if (used + n > budget) break;
|
|
61583
|
+
used += n;
|
|
61584
|
+
out += ch2;
|
|
61585
|
+
}
|
|
61586
|
+
return out + ELLIPSIS;
|
|
61587
|
+
}
|
|
61588
|
+
function validId(id) {
|
|
61589
|
+
if (Buffer.byteLength(id, "utf8") > MAX_ID_BYTES) return false;
|
|
61590
|
+
const segments3 = id.split("/");
|
|
61591
|
+
return segments3.length <= MAX_ID_DEPTH && segments3.every((s2) => SEGMENT.test(s2));
|
|
61592
|
+
}
|
|
61593
|
+
function idSegment(raw, n = 12) {
|
|
61594
|
+
const s2 = raw.replace(/[^A-Za-z0-9_.+-]/g, "_").slice(0, n);
|
|
61595
|
+
return s2 === "" ? "x" : s2;
|
|
61596
|
+
}
|
|
61597
|
+
function encodeText(text, maxBytes) {
|
|
61598
|
+
if (text === void 0) return void 0;
|
|
61599
|
+
const line2 = sanitizeLine(text);
|
|
61600
|
+
if (line2 === "") return void 0;
|
|
61601
|
+
return Buffer.from(truncateUtf8(line2, maxBytes), "utf8").toString("base64");
|
|
61602
|
+
}
|
|
61603
|
+
function encodePairs(report2) {
|
|
61604
|
+
if (!STATES.includes(report2.state)) return void 0;
|
|
61605
|
+
if (report2.id !== void 0 && !validId(report2.id)) return void 0;
|
|
61606
|
+
const pairs = [`state=${report2.state}`];
|
|
61607
|
+
if (report2.id !== void 0) pairs.push(`id=${report2.id}`);
|
|
61608
|
+
if (report2.state === "blocked" && report2.kind !== void 0 && KINDS4.includes(report2.kind))
|
|
61609
|
+
pairs.push(`kind=${report2.kind}`);
|
|
61610
|
+
const p = report2.progress;
|
|
61611
|
+
if ((report2.state === "working" || report2.state === "blocked") && p !== void 0 && Number.isInteger(p) && p >= 0 && p <= 100)
|
|
61612
|
+
pairs.push(`progress=${p}`);
|
|
61613
|
+
if (report2.app !== void 0 && SEGMENT.test(report2.app)) pairs.push(`app=${report2.app}`);
|
|
61614
|
+
if (report2.state !== "clear") {
|
|
61615
|
+
const title = encodeText(report2.title, MAX_TITLE_BYTES);
|
|
61616
|
+
if (title !== void 0) pairs.push(`title=${title}`);
|
|
61617
|
+
const msg2 = encodeText(report2.msg, MAX_MSG_BYTES);
|
|
61618
|
+
if (msg2 !== void 0) pairs.push(`msg=${msg2}`);
|
|
61619
|
+
}
|
|
61620
|
+
while (osc(pairs.join(":")).length > MAX_SEQUENCE_BYTES) {
|
|
61621
|
+
const last = pairs.at(-1);
|
|
61622
|
+
if (!last.startsWith("msg=") && !last.startsWith("title=")) return void 0;
|
|
61623
|
+
pairs.pop();
|
|
61624
|
+
}
|
|
61625
|
+
return pairs.join(":");
|
|
61626
|
+
}
|
|
61627
|
+
function osc(body) {
|
|
61628
|
+
return `\x1B]7501;${body}\x1B\\`;
|
|
61629
|
+
}
|
|
61630
|
+
function tmuxPassthrough(sequence) {
|
|
61631
|
+
return `\x1BPtmux;${sequence.replaceAll("\x1B", "\x1B\x1B")}\x1B\\`;
|
|
61632
|
+
}
|
|
61633
|
+
function isProgramStatusReply(sequence) {
|
|
61634
|
+
return /^\x1b\]7501;\?/.test(sequence);
|
|
61635
|
+
}
|
|
61636
|
+
function isDa1Reply(sequence) {
|
|
61637
|
+
return /^\x1b\[\?[\d;]*c$/.test(sequence);
|
|
61638
|
+
}
|
|
61639
|
+
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;
|
|
61640
|
+
var init_program_status = __esm({
|
|
61641
|
+
"src/tui/program-status.ts"() {
|
|
61642
|
+
"use strict";
|
|
61643
|
+
PROGRAM_STATUS_QUERY = "\x1B]7501;?\x1B\\";
|
|
61644
|
+
DA1_QUERY = "\x1B[c";
|
|
61645
|
+
MAX_SEQUENCE_BYTES = 4096;
|
|
61646
|
+
MAX_TITLE_BYTES = 192;
|
|
61647
|
+
MAX_MSG_BYTES = 2048;
|
|
61648
|
+
MAX_ID_BYTES = 128;
|
|
61649
|
+
MAX_ID_DEPTH = 8;
|
|
61650
|
+
SEGMENT = /^[A-Za-z0-9_.+-]{1,32}$/;
|
|
61651
|
+
STATES = ["idle", "working", "done", "blocked", "error", "clear"];
|
|
61652
|
+
KINDS4 = ["permission", "question", "auth"];
|
|
61653
|
+
ELLIPSIS = "…";
|
|
61654
|
+
ProgramStatusEmitter = class {
|
|
61655
|
+
constructor(options) {
|
|
61656
|
+
this.options = options;
|
|
61657
|
+
this.tmux = Boolean(options.env?.["TMUX"]);
|
|
61658
|
+
this.now = options.now ?? Date.now;
|
|
61659
|
+
}
|
|
61660
|
+
options;
|
|
61661
|
+
support = "unknown";
|
|
61662
|
+
tmux;
|
|
61663
|
+
desired = /* @__PURE__ */ new Map();
|
|
61664
|
+
sent = /* @__PURE__ */ new Map();
|
|
61665
|
+
timers = /* @__PURE__ */ new Map();
|
|
61666
|
+
probeTimer;
|
|
61667
|
+
now;
|
|
61668
|
+
/** 当前是否会写出报告。 */
|
|
61669
|
+
get supported() {
|
|
61670
|
+
return this.support === "yes";
|
|
61671
|
+
}
|
|
61672
|
+
/** 按模式开始:on 直接启用,auto 发检测查询(tmux 里不检测,等同 off),off 什么都不做。 */
|
|
61673
|
+
start() {
|
|
61674
|
+
if (this.support !== "unknown") return;
|
|
61675
|
+
const mode = this.options.mode;
|
|
61676
|
+
if (mode === "off" || mode === "auto" && this.tmux) {
|
|
61677
|
+
this.support = "no";
|
|
61678
|
+
return;
|
|
61679
|
+
}
|
|
61680
|
+
if (mode === "on") return this.enable();
|
|
61681
|
+
this.support = "probing";
|
|
61682
|
+
this.options.write(PROGRAM_STATUS_QUERY + DA1_QUERY);
|
|
61683
|
+
this.probeTimer = setTimeout(() => this.settleProbe(false), this.options.timeoutMs ?? 300);
|
|
61684
|
+
this.probeTimer.unref?.();
|
|
61685
|
+
}
|
|
61686
|
+
/** 输入解析里调用:吞掉检测回复(返回 true),其余返回 false。 */
|
|
61687
|
+
handleInput(sequence) {
|
|
61688
|
+
if (isProgramStatusReply(sequence)) {
|
|
61689
|
+
if (this.support === "probing") this.settleProbe(true);
|
|
61690
|
+
return true;
|
|
61691
|
+
}
|
|
61692
|
+
if (isDa1Reply(sequence)) {
|
|
61693
|
+
if (this.support === "probing") this.settleProbe(false);
|
|
61694
|
+
return true;
|
|
61695
|
+
}
|
|
61696
|
+
return false;
|
|
61697
|
+
}
|
|
61698
|
+
/** 设定某个 id(缺省根记录)的状态;`clear` 同时忘掉该 id 及其下层的记录。 */
|
|
61699
|
+
report(report2) {
|
|
61700
|
+
const key = report2.id ?? "";
|
|
61701
|
+
const full = this.options.app !== void 0 ? { ...report2, app: this.options.app } : report2;
|
|
61702
|
+
if (report2.state === "clear") {
|
|
61703
|
+
for (const id of [...this.desired.keys()])
|
|
61704
|
+
if (key === "" || id === key || id.startsWith(`${key}/`)) this.forget(id);
|
|
61705
|
+
}
|
|
61706
|
+
this.desired.set(key, full);
|
|
61707
|
+
if (this.support === "yes") this.flush(key);
|
|
61708
|
+
if (report2.state === "clear") this.desired.delete(key);
|
|
61709
|
+
}
|
|
61710
|
+
/** 停止计时器(不再写任何东西)。 */
|
|
61711
|
+
dispose() {
|
|
61712
|
+
if (this.probeTimer !== void 0) clearTimeout(this.probeTimer);
|
|
61713
|
+
this.probeTimer = void 0;
|
|
61714
|
+
for (const timer of this.timers.values()) clearTimeout(timer);
|
|
61715
|
+
this.timers.clear();
|
|
61716
|
+
if (this.support === "probing") this.support = "no";
|
|
61717
|
+
}
|
|
61718
|
+
settleProbe(ok) {
|
|
61719
|
+
if (this.probeTimer !== void 0) clearTimeout(this.probeTimer);
|
|
61720
|
+
this.probeTimer = void 0;
|
|
61721
|
+
if (ok) this.enable();
|
|
61722
|
+
else this.support = "no";
|
|
61723
|
+
}
|
|
61724
|
+
enable() {
|
|
61725
|
+
this.support = "yes";
|
|
61726
|
+
for (const key of this.desired.keys()) this.flush(key);
|
|
61727
|
+
}
|
|
61728
|
+
forget(id) {
|
|
61729
|
+
this.desired.delete(id);
|
|
61730
|
+
this.sent.delete(id);
|
|
61731
|
+
const timer = this.timers.get(id);
|
|
61732
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
61733
|
+
this.timers.delete(id);
|
|
61734
|
+
}
|
|
61735
|
+
flush(key) {
|
|
61736
|
+
const report2 = this.desired.get(key);
|
|
61737
|
+
if (report2 === void 0) return;
|
|
61738
|
+
const body = encodePairs(report2);
|
|
61739
|
+
if (body === void 0) return;
|
|
61740
|
+
const last = this.sent.get(key);
|
|
61741
|
+
if (last?.body === body) return;
|
|
61742
|
+
const throttle = this.options.throttleMs ?? 500;
|
|
61743
|
+
const head = `${report2.state}:${report2.kind ?? ""}`;
|
|
61744
|
+
const wait = last !== void 0 && last.head === head ? last.at + throttle - this.now() : 0;
|
|
61745
|
+
if (wait > 0 && report2.state !== "clear") {
|
|
61746
|
+
if (!this.timers.has(key)) {
|
|
61747
|
+
const timer2 = setTimeout(() => {
|
|
61748
|
+
this.timers.delete(key);
|
|
61749
|
+
this.flush(key);
|
|
61750
|
+
}, wait);
|
|
61751
|
+
timer2.unref?.();
|
|
61752
|
+
this.timers.set(key, timer2);
|
|
61753
|
+
}
|
|
61754
|
+
return;
|
|
61755
|
+
}
|
|
61756
|
+
const timer = this.timers.get(key);
|
|
61757
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
61758
|
+
this.timers.delete(key);
|
|
61759
|
+
const sequence = osc(body);
|
|
61760
|
+
this.options.write(this.tmux ? tmuxPassthrough(sequence) : sequence);
|
|
61761
|
+
if (report2.state === "clear") this.sent.delete(key);
|
|
61762
|
+
else this.sent.set(key, { body, head, at: this.now() });
|
|
61763
|
+
}
|
|
61764
|
+
};
|
|
61765
|
+
}
|
|
61766
|
+
});
|
|
61767
|
+
|
|
61768
|
+
// src/modes/interactive/program-status-ui.ts
|
|
61769
|
+
function blocked(kind, text) {
|
|
61770
|
+
return { state: "blocked", kind, msg: text };
|
|
61771
|
+
}
|
|
61772
|
+
function programStatusUi(deps) {
|
|
61773
|
+
const { terminal, programStatus } = deps.options;
|
|
61774
|
+
const mode = deps.runtime.config.ui?.programStatus ?? "auto";
|
|
61775
|
+
if (terminal !== void 0 && programStatus === void 0 || mode === "off")
|
|
61776
|
+
return { wrap: (handler) => handler, start: () => void 0, exit: () => void 0 };
|
|
61777
|
+
const emitter = new ProgramStatusEmitter({
|
|
61778
|
+
write: (data2) => deps.tui.terminal.write(data2),
|
|
61779
|
+
mode,
|
|
61780
|
+
env: deps.env,
|
|
61781
|
+
app: "ama",
|
|
61782
|
+
...programStatus
|
|
61783
|
+
});
|
|
61784
|
+
const tracker = new ProgramStatusTracker(emitter, deps.cwd);
|
|
61785
|
+
deps.tui.addInputListener((data2) => {
|
|
61786
|
+
if (emitter.handleInput(data2)) return true;
|
|
61787
|
+
tracker.acknowledge();
|
|
61788
|
+
return false;
|
|
61789
|
+
});
|
|
61790
|
+
return {
|
|
61791
|
+
wrap: (handler) => (event) => {
|
|
61792
|
+
tracker.onEvent(event);
|
|
61793
|
+
handler(event);
|
|
61794
|
+
},
|
|
61795
|
+
start: () => {
|
|
61796
|
+
emitter.start();
|
|
61797
|
+
tracker.sync();
|
|
61798
|
+
},
|
|
61799
|
+
exit: () => {
|
|
61800
|
+
emitter.report({ state: "clear" });
|
|
61801
|
+
emitter.dispose();
|
|
61802
|
+
}
|
|
61803
|
+
};
|
|
61804
|
+
}
|
|
61805
|
+
var AUTH_EXPIRED, ProgramStatusTracker;
|
|
61806
|
+
var init_program_status_ui = __esm({
|
|
61807
|
+
"src/modes/interactive/program-status-ui.ts"() {
|
|
61808
|
+
"use strict";
|
|
61809
|
+
init_i18n();
|
|
61810
|
+
init_program_status();
|
|
61811
|
+
init_tool_summary();
|
|
61812
|
+
AUTH_EXPIRED = /\bauth_expired\b/;
|
|
61813
|
+
ProgramStatusTracker = class {
|
|
61814
|
+
constructor(emitter, cwd = () => void 0) {
|
|
61815
|
+
this.emitter = emitter;
|
|
61816
|
+
this.cwd = cwd;
|
|
61817
|
+
}
|
|
61818
|
+
emitter;
|
|
61819
|
+
cwd;
|
|
61820
|
+
running = false;
|
|
61821
|
+
activity;
|
|
61822
|
+
approvals = /* @__PURE__ */ new Map();
|
|
61823
|
+
plan;
|
|
61824
|
+
auth;
|
|
61825
|
+
outcome;
|
|
61826
|
+
lastError;
|
|
61827
|
+
tasks = /* @__PURE__ */ new Map();
|
|
61828
|
+
onEvent(event) {
|
|
61829
|
+
const run7 = msg().interactive.view.run;
|
|
61830
|
+
switch (event.type) {
|
|
61831
|
+
case "session_start":
|
|
61832
|
+
if (event.reason !== "startup") this.reset();
|
|
61833
|
+
break;
|
|
61834
|
+
case "agent_start":
|
|
61835
|
+
this.running = true;
|
|
61836
|
+
this.activity = run7.thinking;
|
|
61837
|
+
this.outcome = this.auth = this.lastError = void 0;
|
|
61838
|
+
for (const [key, task] of this.tasks)
|
|
61839
|
+
if (task.state !== "working" && task.state !== "blocked") this.dropTask(key);
|
|
61840
|
+
break;
|
|
61841
|
+
case "message_update": {
|
|
61842
|
+
const last = event.message.content.at(-1);
|
|
61843
|
+
this.activity = last?.type === "text" ? run7.replying : run7.thinking;
|
|
61844
|
+
break;
|
|
61845
|
+
}
|
|
61846
|
+
case "tool_execution_start":
|
|
61847
|
+
if (event.parentToolCallId === void 0) this.activity = run7.runningTool(event.toolName);
|
|
61848
|
+
break;
|
|
61849
|
+
case "compaction_start":
|
|
61850
|
+
this.activity = run7.compacting;
|
|
61851
|
+
break;
|
|
61852
|
+
case "message_end":
|
|
61853
|
+
if (event.message.role === "assistant" && event.message.stopReason === "error")
|
|
61854
|
+
this.lastError = event.message.errorMessage ?? "error";
|
|
61855
|
+
break;
|
|
61856
|
+
case "agent_end":
|
|
61857
|
+
if (!event.willRetry) this.outcome = this.outcomeOf(event.stopReason);
|
|
61858
|
+
break;
|
|
61859
|
+
case "agent_settled":
|
|
61860
|
+
this.running = false;
|
|
61861
|
+
this.outcome ??= { state: "done" };
|
|
61862
|
+
break;
|
|
61863
|
+
case "permission_request": {
|
|
61864
|
+
const summary2 = flat(toolSummary(event.toolName, event.input, this.cwd()), 80);
|
|
61865
|
+
const text = summary2 === "" ? event.toolName : `${event.toolName} · ${summary2}`;
|
|
61866
|
+
const taskId = event.context?.taskId;
|
|
61867
|
+
this.approvals.set(event.requestId, { msg: text, ...taskId ? { taskId } : {} });
|
|
61868
|
+
const task = taskId !== void 0 ? this.tasks.get(taskId) : void 0;
|
|
61869
|
+
if (task !== void 0) Object.assign(task, { state: "blocked", msg: text });
|
|
61870
|
+
break;
|
|
61871
|
+
}
|
|
61872
|
+
case "permission_resolved": {
|
|
61873
|
+
const taskId = this.approvals.get(event.requestId)?.taskId;
|
|
61874
|
+
this.approvals.delete(event.requestId);
|
|
61875
|
+
const task = taskId !== void 0 ? this.tasks.get(taskId) : void 0;
|
|
61876
|
+
const still = [...this.approvals.values()].some((p) => p.taskId === taskId);
|
|
61877
|
+
if (task?.state === "blocked" && !still) Object.assign(task, { state: "working" });
|
|
61878
|
+
break;
|
|
61879
|
+
}
|
|
61880
|
+
case "plan_proposed":
|
|
61881
|
+
this.plan = msg().plan.dialog.title;
|
|
61882
|
+
break;
|
|
61883
|
+
case "plan_resolved":
|
|
61884
|
+
this.plan = void 0;
|
|
61885
|
+
break;
|
|
61886
|
+
case "model_changed":
|
|
61887
|
+
this.auth = void 0;
|
|
61888
|
+
break;
|
|
61889
|
+
case "subagent_start":
|
|
61890
|
+
this.tasks.set(event.taskId, {
|
|
61891
|
+
id: `task/${idSegment(event.taskId)}`,
|
|
61892
|
+
title: event.description,
|
|
61893
|
+
state: "working",
|
|
61894
|
+
msg: event.agent
|
|
61895
|
+
});
|
|
61896
|
+
break;
|
|
61897
|
+
case "subagent_update": {
|
|
61898
|
+
const task = this.tasks.get(event.taskId);
|
|
61899
|
+
if (task?.state === "working" && event.toolName !== void 0)
|
|
61900
|
+
task.msg = run7.runningTool(event.toolName);
|
|
61901
|
+
break;
|
|
61902
|
+
}
|
|
61903
|
+
case "subagent_end": {
|
|
61904
|
+
const task = this.tasks.get(event.taskId);
|
|
61905
|
+
if (task === void 0) break;
|
|
61906
|
+
const s2 = event.status;
|
|
61907
|
+
task.state = s2 === "completed" ? "done" : s2 === "aborted" || s2 === "interrupted" ? "idle" : "error";
|
|
61908
|
+
delete task.msg;
|
|
61909
|
+
break;
|
|
61910
|
+
}
|
|
61911
|
+
default:
|
|
61912
|
+
return;
|
|
61913
|
+
}
|
|
61914
|
+
this.sync();
|
|
61915
|
+
}
|
|
61916
|
+
/** 用户按键:已看到的 done / error 回到 idle。 */
|
|
61917
|
+
acknowledge() {
|
|
61918
|
+
if (this.running || this.outcome === void 0 || this.outcome.state === "idle") return;
|
|
61919
|
+
this.outcome = { state: "idle" };
|
|
61920
|
+
this.sync();
|
|
61921
|
+
}
|
|
61922
|
+
/** 当前根记录(测试也用)。 */
|
|
61923
|
+
root() {
|
|
61924
|
+
const pending = [...this.approvals.values()].at(-1);
|
|
61925
|
+
if (pending !== void 0) return blocked("permission", pending.msg);
|
|
61926
|
+
if (this.plan !== void 0) return blocked("question", this.plan);
|
|
61927
|
+
if (this.auth !== void 0) return blocked("auth", this.auth);
|
|
61928
|
+
if (this.running)
|
|
61929
|
+
return { state: "working", ...this.activity !== void 0 ? { msg: this.activity } : {} };
|
|
61930
|
+
return this.outcome ?? { state: "idle" };
|
|
61931
|
+
}
|
|
61932
|
+
/** 写出全部记录(发射器同值去重)。 */
|
|
61933
|
+
sync() {
|
|
61934
|
+
this.emitter.report(this.root());
|
|
61935
|
+
for (const task of this.tasks.values())
|
|
61936
|
+
this.emitter.report({
|
|
61937
|
+
id: task.id,
|
|
61938
|
+
state: task.state,
|
|
61939
|
+
title: task.title,
|
|
61940
|
+
...task.state === "blocked" ? { kind: "permission" } : {},
|
|
61941
|
+
...task.msg !== void 0 ? { msg: task.msg } : {}
|
|
61942
|
+
});
|
|
61943
|
+
}
|
|
61944
|
+
outcomeOf(stopReason) {
|
|
61945
|
+
if (stopReason === "aborted") return { state: "idle" };
|
|
61946
|
+
if (stopReason !== "error") return { state: "done" };
|
|
61947
|
+
const text = flat(this.lastError ?? "error", 200);
|
|
61948
|
+
if (AUTH_EXPIRED.test(text)) this.auth = text;
|
|
61949
|
+
return { state: "error", msg: text };
|
|
61950
|
+
}
|
|
61951
|
+
dropTask(key) {
|
|
61952
|
+
const task = this.tasks.get(key);
|
|
61953
|
+
this.tasks.delete(key);
|
|
61954
|
+
if (task !== void 0) this.emitter.report({ id: task.id, state: "clear" });
|
|
61955
|
+
}
|
|
61956
|
+
reset() {
|
|
61957
|
+
this.running = false;
|
|
61958
|
+
this.approvals.clear();
|
|
61959
|
+
this.plan = this.auth = this.outcome = this.lastError = this.activity = void 0;
|
|
61960
|
+
for (const key of [...this.tasks.keys()]) this.dropTask(key);
|
|
61961
|
+
}
|
|
61962
|
+
};
|
|
61963
|
+
}
|
|
61964
|
+
});
|
|
61965
|
+
|
|
60777
61966
|
// src/modes/interactive/terminal-setup.ts
|
|
60778
61967
|
function processTerminal() {
|
|
60779
61968
|
const stdin = process.stdin;
|
|
@@ -60818,6 +62007,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
60818
62007
|
const keys = options.keybindings ?? loadKeys(runtime, (m) => startupWarnings.push(m));
|
|
60819
62008
|
let session = currentSession(runtime);
|
|
60820
62009
|
const tui = new TUI(terminal);
|
|
62010
|
+
const osc7501 = programStatusUi({ tui, runtime, env, options, cwd: () => session.state.cwd });
|
|
60821
62011
|
const view = new MessageView({
|
|
60822
62012
|
theme,
|
|
60823
62013
|
...ui.showThinking !== void 0 ? { showThinking: ui.showThinking } : {},
|
|
@@ -60917,7 +62107,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
60917
62107
|
queueView.setQueue(steering, followUp);
|
|
60918
62108
|
render();
|
|
60919
62109
|
};
|
|
60920
|
-
const
|
|
62110
|
+
const handleEvent3 = createSessionEventHandler({
|
|
60921
62111
|
view,
|
|
60922
62112
|
tools,
|
|
60923
62113
|
status,
|
|
@@ -60929,6 +62119,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
60929
62119
|
notice,
|
|
60930
62120
|
render
|
|
60931
62121
|
});
|
|
62122
|
+
const onEvent = osc7501.wrap(handleEvent3);
|
|
60932
62123
|
let unsubscribe = session.subscribe(onEvent);
|
|
60933
62124
|
const startupLevel = startupScreenLevel(runtime);
|
|
60934
62125
|
const home = env["HOME"] ?? env["USERPROFILE"];
|
|
@@ -61156,6 +62347,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
61156
62347
|
if (hintTimer !== void 0) clearTimeout(hintTimer);
|
|
61157
62348
|
loader.stop();
|
|
61158
62349
|
area.dispose();
|
|
62350
|
+
osc7501.exit();
|
|
61159
62351
|
view.addExitSummary(exitSummaryLines(session.getStats(), now() - startedAt, theme));
|
|
61160
62352
|
tui.clear();
|
|
61161
62353
|
tui.addChild(view);
|
|
@@ -61194,6 +62386,7 @@ function runInteractiveMode(runtime, context, options = {}) {
|
|
|
61194
62386
|
);
|
|
61195
62387
|
return;
|
|
61196
62388
|
}
|
|
62389
|
+
osc7501.start();
|
|
61197
62390
|
runtime.approvals.setUiBroker(broker);
|
|
61198
62391
|
runtime.notifier.set((message, level) => notice(level, message));
|
|
61199
62392
|
agentUi.attach(session);
|
|
@@ -61250,6 +62443,7 @@ var init_interactive_mode = __esm({
|
|
|
61250
62443
|
init_run_indicator();
|
|
61251
62444
|
init_status_area();
|
|
61252
62445
|
init_session_events();
|
|
62446
|
+
init_program_status_ui();
|
|
61253
62447
|
init_subagent_view();
|
|
61254
62448
|
init_terminal_setup();
|
|
61255
62449
|
init_tool_view();
|
|
@@ -66972,7 +68166,7 @@ function traceHtmlData(source, opts) {
|
|
|
66972
68166
|
}
|
|
66973
68167
|
const du = durationText(node, theme);
|
|
66974
68168
|
if (du !== "") out.du = du;
|
|
66975
|
-
const tk =
|
|
68169
|
+
const tk = tokensText2(node, theme);
|
|
66976
68170
|
if (tk !== "") out.tk = tk;
|
|
66977
68171
|
const ca = cacheText2(node);
|
|
66978
68172
|
if (ca !== "") out.ca = ca;
|