lark-remote 0.5.20 → 0.5.21
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 +10 -0
- package/dist/bridge/inbound-media.js +71 -45
- package/dist/bridge/index.d.ts +9 -0
- package/dist/bridge/index.js +230 -203
- package/dist/card/approval-render.js +32 -33
- package/dist/card/card-budget.js +123 -98
- package/dist/card/run-renderer.js +82 -68
- package/dist/card/run-state.d.ts +0 -14
- package/dist/card/run-state.js +335 -207
- package/dist/card/tool-render.js +20 -16
- package/dist/card/usage-format.d.ts +12 -9
- package/dist/card/usage-format.js +111 -97
- package/dist/common/text-width.js +36 -24
- package/dist/common/tool-summary.js +132 -90
- package/dist/index.js +226 -190
- package/dist/message-handlers.js +253 -236
- package/dist/router/commands/ls.d.ts +3 -0
- package/dist/router/commands/ls.js +256 -175
- package/dist/router/commands/order.js +184 -159
- package/dist/router/commands/resume.js +189 -133
- package/dist/router/commands/ws.js +219 -174
- package/dist/router/index.js +192 -201
- package/dist/runner/bash/runner.js +2 -4
- package/dist/runner/codex/app-server/translator.d.ts +2 -0
- package/dist/runner/codex/app-server/translator.js +287 -221
- package/dist/runner/common/acp/base-translator.js +19 -17
- package/dist/runner/common/jsonl-stream.js +154 -187
- package/dist/runner/common/jsonrpc/client.d.ts +29 -0
- package/dist/runner/common/jsonrpc/client.js +43 -12
- package/dist/runner/common/spawning-runner.d.ts +5 -0
- package/dist/runner/common/spawning-runner.js +8 -3
- package/dist/runner/common/turn-started.d.ts +8 -0
- package/dist/runner/common/turn-started.js +11 -0
- package/dist/runner/dsh/approval.js +84 -51
- package/dist/runner/dsh/client.d.ts +7 -9
- package/dist/runner/dsh/client.js +356 -287
- package/dist/runner/dsh/mux-stream.js +28 -8
- package/dist/runner/dsh/runner.d.ts +4 -3
- package/dist/runner/dsh/runner.js +88 -64
- package/dist/runner/dsh/translator.d.ts +1 -31
- package/dist/runner/dsh/translator.js +180 -178
- package/dist/runner/kimi/acp/runner.js +81 -44
- package/dist/runner/opencode/acp/error-monitor.js +5 -5
- package/dist/runner/pi/rpc/client.js +4 -13
- package/dist/runner/pi/rpc/translator.js +61 -60
- package/dist/session/claude/sessions.js +113 -101
- package/dist/session/codex/rollout-reader.js +179 -180
- package/dist/session/dsh/sessions.js +281 -231
- package/dist/session/kimi/sessions.d.ts +0 -7
- package/dist/session/kimi/sessions.js +129 -109
- package/dist/session/opencode/sessions.d.ts +0 -11
- package/dist/session/opencode/sessions.js +161 -137
- package/dist/session/session-store.d.ts +8 -0
- package/dist/session/session-store.js +98 -98
- package/package.json +1 -1
|
@@ -9,6 +9,70 @@
|
|
|
9
9
|
* first.
|
|
10
10
|
*/
|
|
11
11
|
import { getLogger } from '../../logger/index.js';
|
|
12
|
+
// --- 模块级命名函数:把状态显式传入,避免在方法内定义带决策点的闭包 ---
|
|
13
|
+
// crapper 会把方法内部闭包的决策点计入外层方法;抽到模块顶层后
|
|
14
|
+
// onWaterfall / waitForBinding 只剩选路。
|
|
15
|
+
/** 重连重投:刷新已绑定 waterfall 的应答通道,不产新 binding。 */
|
|
16
|
+
function refreshRedeliveredWaterfall(bindings, waterfallByCallId, approvalId, waterfall) {
|
|
17
|
+
const binding = bindings.get(approvalId);
|
|
18
|
+
if (!binding)
|
|
19
|
+
return;
|
|
20
|
+
binding.waterfall.clientId = waterfall.clientId;
|
|
21
|
+
if (waterfall.reason)
|
|
22
|
+
binding.waterfall.reason = waterfall.reason;
|
|
23
|
+
if (waterfall.callId)
|
|
24
|
+
waterfallByCallId.set(waterfall.callId, binding.waterfall);
|
|
25
|
+
}
|
|
26
|
+
/** 第一段:按 callId 精确匹配未绑定 audit。 */
|
|
27
|
+
function auditWithCallId(audits, bindings, callId) {
|
|
28
|
+
for (const audit of audits) {
|
|
29
|
+
if (audit.callId === callId && !bindings.has(audit.approvalId))
|
|
30
|
+
return audit;
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
/** 第二段:无 callId 的 audit,按 toolName 兜底配对。 */
|
|
35
|
+
function unboundAuditWithoutCallId(audits, bindings, toolName) {
|
|
36
|
+
for (const audit of audits) {
|
|
37
|
+
if (!audit.callId && !bindings.has(audit.approvalId) && audit.toolName === toolName) {
|
|
38
|
+
return audit;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
/** 第三段:waterfall 无 callId 时,按 toolName 找最老未绑定 audit。 */
|
|
44
|
+
function unboundAuditByToolName(audits, bindings, toolName) {
|
|
45
|
+
for (const audit of audits) {
|
|
46
|
+
if (!bindings.has(audit.approvalId) && audit.toolName === toolName)
|
|
47
|
+
return audit;
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/** 按 waterfall 是否有 callId 选路,顺序与原实现三段 for 循环一致。 */
|
|
52
|
+
function findPairableAudit(audits, bindings, waterfall) {
|
|
53
|
+
if (waterfall.callId) {
|
|
54
|
+
return (auditWithCallId(audits.values(), bindings, waterfall.callId) ??
|
|
55
|
+
unboundAuditWithoutCallId(audits.values(), bindings, waterfall.toolName));
|
|
56
|
+
}
|
|
57
|
+
return unboundAuditByToolName(audits.values(), bindings, waterfall.toolName);
|
|
58
|
+
}
|
|
59
|
+
/** 结束一次等待(幂等):清 timer、摘监听、从 waiters 移除、resolve。 */
|
|
60
|
+
function finishBindingWait(state, binding) {
|
|
61
|
+
if (state.settled)
|
|
62
|
+
return;
|
|
63
|
+
state.settled = true;
|
|
64
|
+
if (state.timer !== undefined)
|
|
65
|
+
clearTimeout(state.timer);
|
|
66
|
+
state.signal?.removeEventListener('abort', state.onAbort);
|
|
67
|
+
const set = state.waiters.get(state.approvalId);
|
|
68
|
+
set?.delete(state.finish);
|
|
69
|
+
if (set && set.size === 0)
|
|
70
|
+
state.waiters.delete(state.approvalId);
|
|
71
|
+
state.resolve(binding);
|
|
72
|
+
}
|
|
73
|
+
function abortBindingWait(state) {
|
|
74
|
+
finishBindingWait(state, undefined);
|
|
75
|
+
}
|
|
12
76
|
export class DshApprovalTracker {
|
|
13
77
|
audits = new Map();
|
|
14
78
|
waterfallByCallId = new Map();
|
|
@@ -43,45 +107,15 @@ export class DshApprovalTracker {
|
|
|
43
107
|
if (existingApprovalId) {
|
|
44
108
|
// A reconnect re-delivers the same pending event with a new Client
|
|
45
109
|
// identity. Keep the card binding but refresh the answer channel.
|
|
46
|
-
|
|
47
|
-
if (binding) {
|
|
48
|
-
binding.waterfall.clientId = waterfall.clientId;
|
|
49
|
-
if (waterfall.reason)
|
|
50
|
-
binding.waterfall.reason = waterfall.reason;
|
|
51
|
-
if (waterfall.callId) {
|
|
52
|
-
this.waterfallByCallId.set(waterfall.callId, binding.waterfall);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
110
|
+
refreshRedeliveredWaterfall(this.bindings, this.waterfallByCallId, existingApprovalId, waterfall);
|
|
55
111
|
return undefined;
|
|
56
112
|
}
|
|
57
113
|
if (waterfall.callId)
|
|
58
114
|
this.waterfallByCallId.set(waterfall.callId, waterfall);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// Some approval types omit callId on the durable audit. Pair with the
|
|
66
|
-
// oldest unbound audit for the same tool before falling back to Web UI.
|
|
67
|
-
for (const audit of this.audits.values()) {
|
|
68
|
-
if (!audit.callId &&
|
|
69
|
-
!this.bindings.has(audit.approvalId) &&
|
|
70
|
-
audit.toolName === waterfall.toolName) {
|
|
71
|
-
return this.bind(audit, waterfall);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// A missing callId is unusual but not fatal: pair with the oldest unbound
|
|
76
|
-
// audit for the same tool, preserving the audit id on the card.
|
|
77
|
-
if (!waterfall.callId) {
|
|
78
|
-
for (const audit of this.audits.values()) {
|
|
79
|
-
if (!this.bindings.has(audit.approvalId) && audit.toolName === waterfall.toolName) {
|
|
80
|
-
return this.bind(audit, waterfall);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return undefined;
|
|
115
|
+
// Some approval types omit callId on the durable audit: pair with the
|
|
116
|
+
// oldest unbound audit for the same tool before falling back to Web UI.
|
|
117
|
+
const audit = findPairableAudit(this.audits, this.bindings, waterfall);
|
|
118
|
+
return audit ? this.bind(audit, waterfall) : undefined;
|
|
85
119
|
}
|
|
86
120
|
/** Mark an audit resolved (local response or an external decision). */
|
|
87
121
|
onDecided(approvalId) {
|
|
@@ -125,24 +159,23 @@ export class DshApprovalTracker {
|
|
|
125
159
|
if (signal?.aborted)
|
|
126
160
|
return undefined;
|
|
127
161
|
return new Promise((resolve) => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
this.waiters.delete(approvalId);
|
|
139
|
-
resolve(binding);
|
|
162
|
+
// 状态显式打包;finish/onAbort 用模块级函数 + bind 绑定状态,
|
|
163
|
+
// 不在方法内定义带决策点的闭包。
|
|
164
|
+
const state = {
|
|
165
|
+
settled: false,
|
|
166
|
+
onAbort: () => { },
|
|
167
|
+
approvalId,
|
|
168
|
+
waiters: this.waiters,
|
|
169
|
+
resolve,
|
|
170
|
+
signal,
|
|
171
|
+
finish: () => { },
|
|
140
172
|
};
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
173
|
+
state.finish = finishBindingWait.bind(null, state);
|
|
174
|
+
state.onAbort = abortBindingWait.bind(null, state);
|
|
175
|
+
state.timer = setTimeout(abortBindingWait.bind(null, state), timeoutMs);
|
|
176
|
+
signal?.addEventListener('abort', state.onAbort, { once: true });
|
|
144
177
|
const set = this.waiters.get(approvalId) ?? new Set();
|
|
145
|
-
set.add(finish);
|
|
178
|
+
set.add(state.finish);
|
|
146
179
|
this.waiters.set(approvalId, set);
|
|
147
180
|
});
|
|
148
181
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* `sessionEvents()` adds per-session filtering, reconnect + follow-snapshot
|
|
20
20
|
* replay, and seq-based dedup.
|
|
21
21
|
*/
|
|
22
|
-
import type { DshApprovalStreamItem, DshCommandResult, DshModelCatalogValue, DshModelSelection, DshOpenTurnState, DshPermissionCatalogValue, DshJobView, DshPresetListValue, DshProjectionItem, DshProjectionSnapshot, DshQuestion, DshRemoteEventOutcome, DshSessionPageValue, DshStreamItem } from '../../dsh/types.js';
|
|
22
|
+
import type { DshApprovalStreamItem, DshCommandResult, DshFollowSnapshot, DshModelCatalogValue, DshModelSelection, DshOpenTurnState, DshPermissionCatalogValue, DshJobView, DshPresetListValue, DshProjectionItem, DshProjectionSnapshot, DshQuestion, DshRemoteEventOutcome, DshSessionEvent, DshSessionPageValue, DshStreamItem } from '../../dsh/types.js';
|
|
23
23
|
import type { GoalView } from '../types.js';
|
|
24
24
|
export { DshError } from './errors.js';
|
|
25
25
|
interface WebSocketMessageEvent {
|
|
@@ -105,8 +105,11 @@ export declare class DshClient {
|
|
|
105
105
|
signal?: AbortSignal;
|
|
106
106
|
timeoutMs?: number;
|
|
107
107
|
}): Promise<unknown>;
|
|
108
|
-
/**
|
|
109
|
-
|
|
108
|
+
/** One unary POST attempt: obtain cookie, then post; both stages may ask to
|
|
109
|
+
* retry once (401 → re-mint cookie); all other failures throw DshError. */
|
|
110
|
+
private attemptUnary;
|
|
111
|
+
private obtainUnaryCookie;
|
|
112
|
+
private postUnary;
|
|
110
113
|
/** Create a session. Pass `agentPreset` to pin the session's preset (fixed at
|
|
111
114
|
* creation). */
|
|
112
115
|
createSession(payload: {
|
|
@@ -157,8 +160,6 @@ export declare class DshClient {
|
|
|
157
160
|
signal?: AbortSignal;
|
|
158
161
|
timeoutMs?: number;
|
|
159
162
|
}): Promise<void>;
|
|
160
|
-
/** Hand one waterfall delivery back with `next` (another answerer owns it). */
|
|
161
|
-
private delegateWaterfall;
|
|
162
163
|
/**
|
|
163
164
|
* Return the highest event `seq` currently persisted for the session.
|
|
164
165
|
*
|
|
@@ -279,9 +280,6 @@ export declare class DshClient {
|
|
|
279
280
|
* `next` so a different lark-remote workspace cannot park it.
|
|
280
281
|
*/
|
|
281
282
|
approvalEvents(sessionId: string, signal: AbortSignal): AsyncGenerator<DshApprovalStreamItem>;
|
|
282
|
-
/** Translate one durable event into a stream item (approvals are surfaced
|
|
283
|
-
* separately; everything else is forwarded to the runner). */
|
|
284
|
-
private eventItem;
|
|
285
283
|
/**
|
|
286
284
|
* Per-session subscription: yields session events, assistant stream chunks
|
|
287
285
|
* and approval notices for `sessionId`, auto-reconnecting on stream
|
|
@@ -312,7 +310,7 @@ export declare class DshClient {
|
|
|
312
310
|
* 返回 seq 升序的完整回放序列(回填 + 快照记录;与 lastSeq 重叠的条目
|
|
313
311
|
* 由回放循环的 seq 去重兜住)。
|
|
314
312
|
*/
|
|
315
|
-
|
|
313
|
+
replaySnapshotGap(sessionId: string, signal: AbortSignal, lastSeq: number, frame: DshFollowSnapshot): Promise<DshSessionEvent[]>;
|
|
316
314
|
/**
|
|
317
315
|
* Host-wide live projection stream (`session/control`).
|
|
318
316
|
*
|