lark-remote 0.4.5 → 0.5.1
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 +34 -0
- package/dist/bridge/approval-coordinator.d.ts +1 -1
- package/dist/bridge/approval-coordinator.js +3 -3
- package/dist/bridge/inbound-media.js +10 -7
- package/dist/bridge/index.d.ts +55 -17
- package/dist/bridge/index.js +145 -74
- package/dist/bridge/queue-manager.d.ts +71 -20
- package/dist/bridge/queue-manager.js +139 -57
- 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 +1 -1
- package/dist/card/card-session.d.ts +4 -4
- package/dist/card/card-session.js +6 -6
- package/dist/card/run-card-session.js +2 -2
- package/dist/card/run-renderer.d.ts +1 -1
- package/dist/card/run-renderer.js +14 -14
- 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 +2 -1
- package/dist/clone.d.ts +5 -3
- package/dist/clone.js +8 -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.js +5 -2
- 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/connector/index.d.ts +5 -5
- package/dist/connector/index.js +24 -11
- 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/index.js +23 -12
- package/dist/instance-lock.js +4 -3
- 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 +6 -2
- package/dist/platform/agent-stopper.d.ts +1 -1
- 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 +1 -1
- package/dist/platform/terminator-win32.js +2 -2
- 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/config/codex.d.ts +1 -1
- package/dist/router/config/codex.js +2 -2
- package/dist/router/config/opencode.js +1 -1
- package/dist/router/index.d.ts +65 -16
- package/dist/router/index.js +141 -47
- package/dist/router/order-exec-dispatch.js +2 -2
- package/dist/runner/bash/runner.d.ts +2 -2
- package/dist/runner/bash/runner.js +6 -6
- package/dist/runner/claude/runner.js +1 -1
- package/dist/runner/claude/session.d.ts +2 -2
- package/dist/runner/claude/session.js +14 -14
- package/dist/runner/codex/app-server/runner.d.ts +28 -0
- package/dist/runner/codex/app-server/runner.js +57 -4
- 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/acp-approval.d.ts +2 -2
- package/dist/runner/common/acp/acp-approval.js +3 -3
- package/dist/runner/common/acp/base-acp-runner.js +1 -1
- 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 +1 -1
- package/dist/runner/common/connection-based-runner.js +2 -2
- 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 +1 -1
- package/dist/runner/common/jsonrpc/connection-manager.js +1 -1
- package/dist/runner/common/jsonrpc/transport.d.ts +1 -1
- package/dist/runner/common/jsonrpc/transport.js +2 -2
- package/dist/runner/common/spawning-runner.d.ts +21 -8
- package/dist/runner/common/spawning-runner.js +41 -15
- package/dist/runner/dsh/runner.js +2 -2
- package/dist/runner/kimi/acp/runner.d.ts +3 -3
- package/dist/runner/kimi/acp/runner.js +9 -9
- package/dist/runner/kimi/acp/translator.d.ts +2 -2
- package/dist/runner/kimi/acp/translator.js +4 -4
- package/dist/runner/opencode/acp/runner.d.ts +2 -2
- package/dist/runner/opencode/acp/runner.js +3 -3
- package/dist/runner/opencode/acp/translator.js +1 -1
- package/dist/runner/pi/rpc/runner.js +2 -2
- package/dist/runner/pi/rpc/translator.d.ts +1 -1
- package/dist/runner/pi/rpc/translator.js +4 -4
- package/dist/runner/types.d.ts +11 -2
- package/dist/runner/types.js +12 -1
- package/dist/session/claude/session-index.d.ts +12 -0
- package/dist/session/claude/session-index.js +20 -5
- 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 +12 -12
- 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.js +2 -2
- package/dist/session/kimi/sessions.d.ts +2 -2
- package/dist/session/kimi/sessions.js +11 -11
- package/dist/session/opencode/sessions.d.ts +3 -3
- package/dist/session/opencode/sessions.js +12 -10
- package/dist/session/pi/sessions.js +13 -12
- package/dist/session/session-store.d.ts +1 -1
- package/dist/session/session-store.js +1 -1
- package/package.json +1 -1
|
@@ -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) {
|
|
@@ -78,7 +78,7 @@ function assembleCard(state, 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) {
|
|
@@ -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) => {
|
|
@@ -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?: {
|
|
@@ -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} 个早期步骤_`)]
|
|
@@ -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) {
|
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,7 +2,8 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* CLI 引导层(bootstrap):在 import 应用模块图之前决定运行时(bun/node)并拉起它。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* **这是全仓唯一被认可的 spawn 收口例外**(即 AGENTS.md「子进程 spawn 只走
|
|
6
|
+
* platform/spawn.ts」红线的显式豁免)。三个理由缺一不可:
|
|
6
7
|
* 1. 时序:preflight(Node 版本守卫、-v/-h/--advanced-help)必须在 import 应用
|
|
7
8
|
* 模块图之前跑完——dist/cli.js 刻意不使用 ES2020+ 语法以便在 node 12 上仍
|
|
8
9
|
* 可被解析,而 dist/index.js 是 ES2022;先 import platform/spawn 就等于先把
|
package/dist/clone.d.ts
CHANGED
|
@@ -25,7 +25,8 @@ import { type QRCodeInfo, type RegisterAppResult } from '@larksuite/channel';
|
|
|
25
25
|
type CloneState = 'idle' | 'awaiting_scan' | 'finalizing';
|
|
26
26
|
/**
|
|
27
27
|
* 校验用户指定的分身名字:路径分隔符、以 . 开头、尾点/尾空格(win32 会静默
|
|
28
|
-
* 吞掉)、win32
|
|
28
|
+
* 吞掉)、win32 非法字符(`<>:"|?*`,NTFS/Win32 API 拒绝)、win32 保留设备名
|
|
29
|
+
* 一律拒绝。
|
|
29
30
|
*/
|
|
30
31
|
export declare function isValidCloneName(name: string): boolean;
|
|
31
32
|
/** 随机后缀:2 位数字 + 2 位小写字母/数字,如 `37ab`。 */
|
|
@@ -126,8 +127,9 @@ export declare class CloneSession {
|
|
|
126
127
|
private readOldOwnerId;
|
|
127
128
|
/**
|
|
128
129
|
* 写配置失败时清理半成品目录。守卫:只删内容全部是本次产物
|
|
129
|
-
* (config.yaml / startup-contact.json 及其
|
|
130
|
-
* 文件时保留现场不动。
|
|
130
|
+
* (config.yaml / startup-contact.json 及其 tmp)的目录,混入其他
|
|
131
|
+
* 文件时保留现场不动。tmp 形态两种都认:atomic-write 现行命名
|
|
132
|
+
* (.{name}.tmp-{pid}-{ts}-{rand})与旧版固定 `.tmp`(升级瞬间崩溃的残留)。
|
|
131
133
|
*/
|
|
132
134
|
private cleanupPartialDir;
|
|
133
135
|
}
|
package/dist/clone.js
CHANGED
|
@@ -24,13 +24,16 @@ const WIN_RESERVED_NAMES = new Set([
|
|
|
24
24
|
]);
|
|
25
25
|
/**
|
|
26
26
|
* 校验用户指定的分身名字:路径分隔符、以 . 开头、尾点/尾空格(win32 会静默
|
|
27
|
-
* 吞掉)、win32
|
|
27
|
+
* 吞掉)、win32 非法字符(`<>:"|?*`,NTFS/Win32 API 拒绝)、win32 保留设备名
|
|
28
|
+
* 一律拒绝。
|
|
28
29
|
*/
|
|
29
30
|
export function isValidCloneName(name) {
|
|
30
31
|
if (!name || name.includes('/') || name.includes('\\') || name.startsWith('.'))
|
|
31
32
|
return false;
|
|
32
33
|
if (/[\s.]$/.test(name))
|
|
33
34
|
return false;
|
|
35
|
+
if (/[<>:"|?*]/.test(name))
|
|
36
|
+
return false;
|
|
34
37
|
if (WIN_RESERVED_NAMES.has(name.toLowerCase()))
|
|
35
38
|
return false;
|
|
36
39
|
return true;
|
|
@@ -393,12 +396,13 @@ export class CloneSession {
|
|
|
393
396
|
}
|
|
394
397
|
/**
|
|
395
398
|
* 写配置失败时清理半成品目录。守卫:只删内容全部是本次产物
|
|
396
|
-
* (config.yaml / startup-contact.json 及其
|
|
397
|
-
* 文件时保留现场不动。
|
|
399
|
+
* (config.yaml / startup-contact.json 及其 tmp)的目录,混入其他
|
|
400
|
+
* 文件时保留现场不动。tmp 形态两种都认:atomic-write 现行命名
|
|
401
|
+
* (.{name}.tmp-{pid}-{ts}-{rand})与旧版固定 `.tmp`(升级瞬间崩溃的残留)。
|
|
398
402
|
*/
|
|
399
403
|
cleanupPartialDir(targetDir) {
|
|
400
404
|
try {
|
|
401
|
-
const allowed = /^(config\.yaml|startup-contact\.json)(\.tmp)
|
|
405
|
+
const allowed = /^(config\.yaml|startup-contact\.json)(\.tmp)?$|^\.(config\.yaml|startup-contact\.json)\.tmp-\d+-\d+-[a-z0-9]+$/;
|
|
402
406
|
const entries = fs.readdirSync(targetDir);
|
|
403
407
|
if (!entries.every((e) => allowed.test(e))) {
|
|
404
408
|
getLogger().warn(`[clone] target dir has foreign entries, kept: ${targetDir}`);
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
export declare const DEFAULT_TRUNCATE_SUFFIX = "\u2026\uFF08\u5DF2\u622A\u65AD\uFF09";
|
|
12
12
|
/**
|
|
13
13
|
* Max byte budget for a single session `tool_result` event's content when
|
|
14
|
-
* replaying an opencode session (
|
|
14
|
+
* replaying an opencode session (pre-fold). Pre-folding here bounds the
|
|
15
15
|
* in-memory `events[]` array and the intermediate card JSON so a single
|
|
16
16
|
* pathological tool_result never inflates the replay payload to megabytes.
|
|
17
17
|
*/
|
package/dist/common/truncate.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
export const DEFAULT_TRUNCATE_SUFFIX = '…(已截断)';
|
|
12
12
|
/**
|
|
13
13
|
* Max byte budget for a single session `tool_result` event's content when
|
|
14
|
-
* replaying an opencode session (
|
|
14
|
+
* replaying an opencode session (pre-fold). Pre-folding here bounds the
|
|
15
15
|
* in-memory `events[]` array and the intermediate card JSON so a single
|
|
16
16
|
* pathological tool_result never inflates the replay payload to megabytes.
|
|
17
17
|
*/
|
|
@@ -76,7 +76,7 @@ export function truncate(str, max, options) {
|
|
|
76
76
|
if (budget <= 0)
|
|
77
77
|
return suffix;
|
|
78
78
|
// Iterate by Unicode codepoint (for...of) so the cut never lands inside a
|
|
79
|
-
// surrogate pair (
|
|
79
|
+
// surrogate pair (must not emit a lone surrogate).
|
|
80
80
|
let end = 0;
|
|
81
81
|
for (const ch of s) {
|
|
82
82
|
if (end + ch.length > budget)
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Consolidates the per-reader memory caches that previously hand-rolled the
|
|
5
5
|
* same "mtime/TTL + entry cap" Map pattern (kimi/pi/opencode session readers).
|
|
6
6
|
* Semantics follow the kimi implementation:
|
|
7
|
-
* - TTL is measured from the cache-write time (
|
|
7
|
+
* - TTL is measured from the cache-write time (defect 2), not key mtime.
|
|
8
8
|
* Note: ttlMs = 0 effectively disables caching — `Date.now() - at >= 0` is
|
|
9
9
|
* always true, so every entry expires immediately.
|
|
10
10
|
* - A hit refreshes recency (LRU); eviction removes the least recently
|
|
11
|
-
* inserted/used entry past `maxEntries` (
|
|
11
|
+
* inserted/used entry past `maxEntries` (defect 1: unbounded growth).
|
|
12
12
|
* The old pi implementation did NOT re-insert on hit (FIFO eviction); the
|
|
13
13
|
* eviction order for pi therefore changes from FIFO to LRU here.
|
|
14
14
|
*/
|
package/dist/common/ttl-cache.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Consolidates the per-reader memory caches that previously hand-rolled the
|
|
5
5
|
* same "mtime/TTL + entry cap" Map pattern (kimi/pi/opencode session readers).
|
|
6
6
|
* Semantics follow the kimi implementation:
|
|
7
|
-
* - TTL is measured from the cache-write time (
|
|
7
|
+
* - TTL is measured from the cache-write time (defect 2), not key mtime.
|
|
8
8
|
* Note: ttlMs = 0 effectively disables caching — `Date.now() - at >= 0` is
|
|
9
9
|
* always true, so every entry expires immediately.
|
|
10
10
|
* - A hit refreshes recency (LRU); eviction removes the least recently
|
|
11
|
-
* inserted/used entry past `maxEntries` (
|
|
11
|
+
* inserted/used entry past `maxEntries` (defect 1: unbounded growth).
|
|
12
12
|
* The old pi implementation did NOT re-insert on hit (FIFO eviction); the
|
|
13
13
|
* eviction order for pi therefore changes from FIFO to LRU here.
|
|
14
14
|
*/
|
|
@@ -52,32 +52,32 @@ export interface BundledModelInfo {
|
|
|
52
52
|
* 依据:codex 运行时对"已配置但文件缺失/不可解析"的目录是硬错误
|
|
53
53
|
* (core/src/config/mod.rs load_model_catalog ?),绝不会回退内置目录;因此键存在即
|
|
54
54
|
* catalog 模式,文件缺失自然落入 `codex debug models` 失败路径 → 模型列表回退
|
|
55
|
-
* [currentModel]
|
|
55
|
+
* [currentModel]。
|
|
56
56
|
*/
|
|
57
57
|
export declare function isCodexCatalogMode(codexHome?: string): boolean;
|
|
58
58
|
/**
|
|
59
59
|
* 单一解析器:把 `codex debug models`(活动目录)或 `--bundled`(内置目录)的原始 JSON
|
|
60
|
-
*
|
|
60
|
+
* 输出解析为模型列表(去重)。过滤/排序镜像 codex:
|
|
61
61
|
* - show_in_picker = visibility == List(openai_models.rs ModelPreset::from);
|
|
62
62
|
* - API 模式(lark 用 API key 认证)下 codex filter_by_auth 过滤 supported_in_api=false;
|
|
63
63
|
* - 按 priority 升序(build_available_models)。
|
|
64
|
-
* 档位按目录声明**原样透传**(含 custom/none
|
|
64
|
+
* 档位按目录声明**原样透传**(含 custom/none),不按标准枚举过滤、不虚构兜底:
|
|
65
65
|
* 未声明档位 → 空列表(codex with_model 语义:len=0 时用声明 default,都没有则不发
|
|
66
|
-
* effort
|
|
66
|
+
* effort;)。空串档位/空串 default 被过滤(codex ReasoningEffort::from_str
|
|
67
67
|
* 对 "" 硬错误)。supported_in_api===true 过滤等价于 codex 的 chatgpt_mode ||
|
|
68
|
-
* supported_in_api:本项目以 API-key 模式运行 codex,chatgpt_mode 恒 false
|
|
68
|
+
* supported_in_api:本项目以 API-key 模式运行 codex,chatgpt_mode 恒 false。
|
|
69
69
|
*/
|
|
70
70
|
export declare function parseCodexModelsOutput(stdout: string): BundledModelInfo[];
|
|
71
71
|
/**
|
|
72
72
|
* 统一目录入口:catalog 模式(model_catalog_json 已声明,含声明退化 '')跑
|
|
73
73
|
* `debug models`(无 --bundled),否则(未声明或 config.toml 解析失败)跑
|
|
74
|
-
* `debug models --bundled
|
|
74
|
+
* `debug models --bundled`。注:codex 无参 `debug models` 在
|
|
75
75
|
* uses_codex_backend()/has_command_auth() 时会请求远端 /models(models-manager
|
|
76
76
|
* manager.rs / models_endpoint.rs);本项目以 API-key 模式运行(无 ChatGPT/命令
|
|
77
77
|
* 认证),结果与 bundled 一致,故非 catalog 用 --bundled(已文档化)。
|
|
78
78
|
* 缓存:键含 binary/home/mode/models.json mtime:size + config.toml mtime:size
|
|
79
|
-
*
|
|
80
|
-
*
|
|
79
|
+
* 成功结果 TTL 1h,失败/空结果短 TTL 负缓存;stat 异常时
|
|
80
|
+
* 指纹为空。
|
|
81
81
|
*
|
|
82
82
|
* 同步路径(卡片构建用):缓存命中直接返回;若有一个后台异步加载
|
|
83
83
|
* (`loadCodexCatalogModelsAsync` / 启动 warm)在途,则不阻塞事件循环、不重复
|
|
@@ -117,7 +117,7 @@ export declare function getReasoningEffortOptions(model: string, codexHome?: str
|
|
|
117
117
|
/**
|
|
118
118
|
* Get default reasoning effort for a model.
|
|
119
119
|
* 未声明/未知模型 → undefined(codex 语义:ModelPreset.default_reasoning_effort
|
|
120
|
-
* unwrap_or(ReasoningEffort::None),即不传 effort
|
|
120
|
+
* unwrap_or(ReasoningEffort::None),即不传 effort;)。
|
|
121
121
|
*/
|
|
122
122
|
export declare function getDefaultReasoningEffort(model: string, codexHome?: string): string | undefined;
|
|
123
123
|
interface LoadCodexConfigOpts {
|