lark-remote 0.4.4 → 0.5.0
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 +28 -0
- package/dist/binder.d.ts +11 -10
- package/dist/binder.js +17 -16
- package/dist/bridge/approval-coordinator.d.ts +1 -1
- package/dist/bridge/approval-coordinator.js +3 -3
- package/dist/bridge/inbound-media.d.ts +1 -27
- package/dist/bridge/inbound-media.js +23 -21
- package/dist/bridge/index.d.ts +57 -57
- package/dist/bridge/index.js +136 -129
- package/dist/bridge/queue-manager.d.ts +45 -38
- package/dist/bridge/queue-manager.js +136 -136
- package/dist/card/approval-render.d.ts +1 -1
- package/dist/card/approval-render.js +6 -6
- package/dist/card/bash-card-session.d.ts +3 -3
- package/dist/card/bash-card-session.js +3 -3
- package/dist/card/bash-renderer.js +5 -5
- package/dist/card/card-session.d.ts +4 -4
- package/dist/card/card-session.js +6 -6
- package/dist/card/card-shared.d.ts +1 -1
- package/dist/card/card-shared.js +2 -2
- package/dist/card/run-card-session.js +2 -2
- package/dist/card/run-renderer.d.ts +1 -1
- package/dist/card/run-renderer.js +22 -22
- package/dist/card/run-state.d.ts +2 -2
- package/dist/card/run-state.js +3 -3
- package/dist/card/tool-render.d.ts +1 -1
- package/dist/card/tool-render.js +6 -6
- package/dist/cli.js +5 -6
- package/dist/clone.d.ts +6 -9
- package/dist/clone.js +12 -8
- package/dist/common/clamp.d.ts +2 -0
- package/dist/common/clamp.js +5 -0
- package/dist/common/fs.d.ts +4 -3
- package/dist/common/fs.js +5 -4
- package/dist/common/truncate.d.ts +1 -1
- package/dist/common/truncate.js +2 -2
- package/dist/common/ttl-cache.d.ts +2 -2
- package/dist/common/ttl-cache.js +2 -2
- package/dist/config/codex-config.d.ts +9 -9
- package/dist/config/codex-config.js +18 -18
- package/dist/config/dir.d.ts +4 -5
- package/dist/config/dir.js +12 -10
- package/dist/config/index.d.ts +3 -3
- package/dist/config/index.js +6 -6
- package/dist/config/opencode-config.js +3 -3
- package/dist/config/wizard.js +2 -2
- package/dist/connector/index.d.ts +5 -7
- package/dist/connector/index.js +29 -16
- package/dist/inbound/event.d.ts +1 -1
- package/dist/inbound/event.js +1 -1
- package/dist/inbound/placeholder.d.ts +2 -2
- package/dist/inbound/placeholder.js +2 -2
- package/dist/inbound/receipt.d.ts +1 -3
- package/dist/inbound/receipt.js +2 -2
- package/dist/inbound/turn-assembler.d.ts +1 -3
- package/dist/inbound/turn-assembler.js +2 -2
- package/dist/index.js +38 -30
- package/dist/instance-lock.js +8 -7
- package/dist/logger/index.d.ts +1 -1
- package/dist/logger/index.js +4 -4
- package/dist/persistence/atomic-write.d.ts +1 -1
- package/dist/persistence/atomic-write.js +9 -5
- package/dist/platform/agent-stopper.d.ts +2 -2
- package/dist/platform/identity.d.ts +7 -1
- package/dist/platform/identity.js +2 -2
- package/dist/platform/path.d.ts +6 -0
- package/dist/platform/path.js +14 -8
- package/dist/platform/select.d.ts +1 -1
- package/dist/platform/select.js +1 -1
- package/dist/platform/shell.d.ts +2 -3
- package/dist/platform/spawn.d.ts +2 -2
- package/dist/platform/spawn.js +2 -2
- package/dist/platform/terminator-posix.js +6 -6
- package/dist/platform/terminator-win32.js +3 -3
- package/dist/platform/terminator.d.ts +3 -3
- package/dist/platform/terminator.js +2 -2
- package/dist/platform/types.d.ts +1 -1
- package/dist/restart.d.ts +1 -1
- package/dist/restart.js +5 -3
- package/dist/router/card-helpers.d.ts +1 -3
- package/dist/router/card-helpers.js +2 -2
- package/dist/router/config/codex.d.ts +1 -1
- package/dist/router/config/codex.js +3 -3
- package/dist/router/config/common/model-patch.d.ts +1 -2
- package/dist/router/config/common/model-patch.js +1 -2
- package/dist/router/config/opencode.js +2 -2
- package/dist/router/config/pi.js +1 -1
- package/dist/router/index.d.ts +30 -30
- package/dist/router/index.js +103 -84
- package/dist/router/order-exec-dispatch.d.ts +3 -10
- package/dist/router/order-exec-dispatch.js +5 -5
- package/dist/router/{utils.d.ts → usage-format.d.ts} +2 -4
- package/dist/router/{utils.js → usage-format.js} +3 -8
- package/dist/runner/bash/runner.d.ts +2 -2
- package/dist/runner/bash/runner.js +6 -6
- package/dist/runner/claude/runner.d.ts +1 -1
- package/dist/runner/claude/runner.js +2 -3
- package/dist/runner/claude/session.d.ts +4 -6
- package/dist/runner/claude/session.js +21 -23
- package/dist/runner/codex/app-server/runner.js +3 -3
- package/dist/runner/codex/app-server/translator.d.ts +2 -2
- package/dist/runner/codex/app-server/translator.js +5 -5
- package/dist/runner/common/acp/{protocol-helpers.d.ts → acp-approval.d.ts} +4 -10
- package/dist/runner/common/acp/{protocol-helpers.js → acp-approval.js} +7 -6
- package/dist/runner/common/acp/base-acp-runner.d.ts +1 -1
- package/dist/runner/common/acp/base-acp-runner.js +2 -2
- package/dist/runner/common/acp/base-translator.d.ts +3 -3
- package/dist/runner/common/acp/base-translator.js +4 -4
- package/dist/runner/common/acp/protocol-types.js +1 -1
- package/dist/runner/common/connection-based-runner.d.ts +5 -5
- package/dist/runner/common/connection-based-runner.js +5 -5
- package/dist/runner/common/jsonl-stream.d.ts +2 -2
- package/dist/runner/common/jsonl-stream.js +12 -12
- package/dist/runner/common/jsonrpc/client.d.ts +1 -1
- package/dist/runner/common/jsonrpc/client.js +1 -1
- package/dist/runner/common/jsonrpc/connection-manager.d.ts +13 -13
- package/dist/runner/common/jsonrpc/connection-manager.js +37 -37
- package/dist/runner/common/jsonrpc/transport.d.ts +1 -1
- package/dist/runner/common/jsonrpc/transport.js +2 -2
- package/dist/runner/common/{usage.d.ts → result-usage.d.ts} +1 -1
- package/dist/runner/common/{usage.js → result-usage.js} +2 -2
- package/dist/runner/common/spawning-runner.d.ts +23 -10
- package/dist/runner/common/spawning-runner.js +48 -22
- package/dist/runner/common/{runner-utils.d.ts → synthetic-events.d.ts} +4 -4
- package/dist/runner/common/{runner-utils.js → synthetic-events.js} +5 -5
- package/dist/runner/dsh/client.d.ts +1 -1
- package/dist/runner/dsh/client.js +1 -1
- package/dist/runner/dsh/runner.js +3 -3
- package/dist/runner/kimi/acp/runner.d.ts +4 -4
- package/dist/runner/kimi/acp/runner.js +10 -10
- package/dist/runner/kimi/acp/translator.d.ts +2 -2
- package/dist/runner/kimi/acp/translator.js +5 -5
- package/dist/runner/opencode/acp/runner.d.ts +4 -4
- package/dist/runner/opencode/acp/runner.js +4 -4
- package/dist/runner/opencode/acp/translator.js +2 -2
- package/dist/runner/pi/rpc/runner.d.ts +1 -1
- package/dist/runner/pi/rpc/runner.js +2 -2
- package/dist/runner/pi/rpc/translator.d.ts +1 -2
- package/dist/runner/pi/rpc/translator.js +4 -6
- package/dist/runner/registry.d.ts +3 -3
- package/dist/runner/registry.js +3 -3
- package/dist/runner/types.d.ts +1 -1
- package/dist/session/claude/session-index.d.ts +13 -1
- package/dist/session/claude/session-index.js +21 -6
- package/dist/session/claude/session-reader.d.ts +1 -1
- package/dist/session/claude/session-reader.js +1 -1
- package/dist/session/claude/sessions.js +10 -10
- package/dist/session/codex/rollout-reader.d.ts +4 -4
- package/dist/session/codex/rollout-reader.js +14 -14
- package/dist/session/common/two-pass.js +2 -2
- package/dist/session/common/usage-accumulator.d.ts +2 -2
- package/dist/session/common/usage-accumulator.js +2 -2
- package/dist/session/dsh/sessions.d.ts +1 -1
- package/dist/session/dsh/sessions.js +3 -3
- package/dist/session/kimi/sessions.d.ts +2 -6
- package/dist/session/kimi/sessions.js +13 -19
- package/dist/session/opencode/sessions.d.ts +3 -3
- package/dist/session/opencode/sessions.js +15 -13
- package/dist/session/pi/sessions.js +13 -12
- package/dist/session/registry.d.ts +1 -1
- package/dist/session/registry.js +1 -1
- package/dist/session/session-store.d.ts +3 -4
- package/dist/session/session-store.js +3 -5
- package/dist/update/index.d.ts +1 -1
- package/dist/update/index.js +1 -1
- package/dist/update/version-check.d.ts +5 -3
- package/dist/update/version-check.js +10 -8
- package/dist/workspace/index.d.ts +4 -4
- package/dist/workspace/index.js +5 -5
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* renderApprovalArea: renders the approval request area in a run card.
|
|
3
3
|
*
|
|
4
|
-
* Renders command/file/permissions approval areas with button mappings
|
|
4
|
+
* Renders command/file/permissions approval areas with button mappings.
|
|
5
5
|
* Uses CardKit 2.0 (no tag:"action" container — 200861 rule).
|
|
6
6
|
*/
|
|
7
7
|
import type { ApprovalView } from '../runner/types.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* renderApprovalArea: renders the approval request area in a run card.
|
|
3
3
|
*
|
|
4
|
-
* Renders command/file/permissions approval areas with button mappings
|
|
4
|
+
* Renders command/file/permissions approval areas with button mappings.
|
|
5
5
|
* Uses CardKit 2.0 (no tag:"action" container — 200861 rule).
|
|
6
6
|
*/
|
|
7
7
|
import { collapsibleMarkdownPanel } from './collapsible.js';
|
|
@@ -13,7 +13,7 @@ function mkNonce() {
|
|
|
13
13
|
}
|
|
14
14
|
/** 计划面板正文字节预算(折叠展示 + 截断保护 28KB 卡片预算)。 */
|
|
15
15
|
const PLAN_PANEL_BYTES = 6000;
|
|
16
|
-
/** reason div(3 处共用);反引号中和防 lark_md
|
|
16
|
+
/** reason div(3 处共用);反引号中和防 lark_md 解析错误。 */
|
|
17
17
|
function reasonDiv(approval) {
|
|
18
18
|
if (!approval.reason)
|
|
19
19
|
return null;
|
|
@@ -39,7 +39,7 @@ export function renderApprovalArea(approval, opts) {
|
|
|
39
39
|
if (!approval)
|
|
40
40
|
return [];
|
|
41
41
|
// 终态(done/error/interrupted/idle_timeout)下 run 已结束:coordinator 已
|
|
42
|
-
// 释放,按钮点击无处响应,隐藏整个审批区避免"点了没反应"
|
|
42
|
+
// 释放,按钮点击无处响应,隐藏整个审批区避免"点了没反应"。
|
|
43
43
|
if (opts?.terminal && opts.terminal !== 'running' && opts.terminal !== 'finalizing') {
|
|
44
44
|
return [];
|
|
45
45
|
}
|
|
@@ -238,7 +238,7 @@ function renderPlanFeedbackInput(requestId, runId) {
|
|
|
238
238
|
function renderCommandApproval(approval, expired, runId) {
|
|
239
239
|
const elements = [];
|
|
240
240
|
// Command display
|
|
241
|
-
//
|
|
241
|
+
// 命令里的反引号会提前终止 lark_md 行内代码 span,奇数次
|
|
242
242
|
// 反引号极易触发 11311 解析错误导致整卡失败(同 renderFileDiff 的中和策略)。
|
|
243
243
|
const neutralizedCommand = (approval.command ?? '').replace(/`/g, '·');
|
|
244
244
|
const cmdContent = neutralizedCommand
|
|
@@ -422,7 +422,7 @@ function renderQuestionApproval(approval, expired, runId) {
|
|
|
422
422
|
elements.push(renderOptionRow(approval.requestId, i, option, isSelected, icon, runId));
|
|
423
423
|
}
|
|
424
424
|
// 自定义答案(Other)的选中态展示:选项按钮无法表示自由文本,单独显示
|
|
425
|
-
//
|
|
425
|
+
// 已选文本,避免「点了没反应」的困惑。
|
|
426
426
|
const customSelected = q.selected?.find((s) => !q.options.some((o) => o.label === s));
|
|
427
427
|
if (customSelected) {
|
|
428
428
|
elements.push({
|
|
@@ -430,7 +430,7 @@ function renderQuestionApproval(approval, expired, runId) {
|
|
|
430
430
|
text: { tag: 'lark_md', content: `✍️ 自定义答案:${customSelected}` },
|
|
431
431
|
});
|
|
432
432
|
}
|
|
433
|
-
//
|
|
433
|
+
// 单选问题提供自定义答案(Other)输入——输入文本后提交
|
|
434
434
|
// (移动端键盘回车/完成键,桌面端输入框右侧提交图标),input_value 经
|
|
435
435
|
// connector raw 事件回传。
|
|
436
436
|
// 显隐按 isOther !== false:Kimi form 会丢弃非声明选项值,翻译时置
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CardSession, type CardChannel } from './card-session.js';
|
|
2
2
|
import { type BashState, type BashRenderOptions } from './bash-renderer.js';
|
|
3
3
|
/**
|
|
4
|
-
* Store-time
|
|
4
|
+
* Store-time 输出上限(字符,层①)。建议「store-time 截断,
|
|
5
5
|
* 保留尾部,上限如 24~64KB」——取区间下界 24_000 字符(字符上限 ×4 字节最坏
|
|
6
6
|
* ~96KB/字段)。渲染层本就只展示尾部(bash-renderer 截断到 12KB 字节),store 截断
|
|
7
7
|
* 不影响显示内容,只保证内存有界:!yes / !cat 大文件不再把全部输出驻留在 session
|
|
@@ -9,7 +9,7 @@ import { type BashState, type BashRenderOptions } from './bash-renderer.js';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare const BASH_OUTPUT_STORE_CAP = 24000;
|
|
11
11
|
/**
|
|
12
|
-
* Store-time
|
|
12
|
+
* Store-time 截断入口(层①/层④共用)。bridge 本地 output/stderr 与 session
|
|
13
13
|
* state 都走它,保证任意路径驻留的字符串 ≤ BASH_OUTPUT_STORE_CAP 字符。
|
|
14
14
|
* 调用方传入的 value 通常已 ≤ CAP(增量场景 output 恒 ≤ CAP,+chunk 后 ≤ CAP+chunk),
|
|
15
15
|
* slice(-CAP) 成本 O(CAP+chunk),不会把 O(n²) 截断问题带回桥接循环。
|
|
@@ -49,7 +49,7 @@ export declare class BashCardSession extends CardSession<BashState, BashRenderOp
|
|
|
49
49
|
output?: string;
|
|
50
50
|
}): Promise<void>;
|
|
51
51
|
/**
|
|
52
|
-
* 合并 patch 并对 output/stderr 做 store-time
|
|
52
|
+
* 合并 patch 并对 output/stderr 做 store-time 截断(层①)。
|
|
53
53
|
* 截断发生在入口(store 时),渲染层无需再为大 state 付代价。
|
|
54
54
|
*/
|
|
55
55
|
private applyCap;
|
|
@@ -2,7 +2,7 @@ import { CardSession } from './card-session.js';
|
|
|
2
2
|
import { renderBashCard } from './bash-renderer.js';
|
|
3
3
|
import { keepTail } from '../common/truncate.js';
|
|
4
4
|
/**
|
|
5
|
-
* Store-time
|
|
5
|
+
* Store-time 输出上限(字符,层①)。建议「store-time 截断,
|
|
6
6
|
* 保留尾部,上限如 24~64KB」——取区间下界 24_000 字符(字符上限 ×4 字节最坏
|
|
7
7
|
* ~96KB/字段)。渲染层本就只展示尾部(bash-renderer 截断到 12KB 字节),store 截断
|
|
8
8
|
* 不影响显示内容,只保证内存有界:!yes / !cat 大文件不再把全部输出驻留在 session
|
|
@@ -10,7 +10,7 @@ import { keepTail } from '../common/truncate.js';
|
|
|
10
10
|
*/
|
|
11
11
|
export const BASH_OUTPUT_STORE_CAP = 24_000;
|
|
12
12
|
/**
|
|
13
|
-
* Store-time
|
|
13
|
+
* Store-time 截断入口(层①/层④共用)。bridge 本地 output/stderr 与 session
|
|
14
14
|
* state 都走它,保证任意路径驻留的字符串 ≤ BASH_OUTPUT_STORE_CAP 字符。
|
|
15
15
|
* 调用方传入的 value 通常已 ≤ CAP(增量场景 output 恒 ≤ CAP,+chunk 后 ≤ CAP+chunk),
|
|
16
16
|
* slice(-CAP) 成本 O(CAP+chunk),不会把 O(n²) 截断问题带回桥接循环。
|
|
@@ -92,7 +92,7 @@ export class BashCardSession extends CardSession {
|
|
|
92
92
|
this.release();
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
95
|
-
* 合并 patch 并对 output/stderr 做 store-time
|
|
95
|
+
* 合并 patch 并对 output/stderr 做 store-time 截断(层①)。
|
|
96
96
|
* 截断发生在入口(store 时),渲染层无需再为大 state 付代价。
|
|
97
97
|
*/
|
|
98
98
|
applyCap(patch) {
|
|
@@ -71,14 +71,14 @@ function assembleCard(state, elements) {
|
|
|
71
71
|
schema: '2.0',
|
|
72
72
|
config: { wide_screen_mode: true, update_multi: true },
|
|
73
73
|
header: {
|
|
74
|
-
template:
|
|
75
|
-
title: { content:
|
|
74
|
+
template: bashHeaderTemplate(state.terminal),
|
|
75
|
+
title: { content: bashHeaderTitle(state.terminal), tag: 'plain_text' },
|
|
76
76
|
},
|
|
77
77
|
body: { elements },
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
* Build output/stderr elements shared by normal & degraded paths (
|
|
81
|
+
* Build output/stderr elements shared by normal & degraded paths (单源):
|
|
82
82
|
* 除截断预算(OUTPUT_MAX_BYTES / DEGRADED_OUTPUT_BYTES)外逐行同构。
|
|
83
83
|
*/
|
|
84
84
|
function buildOutputElements(state, maxBytes) {
|
|
@@ -161,7 +161,7 @@ function bashStatusTagLabel(terminal, exitCode) {
|
|
|
161
161
|
return '出错';
|
|
162
162
|
}
|
|
163
163
|
/** CardKit 2.0 header title */
|
|
164
|
-
function
|
|
164
|
+
function bashHeaderTitle(terminal) {
|
|
165
165
|
if (terminal === 'running')
|
|
166
166
|
return '💻 执行命令...';
|
|
167
167
|
if (terminal === 'error')
|
|
@@ -171,7 +171,7 @@ function bashHeaderTitle2(terminal) {
|
|
|
171
171
|
return '✅ 命令执行完成';
|
|
172
172
|
}
|
|
173
173
|
/** CardKit 2.0 header template */
|
|
174
|
-
function
|
|
174
|
+
function bashHeaderTemplate(terminal) {
|
|
175
175
|
return terminalToColor(terminal);
|
|
176
176
|
}
|
|
177
177
|
//# sourceMappingURL=bash-renderer.js.map
|
|
@@ -59,7 +59,7 @@ export declare abstract class CardSession<S, RO = unknown> {
|
|
|
59
59
|
* 调度一次延迟 flush。已有 pending 调度则复用(合批核心);否则起一个
|
|
60
60
|
* coalesceMs 定时器。flushInFlight 期间不再起 timer(避免重入叠加),但置
|
|
61
61
|
* pendingReschedule 以便 in-flight flush 完成后重新调度——否则 in-flight 期间
|
|
62
|
-
* 到达的 push/update 会停留为 stale
|
|
62
|
+
* 到达的 push/update 会停留为 stale 中间帧。
|
|
63
63
|
*/
|
|
64
64
|
protected scheduleFlush(): void;
|
|
65
65
|
/**
|
|
@@ -87,14 +87,14 @@ export declare abstract class CardSession<S, RO = unknown> {
|
|
|
87
87
|
/** The messageId of the streaming card, available after `start()` resolves. */
|
|
88
88
|
get cardMessageId(): string | undefined;
|
|
89
89
|
/**
|
|
90
|
-
*
|
|
90
|
+
* 合批窗口(ms)。连续事件各触发一次全卡 render + patch 是流式 CPU 主要
|
|
91
91
|
* 来源;窗口内多个事件复用同一次延迟 flush。窗口大小可通过 constructor 覆盖
|
|
92
92
|
* (测试用小窗口/0 禁用)。run/bash 子类共用的 flush 骨架(scheduleFlush/flush/
|
|
93
93
|
* cancelPendingFlush/settle)下沉到基类。
|
|
94
94
|
*/
|
|
95
95
|
protected readonly coalesceMs: number;
|
|
96
96
|
private flushTimer;
|
|
97
|
-
private flushInFlight; /**
|
|
97
|
+
private flushInFlight; /** in-flight flush 期间到达的 push/update 标记。scheduleFlush 在
|
|
98
98
|
* flushInFlight 时早退不调度新 timer,但事件已 reduce 进 state;若无此标志,
|
|
99
99
|
* in-flight flush 完成后该事件无 follow-up render,停留为 stale 中间帧。
|
|
100
100
|
* finally 检查此标志后重新 scheduleFlush,保证 in-flight 期间累积的事件最终被渲染。 */
|
|
@@ -102,7 +102,7 @@ export declare abstract class CardSession<S, RO = unknown> {
|
|
|
102
102
|
/** 当前 in-flight flush 的 promise(若 flush 正在 await updateCard)。
|
|
103
103
|
* finish() 在终态 patch 前 await 它,保证 in-flight 的 pre-terminal patch 先落地、
|
|
104
104
|
* terminal patch 后落地——否则两条 controller.update 并发无 FIFO,
|
|
105
|
-
* pre-terminal 可能在 terminal 之后 resolve 留下"思考中"
|
|
105
|
+
* pre-terminal 可能在 terminal 之后 resolve 留下"思考中"终帧。 */
|
|
106
106
|
protected flushP: Promise<void> | undefined;
|
|
107
107
|
start(): Promise<void>;
|
|
108
108
|
settle(): Promise<StreamSettleResult>;
|
|
@@ -46,7 +46,7 @@ export class CardSession {
|
|
|
46
46
|
* 调度一次延迟 flush。已有 pending 调度则复用(合批核心);否则起一个
|
|
47
47
|
* coalesceMs 定时器。flushInFlight 期间不再起 timer(避免重入叠加),但置
|
|
48
48
|
* pendingReschedule 以便 in-flight flush 完成后重新调度——否则 in-flight 期间
|
|
49
|
-
* 到达的 push/update 会停留为 stale
|
|
49
|
+
* 到达的 push/update 会停留为 stale 中间帧。
|
|
50
50
|
*/
|
|
51
51
|
scheduleFlush() {
|
|
52
52
|
if (this.flushTimer)
|
|
@@ -82,7 +82,7 @@ export class CardSession {
|
|
|
82
82
|
this.flushInFlight = false;
|
|
83
83
|
// flushInFlight 守卫保证同一时刻只有一个 in-flight flush,故可无条件清空。
|
|
84
84
|
this.flushP = undefined;
|
|
85
|
-
//
|
|
85
|
+
// in-flight 期间若有 push/update 到达(pendingReschedule),重新调度一次
|
|
86
86
|
// flush 渲染累积事件,避免 stale 中间帧。终态守卫在 flush() 入口已拦截,
|
|
87
87
|
// 故 finish 后不会误触发。
|
|
88
88
|
if (this.pendingReschedule) {
|
|
@@ -117,14 +117,14 @@ export class CardSession {
|
|
|
117
117
|
return this.messageId;
|
|
118
118
|
}
|
|
119
119
|
/**
|
|
120
|
-
*
|
|
120
|
+
* 合批窗口(ms)。连续事件各触发一次全卡 render + patch 是流式 CPU 主要
|
|
121
121
|
* 来源;窗口内多个事件复用同一次延迟 flush。窗口大小可通过 constructor 覆盖
|
|
122
122
|
* (测试用小窗口/0 禁用)。run/bash 子类共用的 flush 骨架(scheduleFlush/flush/
|
|
123
123
|
* cancelPendingFlush/settle)下沉到基类。
|
|
124
124
|
*/
|
|
125
125
|
coalesceMs;
|
|
126
126
|
flushTimer;
|
|
127
|
-
flushInFlight = false; /**
|
|
127
|
+
flushInFlight = false; /** in-flight flush 期间到达的 push/update 标记。scheduleFlush 在
|
|
128
128
|
* flushInFlight 时早退不调度新 timer,但事件已 reduce 进 state;若无此标志,
|
|
129
129
|
* in-flight flush 完成后该事件无 follow-up render,停留为 stale 中间帧。
|
|
130
130
|
* finally 检查此标志后重新 scheduleFlush,保证 in-flight 期间累积的事件最终被渲染。 */
|
|
@@ -132,7 +132,7 @@ export class CardSession {
|
|
|
132
132
|
/** 当前 in-flight flush 的 promise(若 flush 正在 await updateCard)。
|
|
133
133
|
* finish() 在终态 patch 前 await 它,保证 in-flight 的 pre-terminal patch 先落地、
|
|
134
134
|
* terminal patch 后落地——否则两条 controller.update 并发无 FIFO,
|
|
135
|
-
* pre-terminal 可能在 terminal 之后 resolve 留下"思考中"
|
|
135
|
+
* pre-terminal 可能在 terminal 之后 resolve 留下"思考中"终帧。 */
|
|
136
136
|
flushP;
|
|
137
137
|
async start() {
|
|
138
138
|
if (this.streamOutcome) {
|
|
@@ -158,7 +158,7 @@ export class CardSession {
|
|
|
158
158
|
// the controller is ready — by which time events pushed before the
|
|
159
159
|
// producer ran (see test_anchor_events_before_controller_ready_...) have
|
|
160
160
|
// already updated `this.state`. Reusing the initial card here would drop
|
|
161
|
-
// those early events. The
|
|
161
|
+
// those early events. The"reuse first render" optimization was
|
|
162
162
|
// rejected for this reason (premise "two renders with identical input"
|
|
163
163
|
// does not hold).
|
|
164
164
|
const stream = this.connector.streamCard(this.chatId, this.safeRenderCard(), async (controller) => {
|
|
@@ -34,7 +34,7 @@ export declare function newSessionButton(): object;
|
|
|
34
34
|
/**
|
|
35
35
|
* Create a CardKit 2.0 Compact button for any runCompact-capable runner
|
|
36
36
|
* (codex/kimi/opencode/pi/claude,鸭子类型 `'runCompact' in runner` 探测)。
|
|
37
|
-
* Triggers the compact flow via the
|
|
37
|
+
* Triggers the compact flow via the compact callback(handler 按
|
|
38
38
|
* runId 解析 agentKind,claude 走 stream-json 内建 /compact)。
|
|
39
39
|
*/
|
|
40
40
|
export declare function compactButton(runId: string): object;
|
package/dist/card/card-shared.js
CHANGED
|
@@ -84,11 +84,11 @@ export function newSessionButton() {
|
|
|
84
84
|
/**
|
|
85
85
|
* Create a CardKit 2.0 Compact button for any runCompact-capable runner
|
|
86
86
|
* (codex/kimi/opencode/pi/claude,鸭子类型 `'runCompact' in runner` 探测)。
|
|
87
|
-
* Triggers the compact flow via the
|
|
87
|
+
* Triggers the compact flow via the compact callback(handler 按
|
|
88
88
|
* runId 解析 agentKind,claude 走 stream-json 内建 /compact)。
|
|
89
89
|
*/
|
|
90
90
|
export function compactButton(runId) {
|
|
91
|
-
return cardButton('🗜 Compact', { cmd: '
|
|
91
|
+
return cardButton('🗜 Compact', { cmd: 'compact', runId }, { type: 'primary' });
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* Create a CardKit 2.0 Compact button for resume cards (auto-resume / `/resume <id>`).
|
|
@@ -36,7 +36,7 @@ export class RunCardSession extends CardSession {
|
|
|
36
36
|
async push(event) {
|
|
37
37
|
// state 每事件立即 reduce(始终最新),但 updateCard 延迟到合批窗口末尾。
|
|
38
38
|
// 窗口内多次 push 复用同一 flushTimer,只 render + controller.update 一次
|
|
39
|
-
//
|
|
39
|
+
// push 立即 resolve(fire-and-forget render)—— bridge 串行
|
|
40
40
|
// await 不被 render 阻塞,循环快速灌入事件,多个事件落进同一窗口被合并。
|
|
41
41
|
//
|
|
42
42
|
// 首 push 也走窗口(无 immediate-first-flush):start() 已发初始卡(streaming
|
|
@@ -55,7 +55,7 @@ export class RunCardSession extends CardSession {
|
|
|
55
55
|
this.cancelPendingFlush();
|
|
56
56
|
// 若有 in-flight flush 正在 await updateCard,必须等它完成后再发终态 patch。
|
|
57
57
|
// 否则两条并发 controller.update 无 FIFO 保证,in-flight 的 pre-terminal
|
|
58
|
-
// patch 可能在终态 patch 之后 resolve → 用户看到"思考中"
|
|
58
|
+
// patch 可能在终态 patch 之后 resolve → 用户看到"思考中"终帧。
|
|
59
59
|
// await 保证顺序:pre-terminal 先落地 → terminal 后落地 → terminal 胜出。
|
|
60
60
|
if (this.flushP)
|
|
61
61
|
await this.flushP;
|
|
@@ -37,7 +37,7 @@ type BlockGroup = {
|
|
|
37
37
|
diff?: string;
|
|
38
38
|
timestamp?: string;
|
|
39
39
|
};
|
|
40
|
-
/** 每个块的截断后内容(thinking/plan/text
|
|
40
|
+
/** 每个块的截断后内容(thinking/plan/text),测量与渲染共用(建议项)。 */
|
|
41
41
|
type GroupContentPrepared = Map<BlockGroup, string>;
|
|
42
42
|
/** 导出供测试断言估算精度(估算 ≈ 实际渲染字节,见 tests/anchor/run-card/run-card.test.ts)。 */
|
|
43
43
|
export declare function estimateCardBytes(state: RunState, options?: RunCardRenderOptions, shared?: {
|
|
@@ -3,7 +3,7 @@ import { collapsibleMarkdownPanel, markdownDiv } from './collapsible.js';
|
|
|
3
3
|
import { toolBodyMd, toolHeaderText } from './tool-render.js';
|
|
4
4
|
import { truncateUtf8, truncateMarkdownTables, CARD_BUDGET_BYTES } from './text-truncate.js';
|
|
5
5
|
import { formatTimestamp } from './time.js';
|
|
6
|
-
import { formatUsageStats } from '../router/
|
|
6
|
+
import { formatUsageStats } from '../router/usage-format.js';
|
|
7
7
|
import { renderApprovalArea } from './approval-render.js';
|
|
8
8
|
const REASONING_BYTES = 4_500;
|
|
9
9
|
const TEXT_BYTES = 10_000;
|
|
@@ -16,7 +16,7 @@ const EXTREME_TOOL_KEEP = 1; // Extreme: keep last 1 tool panel
|
|
|
16
16
|
// 影子测量:估算 = 精确复刻 normal 路径将要渲染的 JSON 字节。面板外壳、statusRow、
|
|
17
17
|
// summary、header、按钮全部实测(measureJson),块内容经与渲染相同的变换
|
|
18
18
|
// (truncateUtf8 截断 + markdownDiv 的 escapeMarkdown + JSON.stringify)精确测量,
|
|
19
|
-
//
|
|
19
|
+
// 不依赖任何转义因子或拍脑袋常数(第二轮:CJK/ASCII 转义双向精确)。
|
|
20
20
|
const DEGRADED_THRESHOLD = 24_000; // 估算低于此值走正常路径(留 4KB 裕度,相对 CARD_BUDGET_BYTES=28000);否则直接 degraded。调整时同步评估裕度是否仍覆盖估算偏差
|
|
21
21
|
/** 精确测量对象经 JSON.stringify 后的 UTF-8 字节数。 */
|
|
22
22
|
function measureJson(obj) {
|
|
@@ -275,7 +275,7 @@ function actionButtonList(state, options) {
|
|
|
275
275
|
actionButtons.push(newSessionButton());
|
|
276
276
|
return actionButtons;
|
|
277
277
|
}
|
|
278
|
-
/** Bottom action row: spacer + column_set of actionButtonList (
|
|
278
|
+
/** Bottom action row: spacer + column_set of actionButtonList (估算与渲染共用)。 */
|
|
279
279
|
function actionRow(state, options) {
|
|
280
280
|
const actionButtons = actionButtonList(state, options);
|
|
281
281
|
if (actionButtons.length === 0)
|
|
@@ -293,7 +293,7 @@ function actionRow(state, options) {
|
|
|
293
293
|
];
|
|
294
294
|
}
|
|
295
295
|
/** 审批区位于 body 最底部(底部操作行之后):待审批时决策按钮不遮挡内容流。
|
|
296
|
-
* 例外:skeleton 兜底路径中 approvalArea 在 actionRow
|
|
296
|
+
* 例外:skeleton 兜底路径中 approvalArea 在 actionRow 之前(信息保真),
|
|
297
297
|
* 保证极端降级时审批入口与 stop/new-session 按钮同时可见。 */
|
|
298
298
|
function approvalArea(state) {
|
|
299
299
|
const elements = [];
|
|
@@ -306,7 +306,7 @@ function approvalArea(state) {
|
|
|
306
306
|
}
|
|
307
307
|
return elements;
|
|
308
308
|
}
|
|
309
|
-
/** 底部操作行之前的内容区提示:被 MAX_BLOCKS
|
|
309
|
+
/** 底部操作行之前的内容区提示:被 MAX_BLOCKS 截掉的早期块计数(信息保真)。 */
|
|
310
310
|
function omittedBlocksHint(state) {
|
|
311
311
|
return state.omittedBlocks !== undefined && state.omittedBlocks > 0
|
|
312
312
|
? [markdownDiv(`_💡 已省略 ${state.omittedBlocks} 个早期步骤_`)]
|
|
@@ -318,8 +318,8 @@ function assembleRunCard(state, options, elements) {
|
|
|
318
318
|
schema: '2.0',
|
|
319
319
|
config: { wide_screen_mode: true, update_multi: true },
|
|
320
320
|
header: {
|
|
321
|
-
template:
|
|
322
|
-
title: { content:
|
|
321
|
+
template: headerTemplate(state),
|
|
322
|
+
title: { content: headerTitle(state, options), tag: 'plain_text' },
|
|
323
323
|
},
|
|
324
324
|
body: { elements },
|
|
325
325
|
};
|
|
@@ -346,7 +346,7 @@ function buildFallbackElements(state, options, tier) {
|
|
|
346
346
|
if (toolsOmitted > 0) {
|
|
347
347
|
elements.push(markdownDiv(`_💡 另外 ${toolsOmitted} 个工具调用已省略_`));
|
|
348
348
|
}
|
|
349
|
-
//
|
|
349
|
+
// use object references (like the extreme path) instead of timestamps.
|
|
350
350
|
// RunBlock.timestamp has millisecond precision; ≥2 thinking blocks sharing a
|
|
351
351
|
// timestamp collapse to one Set entry, so `has(block.timestamp)` lets ALL
|
|
352
352
|
// same-timestamp blocks (including ones meant to be omitted) pass through —
|
|
@@ -364,7 +364,7 @@ function buildFallbackElements(state, options, tier) {
|
|
|
364
364
|
}
|
|
365
365
|
return true; // keep all non-thinking, non-tool blocks
|
|
366
366
|
});
|
|
367
|
-
// 信息保真
|
|
367
|
+
// 信息保真 plan/file_change 块在降级路径不渲染内容(正常路径已可见,
|
|
368
368
|
// 降级预算紧张),但必须计数留痕,禁止静默丢弃。
|
|
369
369
|
// 计数在渲染前完成,提示与 thinking/tool 省略提示一并置于卡片顶部——不能等
|
|
370
370
|
// 内容循环结束再追加,否则提示会落在最后一条输出之后,打乱「输出收尾」观感。
|
|
@@ -467,7 +467,7 @@ function buildSkeletonElements(state, options) {
|
|
|
467
467
|
elements.push(markdownDiv('_⚠️ 输出过大且含大量转义字符,已省略全部内容以避免超限;完整内容请查日志_'));
|
|
468
468
|
// Summary (token stats etc.) — static, bounded size
|
|
469
469
|
elements.push(...buildSummaryContent(state));
|
|
470
|
-
// 信息保真
|
|
470
|
+
// 信息保真 skeleton 也渲染审批区——极端兜底不丢审批入口
|
|
471
471
|
//(待审批被静默吞掉 = 用户永远看不到审批请求)。
|
|
472
472
|
elements.push(...approvalArea(state));
|
|
473
473
|
// Bottom action row: stop (if running/finalizing) + compact (if applicable) + new session (always).
|
|
@@ -514,7 +514,7 @@ function bucketThinkingAndTool(blocks) {
|
|
|
514
514
|
* 到 degraded(安全网不丢)。
|
|
515
515
|
*/
|
|
516
516
|
/**
|
|
517
|
-
*
|
|
517
|
+
* 镜像对单源:thinking/plan/file_change 三个 collapsible 面板组的
|
|
518
518
|
* { title, expanded, border, content } 描述,估算(measurePanelBytes)与渲染
|
|
519
519
|
* (collapsibleMarkdownPanel)共用——此前同一套标题/opIcon/内容模板写两遍。
|
|
520
520
|
* text(renderTextBlock)与 tool(renderTool)形态特殊,由调用方各自处理;
|
|
@@ -552,19 +552,19 @@ function describePanelGroup(group, prepared) {
|
|
|
552
552
|
/** 导出供测试断言估算精度(估算 ≈ 实际渲染字节,见 tests/anchor/run-card/run-card.test.ts)。 */
|
|
553
553
|
export function estimateCardBytes(state, options = {}, shared) {
|
|
554
554
|
const finalized = state.terminal !== 'running';
|
|
555
|
-
//
|
|
555
|
+
// renderRunCard 传入共享 groups/prepared 时直接复用(截断只做一次);
|
|
556
556
|
// 独立调用(测试/预算探针)时自建,行为与原先一致。
|
|
557
557
|
const groups = shared?.groups ?? groupBlocks(state.blocks);
|
|
558
558
|
const prepared = shared?.prepared ?? prepareGroupContent(groups);
|
|
559
559
|
// 卡片外壳直接实测 assembleRunCard 空元素产物(schema/config/header/body 结构
|
|
560
|
-
//
|
|
560
|
+
// 与正式渲染完全一致);status/summary/操作行同样实测渲染结构。
|
|
561
561
|
// 注:审批区(approvalArea)不参与估算——待审批通常在途且体积小,超预算由
|
|
562
562
|
// renderRunCard 的 stringify 兜底捕获。
|
|
563
563
|
let total = measureJson(assembleRunCard(state, options, [])) +
|
|
564
564
|
measureJson(statusRow(state)) +
|
|
565
565
|
measureJson(buildSummaryContent(state, { includeNotices: false })) +
|
|
566
566
|
measureJson(actionRow(state, options));
|
|
567
|
-
// 块内容:与 buildChronologicalContent 同源(describePanelGroup
|
|
567
|
+
// 块内容:与 buildChronologicalContent 同源(describePanelGroup 单源)
|
|
568
568
|
let renderedAny = false;
|
|
569
569
|
for (const group of groups) {
|
|
570
570
|
if (group.kind === 'tool') {
|
|
@@ -620,7 +620,7 @@ function measurePanelBytes(title, expanded, border, content) {
|
|
|
620
620
|
*/
|
|
621
621
|
export function renderRunCard(state, options = {}) {
|
|
622
622
|
// 先估后建:用廉价估算预测是否超 28KB 预算,明显超预算直接跳过完整卡构建走
|
|
623
|
-
// degraded。
|
|
623
|
+
// degraded。groups/prepared 只算一次,测量与正式渲染共用同一份截断结果,
|
|
624
624
|
// 避免影子测量 + 正式渲染对每个超限块双倍截断。
|
|
625
625
|
const groups = groupBlocks(state.blocks);
|
|
626
626
|
const prepared = prepareGroupContent(groups);
|
|
@@ -680,9 +680,9 @@ function buildChronologicalContent(state, prepared, groups) {
|
|
|
680
680
|
const elements = [];
|
|
681
681
|
// finalized = 非 running(含 finalizing:主结果已出,thinking 折叠)
|
|
682
682
|
const finalized = state.terminal !== 'running';
|
|
683
|
-
//
|
|
683
|
+
// renderRunCard 传入同一 groups 数组时直接复用(prepared 的键是组对象
|
|
684
684
|
// 引用,重建数组会让 prepared.get 永远 miss,退化为二次截断)。
|
|
685
|
-
//
|
|
685
|
+
// 面板组描述经 describePanelGroup 与估算共享同一份模板。
|
|
686
686
|
// notices 作为普通消息按到达时间插入内容流(有内容时不再沉到 summary)。
|
|
687
687
|
const contentItems = mergeNoticesIntoContent(groups, state.notices);
|
|
688
688
|
for (const item of contentItems) {
|
|
@@ -762,7 +762,7 @@ function buildSummaryContent(state, options = {}) {
|
|
|
762
762
|
// 压缩(operationKind='compaction')不会返回 agent 正文——引擎只压缩上下文
|
|
763
763
|
// 窗口,空内容属正常,不能沿用普通 run 的「(未返回内容)」异常信号
|
|
764
764
|
// (2026-09 用户反馈)。所有会压缩的 agent(codex/claude/kimi/opencode/pi)
|
|
765
|
-
// 都经
|
|
765
|
+
// 都经 streamCompact 走这条共享渲染路径,一处覆盖全部。
|
|
766
766
|
const empty = hasContent
|
|
767
767
|
? ''
|
|
768
768
|
: state.operationKind === 'compaction'
|
|
@@ -802,9 +802,9 @@ function buildDurationInfo(state) {
|
|
|
802
802
|
// 与标题一致:审批等待期间状态行显示「等待审批中」,而不是「工具调用中」。
|
|
803
803
|
if (hasPendingApproval(state))
|
|
804
804
|
return '✋ 等待审批中';
|
|
805
|
-
return
|
|
805
|
+
return footerText(state.footer);
|
|
806
806
|
}
|
|
807
|
-
function
|
|
807
|
+
function footerText(footer) {
|
|
808
808
|
if (footer === 'tool_running')
|
|
809
809
|
return '🧰 工具调用中';
|
|
810
810
|
if (footer === 'streaming')
|
|
@@ -816,7 +816,7 @@ function statusTagLabel(terminal) {
|
|
|
816
816
|
return terminalToLabel(terminal);
|
|
817
817
|
}
|
|
818
818
|
/** CardKit 2.0 header title — agent-aware via options.agentKind. */
|
|
819
|
-
function
|
|
819
|
+
function headerTitle(state, options = {}) {
|
|
820
820
|
const agent = agentDisplayName(options.agentKind ?? 'claude');
|
|
821
821
|
if (state.terminal === 'done')
|
|
822
822
|
return `✅ ${agent} · 已完成`;
|
|
@@ -845,7 +845,7 @@ function hasPendingApproval(state) {
|
|
|
845
845
|
return (state.approvals ?? []).some((a) => !a.expired);
|
|
846
846
|
}
|
|
847
847
|
/** CardKit 2.0 header template color */
|
|
848
|
-
function
|
|
848
|
+
function headerTemplate(state) {
|
|
849
849
|
return terminalToColor(state.terminal);
|
|
850
850
|
}
|
|
851
851
|
//# sourceMappingURL=run-renderer.js.map
|
package/dist/card/run-state.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface ToolEntry {
|
|
|
9
9
|
name: string;
|
|
10
10
|
input: unknown;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* cached parse of `input` (the truncated string) into a record, so
|
|
13
13
|
* `tool-render.ts`'s `asRecord` does not re-`JSON.parse` on every render.
|
|
14
14
|
* Computed once at store time in `reduceAssistantEvent` from the SAME
|
|
15
15
|
* truncated string that the old per-render `asRecord` parsed — so a
|
|
@@ -121,7 +121,7 @@ export interface RunState {
|
|
|
121
121
|
/** 压缩前上下文水位(codex compact 卡展示「压缩前 X → 压缩后 Y」)。 */
|
|
122
122
|
compactPreContextLength?: number;
|
|
123
123
|
/**
|
|
124
|
-
* 待审批请求列表(app-server
|
|
124
|
+
* 待审批请求列表(app-server 模式)。同一 turn 内并发多个审批
|
|
125
125
|
* 时全部渲染,避免后到者顶掉先到者的按钮(单槽会丢 UI,只能等超时 cancel)。
|
|
126
126
|
*/
|
|
127
127
|
approvals?: Array<{
|
package/dist/card/run-state.js
CHANGED
|
@@ -382,7 +382,7 @@ function reduceAssistantEvent(state, event) {
|
|
|
382
382
|
};
|
|
383
383
|
}
|
|
384
384
|
else {
|
|
385
|
-
//
|
|
385
|
+
// parse the truncated stored string ONCE here (not on every render)
|
|
386
386
|
// and cache the result on `parsedInput`. tool-render's asRecord then hits
|
|
387
387
|
// the object branch with zero parsing. The parse uses the SAME truncated
|
|
388
388
|
// string as the old per-render parse, so truncation-broken JSON still
|
|
@@ -450,7 +450,7 @@ function mergeToolUse(existing, incoming) {
|
|
|
450
450
|
};
|
|
451
451
|
}
|
|
452
452
|
/** Handle tool_result content blocks (user message with tool results).
|
|
453
|
-
*
|
|
453
|
+
* rebuild ONLY the block matching `tool_use_id`, copying every other
|
|
454
454
|
* block by reference. The old `.map()` recreated all block objects per
|
|
455
455
|
* tool_result (O(N) allocations on the run-card hot path). Footer still
|
|
456
456
|
* advances to 'streaming' on every content block (parity with old behavior);
|
|
@@ -605,7 +605,7 @@ function stringifyUnknown(value) {
|
|
|
605
605
|
}
|
|
606
606
|
}
|
|
607
607
|
/**
|
|
608
|
-
*
|
|
608
|
+
* parse a (possibly truncated) string into a record, mirroring what
|
|
609
609
|
* `tool-render.ts`'s `asRecord` did on every render. Returns `null` when the
|
|
610
610
|
* string is empty, non-JSON, or parses to a non-object — so a truncation-broken
|
|
611
611
|
* JSON yields `null` exactly as the old per-render parse did. Computed once at
|
|
@@ -20,7 +20,7 @@ export declare function toolHeaderText(tool: ToolEntry): string;
|
|
|
20
20
|
/**
|
|
21
21
|
* Structured body markdown for a tool call. Renders input fields by tool name
|
|
22
22
|
* (Bash → command, Read/Edit/Write → file_path, etc.) and output in a code
|
|
23
|
-
* block. An explicit `toolHint` (declared by the runner, 信息保真
|
|
23
|
+
* block. An explicit `toolHint` (declared by the runner, 信息保真) selects
|
|
24
24
|
* the same rendering by family instead of name. There is no raw-JSON fallback
|
|
25
25
|
* for unknown tools: `default` returns '' and unknown tools only surface their
|
|
26
26
|
* args through the panel header's `summarizeInput` fallback.
|
package/dist/card/tool-render.js
CHANGED
|
@@ -29,13 +29,13 @@ const BODY_TOTAL_MAX = 2500;
|
|
|
29
29
|
*/
|
|
30
30
|
export function toolHeaderText(tool) {
|
|
31
31
|
const icon = tool.status === 'ok' ? '✅' : tool.status === 'error' ? '❌' : '⏳';
|
|
32
|
-
//
|
|
32
|
+
// use the cached parsed record when available (avoids per-render parse).
|
|
33
33
|
const input = tool.parsedInput !== undefined ? tool.parsedInput : tool.input;
|
|
34
34
|
const summary = summarizeInput(tool.name, input);
|
|
35
|
-
// 信息保真
|
|
35
|
+
// 信息保真 ACP kind 映射后 name 与原始 title 不同时,title 以
|
|
36
36
|
// ` — {summary}` 追加在标题末尾(截断沿用 HEADER_SUMMARY_MAX)。
|
|
37
37
|
// 用 truncate(suffix 为空)而非裸 slice:裸 slice 按 UTF-16 码元切,
|
|
38
|
-
// 切点落在 emoji
|
|
38
|
+
// 切点落在 emoji 代理对中间会留下孤立代理项(同族)。
|
|
39
39
|
const blockSummary = tool.summary
|
|
40
40
|
? truncate(tool.summary.replace(/\s+/g, ' ').trim(), HEADER_SUMMARY_MAX, { suffix: '' })
|
|
41
41
|
: '';
|
|
@@ -51,7 +51,7 @@ export function toolHeaderText(tool) {
|
|
|
51
51
|
/**
|
|
52
52
|
* Structured body markdown for a tool call. Renders input fields by tool name
|
|
53
53
|
* (Bash → command, Read/Edit/Write → file_path, etc.) and output in a code
|
|
54
|
-
* block. An explicit `toolHint` (declared by the runner, 信息保真
|
|
54
|
+
* block. An explicit `toolHint` (declared by the runner, 信息保真) selects
|
|
55
55
|
* the same rendering by family instead of name. There is no raw-JSON fallback
|
|
56
56
|
* for unknown tools: `default` returns '' and unknown tools only surface their
|
|
57
57
|
* args through the panel header's `summarizeInput` fallback.
|
|
@@ -156,13 +156,13 @@ function renderWebSearchInput(str) {
|
|
|
156
156
|
return str('query') ? `**Query** \`${truncate(str('query'), BODY_FIELD_MAX)}\`` : '';
|
|
157
157
|
}
|
|
158
158
|
function renderInput(tool) {
|
|
159
|
-
//
|
|
159
|
+
// use the cached parsed record when available (avoids per-render parse).
|
|
160
160
|
const input = tool.parsedInput !== undefined ? tool.parsedInput : tool.input;
|
|
161
161
|
const rec = asRecord(input);
|
|
162
162
|
if (!rec)
|
|
163
163
|
return '';
|
|
164
164
|
const str = (k) => (typeof rec[k] === 'string' ? rec[k] : '');
|
|
165
|
-
// 信息保真
|
|
165
|
+
// 信息保真 hint 优先(runner 自愿声明,只消费不推断);缺失时与现状
|
|
166
166
|
// 完全一致。hint 分支与 name case 共用同一渲染函数,无复制粘贴。
|
|
167
167
|
switch (tool.toolHint) {
|
|
168
168
|
case 'shell':
|
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* CLI 引导层(bootstrap):在 import 应用模块图之前决定运行时(bun/node)并拉起它。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 1. 时序:preflight(Node 版本守卫、-v/-h/--advance-help)必须在 import 应用
|
|
5
|
+
*XX * 缺一不可:
|
|
6
|
+
* 1. 时序:preflight(Node 版本守卫、-v/-h/--advanced-help)必须在 import 应用
|
|
8
7
|
* 模块图之前跑完——dist/cli.js 刻意不使用 ES2020+ 语法以便在 node 12 上仍
|
|
9
8
|
* 可被解析,而 dist/index.js 是 ES2022;先 import platform/spawn 就等于先把
|
|
10
9
|
* 应用模块图拖进来,守卫当场失效(报错堆栈全落在 Node 内部)。
|
|
@@ -20,7 +19,7 @@ import fs from 'node:fs';
|
|
|
20
19
|
import path from 'node:path';
|
|
21
20
|
import { spawn, spawnSync } from 'node:child_process';
|
|
22
21
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
23
|
-
import {
|
|
22
|
+
import { printAdvancedHelp, printHelp, printVersion } from './config/dir.js';
|
|
24
23
|
const entryUrl = new URL('./index.js', import.meta.url);
|
|
25
24
|
const entry = fileURLToPath(entryUrl);
|
|
26
25
|
/**
|
|
@@ -49,8 +48,8 @@ export function handlePreflight(args, nodeVersion = process.versions.node) {
|
|
|
49
48
|
printHelp();
|
|
50
49
|
return 0;
|
|
51
50
|
}
|
|
52
|
-
if (arg === '--
|
|
53
|
-
|
|
51
|
+
if (arg === '--advanced-help') {
|
|
52
|
+
printAdvancedHelp();
|
|
54
53
|
return 0;
|
|
55
54
|
}
|
|
56
55
|
}
|