lark-remote 0.5.12 → 0.5.14
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 -2
- package/README.en.md +1 -14
- package/README.md +1 -14
- package/dist/agent-kinds.d.ts +27 -0
- package/dist/agent-kinds.js +38 -0
- package/dist/bridge/approval-actions.d.ts +95 -0
- package/dist/bridge/approval-actions.js +104 -0
- package/dist/bridge/approval-coordinator.d.ts +1 -0
- package/dist/bridge/approval-coordinator.js +12 -24
- package/dist/bridge/final-usage.d.ts +8 -17
- package/dist/bridge/final-usage.js +1 -18
- package/dist/bridge/index.d.ts +52 -38
- package/dist/bridge/index.js +255 -433
- package/dist/bridge/queue-manager.d.ts +25 -1
- package/dist/bridge/queue-manager.js +179 -160
- package/dist/bridge/run-approval.d.ts +16 -0
- package/dist/bridge/run-approval.js +41 -0
- package/dist/bridge/run-usage.d.ts +32 -0
- package/dist/bridge/run-usage.js +87 -0
- package/dist/bridge/session-writeback.d.ts +19 -0
- package/dist/bridge/session-writeback.js +36 -0
- package/dist/card/approval-render.d.ts +3 -2
- package/dist/card/approval-render.js +3 -2
- package/dist/card/bash-card-session.js +2 -5
- package/dist/{router → card}/card-helpers.d.ts +7 -7
- package/dist/{router → card}/card-helpers.js +8 -8
- package/dist/card/card-session.d.ts +6 -2
- package/dist/card/card-session.js +28 -28
- package/dist/card/card-shared.d.ts +4 -4
- package/dist/card/card-shared.js +4 -10
- package/dist/card/collapsible.js +3 -2
- package/dist/card/final-answer-overflow.d.ts +1 -0
- package/dist/card/final-answer-overflow.js +46 -0
- package/dist/card/run-card-session.d.ts +2 -2
- package/dist/card/run-card-session.js +4 -9
- package/dist/card/run-renderer.d.ts +14 -0
- package/dist/card/run-renderer.js +126 -23
- package/dist/card/run-state.d.ts +40 -51
- package/dist/card/run-state.js +96 -34
- package/dist/card/usage-format.d.ts +30 -0
- package/dist/{router → card}/usage-format.js +3 -10
- package/dist/clone.js +6 -1
- package/dist/config/codex-config.js +4 -4
- package/dist/config/index.d.ts +18 -20
- package/dist/config/index.js +6 -20
- package/dist/config/pi-config.js +6 -4
- package/dist/connector/index.d.ts +2 -4
- package/dist/connector/index.js +7 -11
- package/dist/{runner/dsh → dsh}/auth.js +3 -4
- package/dist/dsh/home.d.ts +2 -0
- package/dist/dsh/home.js +8 -0
- package/dist/dsh/protocol.d.ts +9 -0
- package/dist/dsh/protocol.js +61 -0
- package/dist/inbound/turn-assembler.js +6 -0
- package/dist/index.js +25 -414
- package/dist/message-handlers.d.ts +26 -0
- package/dist/message-handlers.js +275 -0
- package/dist/model-catalog.d.ts +14 -0
- package/dist/model-catalog.js +25 -0
- package/dist/platform/path.d.ts +9 -0
- package/dist/platform/path.js +18 -0
- package/dist/router/active-run-usage.d.ts +4 -0
- package/dist/router/active-run-usage.js +12 -0
- package/dist/router/card-action-payload.d.ts +1 -1
- package/dist/router/card-action-payload.js +1 -1
- package/dist/router/commands/ls.d.ts +9 -0
- package/dist/router/commands/ls.js +243 -0
- package/dist/router/commands/order.d.ts +12 -0
- package/dist/router/commands/order.js +178 -0
- package/dist/router/commands/resume.d.ts +48 -0
- package/dist/router/commands/resume.js +246 -0
- package/dist/router/commands/ws.d.ts +15 -0
- package/dist/router/commands/ws.js +189 -0
- package/dist/router/config/claude.js +5 -4
- package/dist/router/config/codex.js +2 -6
- package/dist/router/config/common/render.d.ts +5 -1
- package/dist/router/config/common/render.js +6 -13
- package/dist/router/config/common/turn-idle.d.ts +2 -0
- package/dist/router/config/common/turn-idle.js +9 -0
- package/dist/router/config/dsh.d.ts +1 -1
- package/dist/router/config/index.d.ts +1 -1
- package/dist/router/config/kimi.js +2 -6
- package/dist/router/config/opencode.js +2 -6
- package/dist/router/config/types.d.ts +11 -3
- package/dist/router/index.d.ts +55 -33
- package/dist/router/index.js +233 -1376
- package/dist/router/paging.d.ts +13 -0
- package/dist/router/paging.js +20 -0
- package/dist/router/path-validation.d.ts +27 -0
- package/dist/router/path-validation.js +45 -0
- package/dist/runner/agent-choices-common.d.ts +1 -1
- package/dist/runner/claude/runner.d.ts +23 -6
- package/dist/runner/claude/runner.js +6 -20
- package/dist/runner/claude/session.js +1 -1
- package/dist/runner/codex/app-server/runner.d.ts +3 -1
- package/dist/runner/codex/app-server/translator.d.ts +13 -0
- package/dist/runner/codex/app-server/translator.js +114 -151
- package/dist/runner/common/acp/base-acp-runner.d.ts +3 -1
- package/dist/runner/common/acp/base-translator.d.ts +3 -8
- package/dist/runner/common/acp/base-translator.js +16 -7
- package/dist/runner/common/connection-based-runner.d.ts +3 -1
- package/dist/runner/common/jsonrpc/transport.js +17 -7
- package/dist/runner/common/spawning-runner.js +10 -4
- package/dist/runner/common/turn-started.d.ts +2 -0
- package/dist/runner/common/turn-started.js +10 -0
- package/dist/runner/dsh/client.d.ts +2 -10
- package/dist/runner/dsh/client.js +13 -220
- package/dist/runner/dsh/daemon.d.ts +0 -2
- package/dist/runner/dsh/daemon.js +9 -7
- package/dist/runner/dsh/errors.d.ts +5 -0
- package/dist/runner/dsh/errors.js +11 -0
- package/dist/runner/dsh/exit-cancel.d.ts +0 -2
- package/dist/runner/dsh/exit-cancel.js +2 -2
- package/dist/runner/dsh/inflight.d.ts +0 -2
- package/dist/runner/dsh/inflight.js +1 -1
- package/dist/runner/dsh/mux-stream.d.ts +26 -0
- package/dist/runner/dsh/mux-stream.js +176 -0
- package/dist/runner/dsh/runner.d.ts +21 -1
- package/dist/runner/dsh/runner.js +76 -73
- package/dist/runner/dsh/translator.d.ts +1 -11
- package/dist/runner/dsh/translator.js +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/runner/kimi/acp/runner.d.ts +22 -1
- package/dist/runner/kimi/acp/runner.js +83 -60
- package/dist/runner/kimi/acp/translator.js +1 -12
- package/dist/runner/opencode/acp/error-monitor.d.ts +11 -0
- package/dist/runner/opencode/acp/error-monitor.js +31 -2
- package/dist/runner/opencode/acp/runner.d.ts +3 -1
- package/dist/runner/opencode/acp/translator.js +1 -12
- package/dist/runner/pi/rpc/runner.d.ts +2 -1
- package/dist/runner/pi/rpc/translator.d.ts +2 -8
- package/dist/runner/pi/rpc/translator.js +2 -7
- package/dist/runner/probe.d.ts +1 -1
- package/dist/runner/probe.js +10 -9
- package/dist/runner/registry.d.ts +2 -20
- package/dist/runner/registry.js +0 -32
- package/dist/runner/types.d.ts +37 -155
- package/dist/runner/types.js +4 -24
- package/dist/session/claude/session-index.d.ts +11 -4
- package/dist/session/claude/session-index.js +34 -10
- package/dist/session/claude/session-reader.d.ts +1 -1
- package/dist/session/claude/sessions.d.ts +2 -2
- package/dist/session/claude/sessions.js +41 -26
- package/dist/session/codex/rollout-reader.d.ts +1 -1
- package/dist/session/codex/rollout-reader.js +14 -13
- package/dist/session/codex/sessions.d.ts +1 -1
- package/dist/session/codex/sessions.js +4 -2
- package/dist/session/common/jsonl.js +7 -1
- package/dist/session/common/pagination.d.ts +2 -0
- package/dist/session/common/pagination.js +1 -1
- package/dist/session/common/recency.d.ts +6 -0
- package/dist/session/common/recency.js +7 -5
- package/dist/session/common/two-pass.d.ts +1 -1
- package/dist/session/common/usage-accumulator.d.ts +1 -1
- package/dist/session/dsh/sessions.d.ts +1 -1
- package/dist/session/dsh/sessions.js +37 -12
- package/dist/session/kimi/sessions.d.ts +1 -1
- package/dist/session/kimi/sessions.js +37 -10
- package/dist/session/opencode/sessions.d.ts +1 -1
- package/dist/session/opencode/sessions.js +53 -48
- package/dist/session/pi/sessions.d.ts +1 -1
- package/dist/session/pi/sessions.js +23 -9
- package/dist/session/registry.d.ts +2 -1
- package/dist/session/session-store.d.ts +1 -2
- package/dist/session/session-store.js +14 -7
- package/dist/session-contract.d.ts +178 -0
- package/dist/session-contract.js +9 -0
- package/package.json +1 -1
- package/dist/router/usage-format.d.ts +0 -60
- /package/dist/{runner/dsh → dsh}/auth.d.ts +0 -0
- /package/dist/{runner/dsh → dsh}/types.d.ts +0 -0
- /package/dist/{runner/dsh → dsh}/types.js +0 -0
package/dist/card/run-state.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentEvent, ApprovalView, ToolHint, GoalView } from '../runner/index.js';
|
|
2
|
+
import type { UsageSnapshot } from '../session-contract.js';
|
|
2
3
|
export type RunTerminal = 'running' | 'finalizing' | 'done' | 'error' | 'interrupted' | 'idle_timeout'
|
|
3
4
|
/**
|
|
4
5
|
* 本轮 turn 已结束,但会话的 goal 仍 active:宿主会自动开始下一轮,任务没有
|
|
@@ -13,10 +14,20 @@ export type RunTerminal = 'running' | 'finalizing' | 'done' | 'error' | 'interru
|
|
|
13
14
|
* 禁止各自再抄一份字面量——三处漂移过一次(goal_continuing 只进白名单不进
|
|
14
15
|
* 按钮判据),新增终态时必漏一处的风险是结构性的。
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
+
declare const RUN_TERMINAL_STATES: readonly ["done", "error", "interrupted", "idle_timeout", "goal_continuing"];
|
|
17
18
|
export type RunFinalTerminal = (typeof RUN_TERMINAL_STATES)[number];
|
|
18
19
|
/** 该状态是否已收尾(非 running/finalizing)。 */
|
|
19
20
|
export declare function isRunTerminal(terminal: RunTerminal): terminal is RunFinalTerminal;
|
|
21
|
+
/** 仍在推进的两个状态(`RunTerminal` 的非终态部分)。 */
|
|
22
|
+
export type RunActiveTerminal = 'running' | 'finalizing';
|
|
23
|
+
/**
|
|
24
|
+
* 该状态是否仍在推进(running 或 finalizing)。
|
|
25
|
+
*
|
|
26
|
+
* `finalizing` 是「result 已到、进程还在收尾」的非终态:卡片仍要处理事件、
|
|
27
|
+
* 仍要显示停止按钮。这个判据此前在 card/bridge 里逐字抄了四处,与
|
|
28
|
+
* `isRunTerminal` 互为反义却各写各的——收在这儿与终态判据并排。
|
|
29
|
+
*/
|
|
30
|
+
export declare function isRunActive(terminal: RunTerminal): terminal is RunActiveTerminal;
|
|
20
31
|
export type RunFooter = 'thinking' | 'tool_running' | 'streaming' | null;
|
|
21
32
|
/** 中断来源(interrupted 终态的原因),供卡片如实归因。 */
|
|
22
33
|
export type InterruptedReason = 'approval_timeout' | 'user_stop' | 'approval_cancelled';
|
|
@@ -85,7 +96,18 @@ export interface RunNotice {
|
|
|
85
96
|
text: string;
|
|
86
97
|
timestamp?: string;
|
|
87
98
|
}
|
|
88
|
-
export interface
|
|
99
|
+
export interface FinalAnswerState {
|
|
100
|
+
content: string;
|
|
101
|
+
timestamp?: string;
|
|
102
|
+
complete: boolean;
|
|
103
|
+
source: 'protocol' | 'inferred';
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 一张 run 卡的状态。用量字段(context/tokens/cache/累计/推理)一律来自
|
|
107
|
+
* `UsageSnapshot` 单源——原先在这里、`FinishMeta`、`usage-format` 和桥侧各抄
|
|
108
|
+
* 一份(§9.21「五处一致」靠人记),加一个字段要改四遍。
|
|
109
|
+
*/
|
|
110
|
+
export interface RunState extends UsageSnapshot {
|
|
89
111
|
runId: string;
|
|
90
112
|
terminal: RunTerminal;
|
|
91
113
|
footer: RunFooter;
|
|
@@ -94,34 +116,17 @@ export interface RunState {
|
|
|
94
116
|
/** 本 run 结束时间(epoch ms):终态后耗时定格,不再随渲染时刻增长。 */
|
|
95
117
|
finishedAt?: number;
|
|
96
118
|
blocks: RunBlock[];
|
|
119
|
+
/**
|
|
120
|
+
* The answer the user is waiting for. Kept outside `blocks` so progress
|
|
121
|
+
* traffic cannot evict or consume its display budget.
|
|
122
|
+
*/
|
|
123
|
+
finalAnswer?: FinalAnswerState;
|
|
97
124
|
sessionId?: string;
|
|
98
125
|
resultSubtype?: 'success' | 'error' | 'interrupted';
|
|
99
126
|
/** interrupted 终态的中断来源;undefined = 未归类(渲染默认文案)。 */
|
|
100
127
|
interruptedReason?: InterruptedReason;
|
|
101
|
-
contextLength?: number;
|
|
102
|
-
/** 当前模型 context window 上限(codex jsonl 提供);卡片据此渲染百分比。 */
|
|
103
|
-
contextLimit?: number;
|
|
104
128
|
errorMsg?: string;
|
|
105
129
|
idleTimeoutMinutes?: number;
|
|
106
|
-
compactCount?: number;
|
|
107
|
-
cacheReadTokens?: number;
|
|
108
|
-
cacheCreationTokens?: number;
|
|
109
|
-
/** Agent-declared total; the done card uses max(total, sum of parts). */
|
|
110
|
-
totalTokens?: number;
|
|
111
|
-
/** Real input tokens from the agent's result event (codex/opencode).
|
|
112
|
-
* When present, the done card shows the real value instead of the
|
|
113
|
-
* contextLength-based estimate. */
|
|
114
|
-
inputTokens?: number;
|
|
115
|
-
/** Real output tokens from the agent's result event. */
|
|
116
|
-
outputTokens?: number;
|
|
117
|
-
/** 会话累计 total/input/output(所有 run 之和),Run 卡片展示"累计"。 */
|
|
118
|
-
cumulativeTotalTokens?: number;
|
|
119
|
-
cumulativeInputTokens?: number;
|
|
120
|
-
cumulativeOutputTokens?: number;
|
|
121
|
-
/** 会话累计 cache read token(所有 run 之和)。 */
|
|
122
|
-
cumulativeCacheReadTokens?: number;
|
|
123
|
-
/** 会话累计 cache creation token(所有 run 之和)。 */
|
|
124
|
-
cumulativeCacheCreationTokens?: number;
|
|
125
130
|
plan?: string;
|
|
126
131
|
/** 实际生效模型(system.init 携带;失败兜底 synthetic init 为 '',渲染须容忍)。 */
|
|
127
132
|
model?: string;
|
|
@@ -135,12 +140,8 @@ export interface RunState {
|
|
|
135
140
|
sessionTitle?: string;
|
|
136
141
|
/** 当前模式(ACP current_mode_update.currentModeId)。 */
|
|
137
142
|
mode?: string;
|
|
138
|
-
/** 推理 token(pi usage.reasoning 累加,经 finish meta 写入)。 */
|
|
139
|
-
reasoningTokens?: number;
|
|
140
143
|
/** Codex 操作类型:'turn' 表示普通 run,'compaction' 表示 compact 运行。 */
|
|
141
144
|
operationKind?: 'turn' | 'compaction';
|
|
142
|
-
/** 压缩前上下文水位(codex compact 卡展示「压缩前 X → 压缩后 Y」)。 */
|
|
143
|
-
compactPreContextLength?: number;
|
|
144
145
|
/**
|
|
145
146
|
* 待审批请求列表(app-server 模式)。同一 turn 内并发多个审批
|
|
146
147
|
* 时全部渲染,避免后到者顶掉先到者的按钮(单槽会丢 UI,只能等超时 cancel)。
|
|
@@ -189,35 +190,23 @@ export interface RunState {
|
|
|
189
190
|
*/
|
|
190
191
|
goalKnown?: boolean;
|
|
191
192
|
}
|
|
192
|
-
|
|
193
|
+
/** 终态卡片的一次性元信息;用量部分与 `RunState` 同源(`UsageSnapshot`)。 */
|
|
194
|
+
export interface FinishMeta extends UsageSnapshot {
|
|
193
195
|
resultSubtype?: 'success' | 'error' | 'interrupted';
|
|
194
196
|
/** 中断来源:由桥侧在 finish 时显式传入(/stop → user_stop、审批卡取消 → approval_cancelled)。 */
|
|
195
197
|
interruptedReason?: InterruptedReason;
|
|
196
|
-
contextLength?: number;
|
|
197
|
-
/** 当前模型 context window 上限;透传到 RunState 供 done 卡片显示百分比。 */
|
|
198
|
-
contextLimit?: number;
|
|
199
198
|
errorMsg?: string;
|
|
200
199
|
idleTimeoutMinutes?: number;
|
|
201
|
-
compactCount?: number;
|
|
202
|
-
compactPreContextLength?: number;
|
|
203
|
-
cacheReadTokens?: number;
|
|
204
|
-
cacheCreationTokens?: number;
|
|
205
|
-
/** Agent-declared total; threaded to RunState for the done card. */
|
|
206
|
-
totalTokens?: number;
|
|
207
|
-
/** Real input/output tokens from the agent's result event. Threaded through
|
|
208
|
-
* to RunState so the done card can display real values instead of estimates. */
|
|
209
|
-
inputTokens?: number;
|
|
210
|
-
outputTokens?: number;
|
|
211
|
-
/** 会话累计 total/input/output(所有 run 之和),从 session jsonl 读取。 */
|
|
212
|
-
cumulativeTotalTokens?: number;
|
|
213
|
-
cumulativeInputTokens?: number;
|
|
214
|
-
cumulativeOutputTokens?: number;
|
|
215
|
-
cumulativeCacheReadTokens?: number;
|
|
216
|
-
cumulativeCacheCreationTokens?: number;
|
|
217
|
-
/** 推理 token(pi usage.reasoning 累加,经 usageMeta 透传)。 */
|
|
218
|
-
reasoningTokens?: number;
|
|
219
200
|
}
|
|
220
201
|
export declare function createInitialRunState(runId: string): RunState;
|
|
221
202
|
export declare function reduceRunState(state: RunState, event: AgentEvent): RunState;
|
|
222
|
-
|
|
203
|
+
/**
|
|
204
|
+
* 用户停止某个后台任务成功后,从卡片状态里摘掉它。
|
|
205
|
+
*
|
|
206
|
+
* run 此时已经收尾(没有流再消费事件),所以这条不走 reducer 的事件入口;但
|
|
207
|
+
* RunState 的形状只允许在本模块内拼装——bridge 直接展开 state 曾把「摘一条」
|
|
208
|
+
* 写成「整体重建」,字段一多就会漏带。
|
|
209
|
+
*/
|
|
210
|
+
export declare function removeBackgroundJob(state: RunState, jobId: string): RunState;
|
|
211
|
+
export declare function finishRun(state: RunState, terminal: RunFinalTerminal, meta?: FinishMeta): RunState;
|
|
223
212
|
export {};
|
package/dist/card/run-state.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { keepTail } from '../common/truncate.js';
|
|
2
|
+
import { asRecord } from '../common/tool-summary.js';
|
|
2
3
|
const MAX_REASONING_CHARS = 4_000;
|
|
3
4
|
const MAX_TEXT_CHARS = 12_000;
|
|
4
5
|
const MAX_TOOL_DETAIL_CHARS = 3_000;
|
|
@@ -10,7 +11,7 @@ const MAX_BLOCKS = 24;
|
|
|
10
11
|
* 禁止各自再抄一份字面量——三处漂移过一次(goal_continuing 只进白名单不进
|
|
11
12
|
* 按钮判据),新增终态时必漏一处的风险是结构性的。
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
const RUN_TERMINAL_STATES = [
|
|
14
15
|
'done',
|
|
15
16
|
'error',
|
|
16
17
|
'interrupted',
|
|
@@ -21,6 +22,16 @@ export const RUN_TERMINAL_STATES = [
|
|
|
21
22
|
export function isRunTerminal(terminal) {
|
|
22
23
|
return RUN_TERMINAL_STATES.includes(terminal);
|
|
23
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* 该状态是否仍在推进(running 或 finalizing)。
|
|
27
|
+
*
|
|
28
|
+
* `finalizing` 是「result 已到、进程还在收尾」的非终态:卡片仍要处理事件、
|
|
29
|
+
* 仍要显示停止按钮。这个判据此前在 card/bridge 里逐字抄了四处,与
|
|
30
|
+
* `isRunTerminal` 互为反义却各写各的——收在这儿与终态判据并排。
|
|
31
|
+
*/
|
|
32
|
+
export function isRunActive(terminal) {
|
|
33
|
+
return terminal === 'running' || terminal === 'finalizing';
|
|
34
|
+
}
|
|
24
35
|
export function createInitialRunState(runId) {
|
|
25
36
|
return {
|
|
26
37
|
runId,
|
|
@@ -50,6 +61,8 @@ export function reduceRunState(state, event) {
|
|
|
50
61
|
return reduceBackgroundJobsEvent(state, event);
|
|
51
62
|
if (event.type === 'result')
|
|
52
63
|
return reduceResultEvent(state, event);
|
|
64
|
+
if (event.type === 'final_answer')
|
|
65
|
+
return reduceFinalAnswerEvent(state, event);
|
|
53
66
|
if (event.type === 'assistant')
|
|
54
67
|
return reduceAssistantEvent(state, event);
|
|
55
68
|
if (event.type === 'user')
|
|
@@ -187,7 +200,7 @@ function reduceTurnDiffEvent(state, event) {
|
|
|
187
200
|
id: event.itemId,
|
|
188
201
|
name: event.toolName ?? 'command',
|
|
189
202
|
input: inputStr,
|
|
190
|
-
parsedInput:
|
|
203
|
+
parsedInput: asRecord(inputStr),
|
|
191
204
|
...(event.toolHint !== undefined ? { toolHint: event.toolHint } : {}),
|
|
192
205
|
output: keepTail(event.toolOutput, MAX_TOOL_DETAIL_CHARS),
|
|
193
206
|
status: complete ? (event.toolStatus ?? 'ok') : 'running',
|
|
@@ -320,31 +333,82 @@ function reduceResultEvent(state, event) {
|
|
|
320
333
|
// sessionId is set by system.init; undefined means init hasn't arrived yet.
|
|
321
334
|
if (state.sessionId === undefined)
|
|
322
335
|
return state;
|
|
336
|
+
const withFinalAnswer = promoteFinalAnswer(state, 'inferred');
|
|
323
337
|
const resultEvent = event;
|
|
324
338
|
const incomingSubtype = event.subtype;
|
|
325
339
|
const incomingErrorMsg = incomingSubtype === 'error' ? (resultEvent.errorMessage ?? 'Agent 返回错误结果') : undefined;
|
|
326
340
|
// 合并 subtype:error 优先,其次 interrupted(任一为 error 即 error;
|
|
327
341
|
// 否则任一为 interrupted 即 interrupted;interrupted 不得并入 success)。
|
|
328
|
-
const mergedSubtype =
|
|
342
|
+
const mergedSubtype = withFinalAnswer.resultSubtype === 'error' || incomingSubtype === 'error'
|
|
329
343
|
? 'error'
|
|
330
|
-
:
|
|
344
|
+
: withFinalAnswer.resultSubtype === 'interrupted' || incomingSubtype === 'interrupted'
|
|
331
345
|
? 'interrupted'
|
|
332
346
|
: 'success';
|
|
333
347
|
// 合并 errorMsg:首个非 undefined 胜出(existing ?? incoming)
|
|
334
|
-
const mergedErrorMsg =
|
|
348
|
+
const mergedErrorMsg = withFinalAnswer.errorMsg ?? incomingErrorMsg;
|
|
335
349
|
return {
|
|
336
|
-
...
|
|
350
|
+
...withFinalAnswer,
|
|
337
351
|
terminal: 'finalizing',
|
|
338
352
|
footer: null,
|
|
339
|
-
blocks: markThinkingInactive(
|
|
353
|
+
blocks: markThinkingInactive(withFinalAnswer.blocks),
|
|
340
354
|
resultSubtype: mergedSubtype,
|
|
341
355
|
errorMsg: mergedErrorMsg,
|
|
342
356
|
// costUsd:首个非 undefined 胜出(与 errorMsg 合并语义一致)
|
|
343
|
-
...(event.total_cost_usd !== undefined &&
|
|
357
|
+
...(event.total_cost_usd !== undefined && withFinalAnswer.costUsd === undefined
|
|
344
358
|
? { costUsd: event.total_cost_usd }
|
|
345
359
|
: {}),
|
|
346
360
|
};
|
|
347
361
|
}
|
|
362
|
+
/** Record an authoritative protocol final answer and remove its progress copy. */
|
|
363
|
+
function reduceFinalAnswerEvent(state, event) {
|
|
364
|
+
if (event.type !== 'final_answer')
|
|
365
|
+
return state;
|
|
366
|
+
if (!event.text.trim() && !state.finalAnswer)
|
|
367
|
+
return state;
|
|
368
|
+
const blocks = event.itemId
|
|
369
|
+
? state.blocks.filter((block) => block.kind !== 'text' || block.itemId !== event.itemId)
|
|
370
|
+
: state.blocks;
|
|
371
|
+
const content = event.text.trim() ? event.text : (state.finalAnswer?.content ?? '');
|
|
372
|
+
return {
|
|
373
|
+
...state,
|
|
374
|
+
blocks,
|
|
375
|
+
finalAnswer: {
|
|
376
|
+
content,
|
|
377
|
+
timestamp: state.finalAnswer?.timestamp ?? event.timestamp,
|
|
378
|
+
complete: event.complete ?? state.finalAnswer?.complete ?? false,
|
|
379
|
+
source: 'protocol',
|
|
380
|
+
},
|
|
381
|
+
footer: 'streaming',
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Agents without an explicit final-answer marker use their last non-empty
|
|
386
|
+
* assistant text block. Moving it out of `blocks` protects it from
|
|
387
|
+
* MAX_BLOCKS and lets the renderer assign it first claim on card space.
|
|
388
|
+
*/
|
|
389
|
+
function promoteFinalAnswer(state, source) {
|
|
390
|
+
if (state.finalAnswer) {
|
|
391
|
+
return state.finalAnswer.complete
|
|
392
|
+
? state
|
|
393
|
+
: { ...state, finalAnswer: { ...state.finalAnswer, complete: true } };
|
|
394
|
+
}
|
|
395
|
+
for (let i = state.blocks.length - 1; i >= 0; i--) {
|
|
396
|
+
const block = state.blocks[i];
|
|
397
|
+
if (block.kind !== 'text' || !block.content.trim())
|
|
398
|
+
continue;
|
|
399
|
+
return {
|
|
400
|
+
...state,
|
|
401
|
+
blocks: state.blocks.filter((_, index) => index !== i),
|
|
402
|
+
finalAnswer: {
|
|
403
|
+
content: block.content,
|
|
404
|
+
timestamp: block.timestamp,
|
|
405
|
+
complete: true,
|
|
406
|
+
source,
|
|
407
|
+
},
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
return state;
|
|
411
|
+
}
|
|
348
412
|
/**
|
|
349
413
|
* 后台任务名单 → RunState.backgroundJobs。
|
|
350
414
|
*
|
|
@@ -357,6 +421,19 @@ function reduceBackgroundJobsEvent(state, event) {
|
|
|
357
421
|
return state;
|
|
358
422
|
return { ...state, backgroundJobs: event.jobs };
|
|
359
423
|
}
|
|
424
|
+
/**
|
|
425
|
+
* 用户停止某个后台任务成功后,从卡片状态里摘掉它。
|
|
426
|
+
*
|
|
427
|
+
* run 此时已经收尾(没有流再消费事件),所以这条不走 reducer 的事件入口;但
|
|
428
|
+
* RunState 的形状只允许在本模块内拼装——bridge 直接展开 state 曾把「摘一条」
|
|
429
|
+
* 写成「整体重建」,字段一多就会漏带。
|
|
430
|
+
*/
|
|
431
|
+
export function removeBackgroundJob(state, jobId) {
|
|
432
|
+
return {
|
|
433
|
+
...state,
|
|
434
|
+
backgroundJobs: (state.backgroundJobs ?? []).filter((job) => job.id !== jobId),
|
|
435
|
+
};
|
|
436
|
+
}
|
|
360
437
|
/**
|
|
361
438
|
* 运行期状态投影 → 状态行。
|
|
362
439
|
*
|
|
@@ -458,7 +535,7 @@ function reduceAssistantEvent(state, event) {
|
|
|
458
535
|
id: content.id,
|
|
459
536
|
name: content.name,
|
|
460
537
|
input: inputStr,
|
|
461
|
-
parsedInput:
|
|
538
|
+
parsedInput: asRecord(inputStr),
|
|
462
539
|
...(content.summary !== undefined ? { summary: content.summary } : {}),
|
|
463
540
|
status: 'running',
|
|
464
541
|
startedAt: event.timestamp,
|
|
@@ -618,30 +695,33 @@ function reduceFileChangeEvent(state, event) {
|
|
|
618
695
|
};
|
|
619
696
|
}
|
|
620
697
|
export function finishRun(state, terminal, meta = {}) {
|
|
698
|
+
const withFinalAnswer = promoteFinalAnswer(state, 'inferred');
|
|
621
699
|
// 允许从 running 或 finalizing finish(/stop、idle watchdog、进程退出 finally)。
|
|
622
700
|
// finalizing 是非终态(result 已收到,进程未退出),可被 finish 转终态。
|
|
623
701
|
// 如果已经是终态,仍然允许补充 meta 信息(如 usage 等,bridge finally 的
|
|
624
702
|
// else-if-sawResult 分支用此路径补充 token 统计)。
|
|
625
|
-
if (
|
|
703
|
+
if (withFinalAnswer.terminal !== 'running' && withFinalAnswer.terminal !== 'finalizing') {
|
|
626
704
|
// Already terminal: apply meta fields if provided (e.g. usage from jsonl)
|
|
627
705
|
const hasMeta = Object.keys(meta).some((k) => meta[k] !== undefined);
|
|
628
706
|
if (!hasMeta)
|
|
629
|
-
return
|
|
630
|
-
return { ...
|
|
707
|
+
return withFinalAnswer;
|
|
708
|
+
return { ...withFinalAnswer, ...sanitizeMeta(meta) };
|
|
631
709
|
}
|
|
632
710
|
// interrupted 终态的中断来源:显式传入优先;否则从顶层持久标记推导
|
|
633
711
|
// (approval_expired 已置位但调用方未传 reason 的路径,如协调器过期自动
|
|
634
712
|
// cancel。原因必须在终态确定,不依赖调用方记得传参)。
|
|
635
713
|
const derivedReason = meta.interruptedReason ??
|
|
636
|
-
(terminal === 'interrupted' &&
|
|
714
|
+
(terminal === 'interrupted' && withFinalAnswer.approvalExpired === true
|
|
715
|
+
? 'approval_timeout'
|
|
716
|
+
: undefined);
|
|
637
717
|
return {
|
|
638
|
-
...
|
|
718
|
+
...withFinalAnswer,
|
|
639
719
|
terminal,
|
|
640
720
|
footer: null,
|
|
641
721
|
// 耗时定格:终态之后再渲染(补 token 统计、点「详情」重渲染)都沿用同一
|
|
642
722
|
// 结束时刻,否则每次 patch 的数字都会变大。
|
|
643
|
-
finishedAt:
|
|
644
|
-
blocks: markThinkingInactive(
|
|
723
|
+
finishedAt: withFinalAnswer.finishedAt ?? Date.now(),
|
|
724
|
+
blocks: markThinkingInactive(withFinalAnswer.blocks),
|
|
645
725
|
...sanitizeMeta(meta),
|
|
646
726
|
...(derivedReason !== undefined ? { interruptedReason: derivedReason } : {}),
|
|
647
727
|
};
|
|
@@ -673,24 +753,6 @@ function stringifyUnknown(value) {
|
|
|
673
753
|
return String(value);
|
|
674
754
|
}
|
|
675
755
|
}
|
|
676
|
-
/**
|
|
677
|
-
* parse a (possibly truncated) string into a record, mirroring what
|
|
678
|
-
* `tool-render.ts`'s `asRecord` did on every render. Returns `null` when the
|
|
679
|
-
* string is empty, non-JSON, or parses to a non-object — so a truncation-broken
|
|
680
|
-
* JSON yields `null` exactly as the old per-render parse did. Computed once at
|
|
681
|
-
* store time and cached on `ToolEntry.parsedInput`.
|
|
682
|
-
*/
|
|
683
|
-
function tryParseRecord(input) {
|
|
684
|
-
if (!input)
|
|
685
|
-
return null;
|
|
686
|
-
try {
|
|
687
|
-
const p = JSON.parse(input);
|
|
688
|
-
return p && typeof p === 'object' ? p : null;
|
|
689
|
-
}
|
|
690
|
-
catch {
|
|
691
|
-
return null;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
756
|
function keepLatestBlocks(blocks) {
|
|
695
757
|
return blocks.length <= MAX_BLOCKS ? blocks : blocks.slice(-MAX_BLOCKS);
|
|
696
758
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format session/run usage stats (context, compact count, tokens, cost) into
|
|
3
|
+
* the display strings shown on cards. Pure — no Router state.
|
|
4
|
+
*
|
|
5
|
+
* 归属 card/:渲染层(run-renderer)与 router 都只消费它的展示字符串,此前
|
|
6
|
+
* 住在 router/ 让它成为 card→router 的唯一理由。
|
|
7
|
+
*/
|
|
8
|
+
import type { UsageSnapshot } from '../session-contract.js';
|
|
9
|
+
/** `formatUsageStats` 只读这几项:会话/进度卡片上的紧凑用量行。 */
|
|
10
|
+
export type SessionDisplayUsage = Pick<UsageSnapshot, 'contextLength' | 'contextLimit' | 'compactCount' | 'cacheReadTokens' | 'cacheCreationTokens'>;
|
|
11
|
+
/**
|
|
12
|
+
* Format usage stats (context length, compact count, cache tokens) into a display string.
|
|
13
|
+
* Each stat on its own line with blank lines between sections.
|
|
14
|
+
* @param usage - Usage stats object
|
|
15
|
+
* @param options - Optional display options (showResult adds result line)
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatUsageStats(usage?: UsageSnapshot & {
|
|
18
|
+
/** 实际生效模型(system.init 携带)。非空字符串才显示。 */
|
|
19
|
+
model?: string;
|
|
20
|
+
/** 本次 run 花费(USD)。存在才显示。 */
|
|
21
|
+
costUsd?: number;
|
|
22
|
+
}, options?: {
|
|
23
|
+
showResult?: boolean;
|
|
24
|
+
result?: string;
|
|
25
|
+
/**
|
|
26
|
+
* 首行状态文案。默认 `✅ 已完成`;goal 仍 active 的收尾卡必须换掉它——
|
|
27
|
+
* 本轮 turn 结束不等于任务结束。
|
|
28
|
+
*/
|
|
29
|
+
completedLabel?: string;
|
|
30
|
+
}): string;
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Format session/run usage stats (context, compact count, tokens, cost) into
|
|
3
3
|
* the display strings shown on cards. Pure — no Router state.
|
|
4
|
+
*
|
|
5
|
+
* 归属 card/:渲染层(run-renderer)与 router 都只消费它的展示字符串,此前
|
|
6
|
+
* 住在 router/ 让它成为 card→router 的唯一理由。
|
|
4
7
|
*/
|
|
5
|
-
export function activeRunUsage(activeRun) {
|
|
6
|
-
if (!activeRun || activeRun.contextLength === undefined)
|
|
7
|
-
return undefined;
|
|
8
|
-
return {
|
|
9
|
-
contextLength: activeRun.contextLength,
|
|
10
|
-
compactCount: activeRun.compactCount,
|
|
11
|
-
cacheReadTokens: activeRun.cacheReadTokens,
|
|
12
|
-
cacheCreationTokens: activeRun.cacheCreationTokens,
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
8
|
/**
|
|
16
9
|
* Format number to human-readable unit string.
|
|
17
10
|
* - >= 1M: one decimal, M suffix (e.g., 1200000 → 1.2M, 25000000 → 25M)
|
package/dist/clone.js
CHANGED
|
@@ -390,7 +390,12 @@ export class CloneSession {
|
|
|
390
390
|
const raw = JSON.parse(fs.readFileSync(path.join(this.configDir, 'startup-contact.json'), 'utf-8'));
|
|
391
391
|
return typeof raw.userId === 'string' && raw.userId ? raw.userId : undefined;
|
|
392
392
|
}
|
|
393
|
-
catch {
|
|
393
|
+
catch (err) {
|
|
394
|
+
// ENOENT = 旧实例从未写过 startup-contact(正常)。其余(解析失败/权限)
|
|
395
|
+
// 留痕:否则下游会误归因成「旧 owner 无条目」。
|
|
396
|
+
if (err.code !== 'ENOENT') {
|
|
397
|
+
getLogger().debug(`[clone] cannot read startup-contact.json for previous owner: ${err?.message ?? String(err)}`);
|
|
398
|
+
}
|
|
394
399
|
return undefined;
|
|
395
400
|
}
|
|
396
401
|
}
|
|
@@ -519,10 +519,10 @@ export function loadCodexConfig(opts = {}) {
|
|
|
519
519
|
}
|
|
520
520
|
catch {
|
|
521
521
|
// config.toml 读取/解析失败:readModelCatalogJsonPath 对此返回
|
|
522
|
-
// TOML_PARSE_FAILED_SENTINEL(isCodexCatalogMode → false
|
|
523
|
-
//
|
|
524
|
-
//
|
|
525
|
-
//
|
|
522
|
+
// TOML_PARSE_FAILED_SENTINEL(isCodexCatalogMode → false),因此正常路径下
|
|
523
|
+
// catalogMode 恒为 false,下面的 `if (catalogMode)` 分支只在两次读取之间
|
|
524
|
+
// config.toml 被改写(TOCTOU)时可达;保留该防御,避免把“已声明 catalog、
|
|
525
|
+
// 随后配置损坏”误降级成 bundled 模型。
|
|
526
526
|
if (catalogMode) {
|
|
527
527
|
return {
|
|
528
528
|
currentModel: '',
|
package/dist/config/index.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export declare const PI_THINKING_LEVELS: readonly ["off", "minimal", "low", "med
|
|
|
22
22
|
export declare const DEFAULT_STOP_GRACE_MS: 5000;
|
|
23
23
|
/** Codex app-server turn idle timeout default (minutes). */
|
|
24
24
|
export declare const DEFAULT_TURN_IDLE_TIMEOUT_MINUTES: 30;
|
|
25
|
+
/** Approval timeout default (ms), shared by schema and bridge fallback. */
|
|
26
|
+
export declare const DEFAULT_APPROVAL_TIMEOUT_MS: number;
|
|
25
27
|
/**
|
|
26
28
|
* 入站媒体默认配置(schema 默认与 connector 兜底共用,避免双源漂移)。
|
|
27
29
|
*
|
|
@@ -32,27 +34,23 @@ export declare const DEFAULT_TURN_IDLE_TIMEOUT_MINUTES: 30;
|
|
|
32
34
|
*/
|
|
33
35
|
export declare const DEFAULT_INBOUND_MEDIA_DIR_NAME = ".lark-remote-temp";
|
|
34
36
|
export declare const DEFAULT_INBOUND_MEDIA_MAX_SIZE_MB = 100;
|
|
35
|
-
/** 模型 ID → alias 映射。 */
|
|
36
|
-
export declare const MODEL_ID_TO_ALIAS: Record<string, string>;
|
|
37
|
-
/** alias → model ID 反向映射。 */
|
|
38
|
-
export declare const MODEL_ALIAS_TO_ID: Record<string, string>;
|
|
39
37
|
declare const ClaudeConfigSchema: z.ZodObject<{
|
|
40
38
|
model: z.ZodDefault<z.ZodString>;
|
|
41
39
|
effort: z.ZodDefault<z.ZodEnum<{
|
|
42
|
-
medium: "medium";
|
|
43
40
|
low: "low";
|
|
44
41
|
high: "high";
|
|
45
|
-
xhigh: "xhigh";
|
|
46
42
|
max: "max";
|
|
43
|
+
medium: "medium";
|
|
44
|
+
xhigh: "xhigh";
|
|
47
45
|
}>>;
|
|
48
46
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
49
47
|
default: "default";
|
|
50
|
-
|
|
51
|
-
bypassPermissions: "bypassPermissions";
|
|
48
|
+
acceptEdits: "acceptEdits";
|
|
52
49
|
auto: "auto";
|
|
50
|
+
bypassPermissions: "bypassPermissions";
|
|
53
51
|
manual: "manual";
|
|
54
|
-
acceptEdits: "acceptEdits";
|
|
55
52
|
dontAsk: "dontAsk";
|
|
53
|
+
plan: "plan";
|
|
56
54
|
}>>;
|
|
57
55
|
approvalTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
58
56
|
idleTtlMinutes: z.ZodDefault<z.ZodNumber>;
|
|
@@ -100,11 +98,11 @@ declare const PiConfigSchema: z.ZodObject<{
|
|
|
100
98
|
provider: z.ZodDefault<z.ZodString>;
|
|
101
99
|
model: z.ZodDefault<z.ZodString>;
|
|
102
100
|
thinking: z.ZodDefault<z.ZodEnum<{
|
|
103
|
-
medium: "medium";
|
|
104
|
-
off: "off";
|
|
105
101
|
low: "low";
|
|
106
102
|
high: "high";
|
|
103
|
+
medium: "medium";
|
|
107
104
|
xhigh: "xhigh";
|
|
105
|
+
off: "off";
|
|
108
106
|
minimal: "minimal";
|
|
109
107
|
}>>;
|
|
110
108
|
tools: z.ZodDefault<z.ZodString>;
|
|
@@ -119,8 +117,8 @@ declare const KimiConfigSchema: z.ZodObject<{
|
|
|
119
117
|
}>>;
|
|
120
118
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
121
119
|
auto: "auto";
|
|
122
|
-
yolo: "yolo";
|
|
123
120
|
manual: "manual";
|
|
121
|
+
yolo: "yolo";
|
|
124
122
|
}>>;
|
|
125
123
|
acp: z.ZodOptional<z.ZodObject<{
|
|
126
124
|
binary: z.ZodDefault<z.ZodString>;
|
|
@@ -154,20 +152,20 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
154
152
|
claude: z.ZodDefault<z.ZodObject<{
|
|
155
153
|
model: z.ZodDefault<z.ZodString>;
|
|
156
154
|
effort: z.ZodDefault<z.ZodEnum<{
|
|
157
|
-
medium: "medium";
|
|
158
155
|
low: "low";
|
|
159
156
|
high: "high";
|
|
160
|
-
xhigh: "xhigh";
|
|
161
157
|
max: "max";
|
|
158
|
+
medium: "medium";
|
|
159
|
+
xhigh: "xhigh";
|
|
162
160
|
}>>;
|
|
163
161
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
164
162
|
default: "default";
|
|
165
|
-
|
|
166
|
-
bypassPermissions: "bypassPermissions";
|
|
163
|
+
acceptEdits: "acceptEdits";
|
|
167
164
|
auto: "auto";
|
|
165
|
+
bypassPermissions: "bypassPermissions";
|
|
168
166
|
manual: "manual";
|
|
169
|
-
acceptEdits: "acceptEdits";
|
|
170
167
|
dontAsk: "dontAsk";
|
|
168
|
+
plan: "plan";
|
|
171
169
|
}>>;
|
|
172
170
|
approvalTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
173
171
|
idleTtlMinutes: z.ZodDefault<z.ZodNumber>;
|
|
@@ -213,11 +211,11 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
213
211
|
provider: z.ZodDefault<z.ZodString>;
|
|
214
212
|
model: z.ZodDefault<z.ZodString>;
|
|
215
213
|
thinking: z.ZodDefault<z.ZodEnum<{
|
|
216
|
-
medium: "medium";
|
|
217
|
-
off: "off";
|
|
218
214
|
low: "low";
|
|
219
215
|
high: "high";
|
|
216
|
+
medium: "medium";
|
|
220
217
|
xhigh: "xhigh";
|
|
218
|
+
off: "off";
|
|
221
219
|
minimal: "minimal";
|
|
222
220
|
}>>;
|
|
223
221
|
tools: z.ZodDefault<z.ZodString>;
|
|
@@ -231,8 +229,8 @@ export declare const AppConfigSchema: z.ZodObject<{
|
|
|
231
229
|
}>>;
|
|
232
230
|
permissionMode: z.ZodDefault<z.ZodEnum<{
|
|
233
231
|
auto: "auto";
|
|
234
|
-
yolo: "yolo";
|
|
235
232
|
manual: "manual";
|
|
233
|
+
yolo: "yolo";
|
|
236
234
|
}>>;
|
|
237
235
|
acp: z.ZodOptional<z.ZodObject<{
|
|
238
236
|
binary: z.ZodDefault<z.ZodString>;
|
package/dist/config/index.js
CHANGED
|
@@ -50,6 +50,8 @@ const DEFAULTS = {
|
|
|
50
50
|
export const DEFAULT_STOP_GRACE_MS = DEFAULTS.STOP_GRACE_MS;
|
|
51
51
|
/** Codex app-server turn idle timeout default (minutes). */
|
|
52
52
|
export const DEFAULT_TURN_IDLE_TIMEOUT_MINUTES = DEFAULTS.TURN_IDLE_TIMEOUT_MINUTES;
|
|
53
|
+
/** Approval timeout default (ms), shared by schema and bridge fallback. */
|
|
54
|
+
export const DEFAULT_APPROVAL_TIMEOUT_MS = DEFAULTS.APPROVAL_TIMEOUT_MS;
|
|
53
55
|
/**
|
|
54
56
|
* 入站媒体默认配置(schema 默认与 connector 兜底共用,避免双源漂移)。
|
|
55
57
|
*
|
|
@@ -60,20 +62,6 @@ export const DEFAULT_TURN_IDLE_TIMEOUT_MINUTES = DEFAULTS.TURN_IDLE_TIMEOUT_MINU
|
|
|
60
62
|
*/
|
|
61
63
|
export const DEFAULT_INBOUND_MEDIA_DIR_NAME = '.lark-remote-temp';
|
|
62
64
|
export const DEFAULT_INBOUND_MEDIA_MAX_SIZE_MB = 100;
|
|
63
|
-
/** 模型 ID → alias 映射。 */
|
|
64
|
-
export const MODEL_ID_TO_ALIAS = {
|
|
65
|
-
'claude-opus-4-8': 'opus',
|
|
66
|
-
'claude-sonnet-4-6': 'sonnet',
|
|
67
|
-
'claude-haiku-4-5-20250501': 'haiku',
|
|
68
|
-
'claude-fable-5': 'fable',
|
|
69
|
-
};
|
|
70
|
-
/** alias → model ID 反向映射。 */
|
|
71
|
-
export const MODEL_ALIAS_TO_ID = {
|
|
72
|
-
opus: 'claude-opus-4-8',
|
|
73
|
-
sonnet: 'claude-sonnet-4-6',
|
|
74
|
-
haiku: 'claude-haiku-4-5-20250501',
|
|
75
|
-
fable: 'claude-fable-5',
|
|
76
|
-
};
|
|
77
65
|
const FeishuConfigSchema = z.object({
|
|
78
66
|
appId: z.string().min(1),
|
|
79
67
|
appSecret: z.string().min(1),
|
|
@@ -83,10 +71,10 @@ const ClaudeConfigSchema = z.object({
|
|
|
83
71
|
effort: z.enum(CLAUDE_EFFORTS).default('medium'),
|
|
84
72
|
/**
|
|
85
73
|
* Claude 权限模式(官方 --permission-mode 枚举 + 'default'=省略该参数)。
|
|
86
|
-
* 默认
|
|
87
|
-
*
|
|
74
|
+
* 默认 auto:低风险操作自动放行,高风险操作走审批(control_request →
|
|
75
|
+
* run 卡审批区);bypassPermissions 仍可选,但不再是默认值。
|
|
88
76
|
*/
|
|
89
|
-
permissionMode: z.enum(CLAUDE_PERMISSION_MODES).default('
|
|
77
|
+
permissionMode: z.enum(CLAUDE_PERMISSION_MODES).default('auto'),
|
|
90
78
|
/** 审批请求超时(ms),默认 5 分钟;超时自动发送 cancel 并中断 turn。
|
|
91
79
|
* 0 = 立即过期(fail-fast,避免审批永久挂起),不推荐;勿随意改短。 */
|
|
92
80
|
approvalTimeoutMs: z.number().int().min(0).default(DEFAULTS.APPROVAL_TIMEOUT_MS),
|
|
@@ -330,7 +318,7 @@ const TEMPLATE = `feishu:
|
|
|
330
318
|
claude:
|
|
331
319
|
model: ${DEFAULTS.CLAUDE_MODEL}
|
|
332
320
|
effort: medium
|
|
333
|
-
permissionMode:
|
|
321
|
+
permissionMode: auto
|
|
334
322
|
approvalTimeoutMs: ${DEFAULTS.APPROVAL_TIMEOUT_MS}
|
|
335
323
|
idleTtlMinutes: ${DEFAULTS.CLAUDE_IDLE_TTL_MINUTES}
|
|
336
324
|
stopGraceMs: ${DEFAULTS.STOP_GRACE_MS}
|
|
@@ -566,8 +554,6 @@ export function getAgentConfig(config, kind) {
|
|
|
566
554
|
export function getModelOptionsFromSettings(settingsPath) {
|
|
567
555
|
if (!settingsPath)
|
|
568
556
|
return [];
|
|
569
|
-
if (!fs.existsSync(settingsPath))
|
|
570
|
-
return [];
|
|
571
557
|
try {
|
|
572
558
|
const content = fs.readFileSync(settingsPath, 'utf-8');
|
|
573
559
|
const settings = JSON.parse(content);
|
package/dist/config/pi-config.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import os from 'node:os';
|
|
8
8
|
import path from 'node:path';
|
|
9
|
+
import { getLogger } from '../logger/index.js';
|
|
9
10
|
/**
|
|
10
11
|
* 解析 pi 配置目录。优先使用 PI_CONFIG_DIR 环境变量(测试隔离用),
|
|
11
12
|
* 默认 ~/.pi/agent。每次调用时动态读取环境变量,避免模块级缓存导致
|
|
@@ -71,8 +72,9 @@ export function loadPiProviderConfig() {
|
|
|
71
72
|
try {
|
|
72
73
|
modelsData = JSON.parse(fs.readFileSync(modelsFile, 'utf-8'));
|
|
73
74
|
}
|
|
74
|
-
catch {
|
|
75
|
-
//
|
|
75
|
+
catch (err) {
|
|
76
|
+
// 解析失败 = pi 模型选项会静默消失,必须留痕(此前全文件零日志)。
|
|
77
|
+
getLogger().warn(`[pi-config] cannot parse ${modelsFile}: ${err.message}`);
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
// 2. 读取 auth.json
|
|
@@ -81,8 +83,8 @@ export function loadPiProviderConfig() {
|
|
|
81
83
|
try {
|
|
82
84
|
authData = JSON.parse(fs.readFileSync(authFile, 'utf-8')) ?? {};
|
|
83
85
|
}
|
|
84
|
-
catch {
|
|
85
|
-
|
|
86
|
+
catch (err) {
|
|
87
|
+
getLogger().warn(`[pi-config] cannot parse ${authFile}: ${err.message}`);
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
// 3. 从 models.json 提取 providers
|