@tbox.cn/tboxcode-dsh-sdk 0.0.0-stage → 0.1.0-rc.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/lib/index.d.ts +722 -0
- package/lib/index.js +5 -0
- package/package.json +27 -3
- package/README.md +0 -3
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
import { CommandDescriptorLike, ModeKnobs, SkillSummaryLike } from "@tbox.cn/dsh-acp-bridge-core";
|
|
2
|
+
import { SessionUpdate } from "@agentclientprotocol/sdk";
|
|
3
|
+
import { AgentLike, ConfigModelSelection, HostAgentHandle, HostStreamFrame, LlmCatalogDeps, PersistedHeader, SessionDeps, SessionLike, SharedAcpCore } from "@tbox.cn/dsh-acp-full";
|
|
4
|
+
import { IncomingMessage, Server } from "node:http";
|
|
5
|
+
|
|
6
|
+
//#region src/supervisor.d.ts
|
|
7
|
+
type SupervisorPhase = 'idle' | 'booting' | 'standby' | 'starting' | 'ready' | 'restarting' | 'failed-permanent' | 'failed-protocol' | 'disposed';
|
|
8
|
+
interface SupervisorOptions {
|
|
9
|
+
/**
|
|
10
|
+
* cli 启动命令(argv 前缀,末尾追加 'server')。缺省 = PATH 上的
|
|
11
|
+
* `tboxcode-dsh`(机器路径裸命令零 flag 契约);测试注入假 bin。
|
|
12
|
+
*/
|
|
13
|
+
command?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* start 释放形态(warmup 规格——释放时机归 Supervisor,cli 状态机唯一):
|
|
16
|
+
* immediate = 常规(收 standby 立即发 start);on-first-connection = 预热
|
|
17
|
+
* (首连接触发释放——connect() 挂起到 ready)。
|
|
18
|
+
*/
|
|
19
|
+
startMode?: 'immediate' | 'on-first-connection';
|
|
20
|
+
/** 就绪确认超时(boot→ready 全程;超时 kill + 瞬时退避)。缺省 120s。 */
|
|
21
|
+
readyTimeoutMs?: number;
|
|
22
|
+
/** 退避基数(缺省 1000ms;序列 = min(base×2^attempt, max)——opencode 先例)。 */
|
|
23
|
+
backoffBaseMs?: number;
|
|
24
|
+
/** 退避上限(缺省 5000ms)。 */
|
|
25
|
+
backoffMaxMs?: number;
|
|
26
|
+
/** 连续重启上限(缺省 3——耗尽即 failed-permanent 上抛)。 */
|
|
27
|
+
maxRestartAttempts?: number;
|
|
28
|
+
/** stderr 环形缓冲行容量(缺省 1000——ready-channel-v2 建议值)。 */
|
|
29
|
+
ringBufferLines?: number;
|
|
30
|
+
/** 子进程环境(叠加在 process.env 上)。 */
|
|
31
|
+
env?: Record<string, string>;
|
|
32
|
+
/** 进度日志(stderr 通道由消费方收口;禁 token——安全纪律)。 */
|
|
33
|
+
log?: (message: string) => void;
|
|
34
|
+
}
|
|
35
|
+
interface ConnectionCredentials {
|
|
36
|
+
baseUrl: string;
|
|
37
|
+
cookie: string;
|
|
38
|
+
port: number;
|
|
39
|
+
}
|
|
40
|
+
/** 子进程适配面(默认实现 = child_process 行流包装;测试注入假件)。 */
|
|
41
|
+
interface SupervisorChild {
|
|
42
|
+
writeStdin(chunk: string): void;
|
|
43
|
+
onStdoutLine(listener: (line: string) => void): void;
|
|
44
|
+
onStderrLine(listener: (line: string) => void): void;
|
|
45
|
+
onExit(listener: (code: number | null) => void): void;
|
|
46
|
+
kill(signal?: 'SIGTERM' | 'SIGKILL'): void;
|
|
47
|
+
}
|
|
48
|
+
type SupervisorSpawner = (argv: string[]) => SupervisorChild;
|
|
49
|
+
/** Supervisor 部署错误(退出码 2/3 路由或退避耗尽——消费方上抛面)。 */
|
|
50
|
+
declare class SupervisorDeploymentError extends Error {
|
|
51
|
+
readonly kind: 'permanent' | 'protocol' | 'exhausted';
|
|
52
|
+
readonly report: string;
|
|
53
|
+
constructor(kind: 'permanent' | 'protocol' | 'exhausted', message: string, report: string);
|
|
54
|
+
}
|
|
55
|
+
/** 默认凭据交换:GET /connect?interactions=answer → 302 + v2 cookie(S2a 定案通道)。 */
|
|
56
|
+
declare function exchangeCredentialsViaConnect(port: number, token: string): Promise<string>;
|
|
57
|
+
declare class Supervisor {
|
|
58
|
+
#private;
|
|
59
|
+
constructor(options?: SupervisorOptions, spawner?: SupervisorSpawner, exchange?: (port: number, token: string) => Promise<string>);
|
|
60
|
+
phase(): SupervisorPhase;
|
|
61
|
+
onPhaseChange(listener: (phase: SupervisorPhase) => void): () => void;
|
|
62
|
+
/** 启动(spawn → standby → start 释放 → ready)。失败(永久 / 偏斜 / 退避耗尽)抛部署错误。 */
|
|
63
|
+
start(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* 网关连接凭据(pre-standby 连接统一挂到 ready——warmup 规格;on-first-connection
|
|
66
|
+
* 形态下首调用触发 start 释放)。重启后缓存失效(凭据轮换——新 port + 新 token)。
|
|
67
|
+
*/
|
|
68
|
+
connect(): Promise<ConnectionCredentials>;
|
|
69
|
+
/**
|
|
70
|
+
* 强制重新交换凭据(绕过 generation 缓存——R0 定案:dsh peer 生命周期
|
|
71
|
+
* 绑定连接面,mux 断开即 PeerId 销毁、旧 cookie 永久 401;再入通道)。
|
|
72
|
+
*/
|
|
73
|
+
reconnect(): Promise<ConnectionCredentials>;
|
|
74
|
+
/** 崩溃导出(环形缓冲 stderr + 退出码序列 + 相位历史——诊断自包含)。 */
|
|
75
|
+
crashReport(): string;
|
|
76
|
+
/** 停机(SIGTERM → 3s 宽限 → SIGKILL;等待子进程退出)。 */
|
|
77
|
+
dispose(): Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/wire.d.ts
|
|
81
|
+
/**
|
|
82
|
+
* wire 契约(手写恰两处之二——sdk 对外面;规格真源 = dsh 0.2.1-rc.2 源码形状,
|
|
83
|
+
* 逐字段锚点见各类型注释;verify:upgrade 第五项帧比对守护漂移)。
|
|
84
|
+
*
|
|
85
|
+
* 编译域 / wire 域二分(bridge-typing-boundary-hardening):本文件是 wire 域——
|
|
86
|
+
* dsh wire 形状对齐的子集手写(sdk 自有),永不内联跨仓类型;编译域直借
|
|
87
|
+
* (import type @deepseek-ai/*)住 bridge-core,不进本包。
|
|
88
|
+
*/
|
|
89
|
+
/** dsh wire JSON 值域(JsonValue 子集声明——wire 域不做深校验,envelope 级守卫)。 */
|
|
90
|
+
type WireJson = string | number | boolean | null | readonly WireJson[] | {
|
|
91
|
+
readonly [key: string]: WireJson;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Session 事件 wire envelope(dsh:`packages/api/session-controller/src/types.ts:476-487`
|
|
95
|
+
* SessionWireEvent——0.2.1 形状:type/seq/time/data 四必备 + ignorable /
|
|
96
|
+
* sourceEventSeqs / surfaceOp 三可选)。
|
|
97
|
+
*/
|
|
98
|
+
interface WireSessionEvent {
|
|
99
|
+
readonly type: string;
|
|
100
|
+
readonly seq: number;
|
|
101
|
+
readonly time: number;
|
|
102
|
+
readonly data: WireJson;
|
|
103
|
+
readonly ignorable?: true;
|
|
104
|
+
readonly sourceEventSeqs?: WireJson;
|
|
105
|
+
readonly surfaceOp?: WireJson;
|
|
106
|
+
}
|
|
107
|
+
/** 会话寻址(dsh SessionAddress——durable 会话 id;subagent 联合面桥内不消费)。 */
|
|
108
|
+
type WireSessionAddress = string;
|
|
109
|
+
/** follow 请求参数(dsh:`packages/api/session-controller/src/types.ts:504-509`——无 cursor 参数)。 */
|
|
110
|
+
interface WireFollowRequest {
|
|
111
|
+
readonly address: WireSessionAddress;
|
|
112
|
+
readonly maxMessages?: number;
|
|
113
|
+
readonly assistantStream?: true;
|
|
114
|
+
}
|
|
115
|
+
/** 重连 opening snapshot 的活跃 attempt(assistantStream 基线契约——stream.spec 收口语义)。 */
|
|
116
|
+
interface WireAssistantStreamAttempt {
|
|
117
|
+
readonly attemptId: string;
|
|
118
|
+
readonly startedAfterSeq: number;
|
|
119
|
+
readonly turn: number;
|
|
120
|
+
readonly step: number;
|
|
121
|
+
readonly nextIndex: number;
|
|
122
|
+
}
|
|
123
|
+
/** assistant-stream 基线(重连衔接断言面——live 首帧 revision === baseline.revision + 1)。 */
|
|
124
|
+
interface WireAssistantStreamBaseline {
|
|
125
|
+
readonly revision: number;
|
|
126
|
+
readonly activeAttempt?: {
|
|
127
|
+
readonly attemptId: string;
|
|
128
|
+
readonly nextIndex: number;
|
|
129
|
+
};
|
|
130
|
+
readonly attempts?: readonly WireAssistantStreamAttempt[];
|
|
131
|
+
}
|
|
132
|
+
/** assistant-stream live 帧(dsh agent runtime-types 呈现帧的 wire 子集)。 */
|
|
133
|
+
interface WireAssistantStreamFrame {
|
|
134
|
+
readonly attemptId: string;
|
|
135
|
+
readonly index: number;
|
|
136
|
+
readonly revision: number;
|
|
137
|
+
readonly chunk?: {
|
|
138
|
+
readonly type: string;
|
|
139
|
+
readonly text?: string;
|
|
140
|
+
};
|
|
141
|
+
readonly finish?: unknown;
|
|
142
|
+
}
|
|
143
|
+
/** 会话 wire 头(dsh:`packages/api/session-controller/src/types.ts:449-466` SessionWireHeader)。 */
|
|
144
|
+
interface WireSessionHeader {
|
|
145
|
+
readonly version: number;
|
|
146
|
+
readonly id: string;
|
|
147
|
+
readonly createdAt: number;
|
|
148
|
+
readonly cwd?: string;
|
|
149
|
+
readonly parentSession?: string;
|
|
150
|
+
readonly isSeeded: boolean;
|
|
151
|
+
readonly origin?: 'subagent';
|
|
152
|
+
readonly delegationDepth?: number;
|
|
153
|
+
readonly agentPreset?: string;
|
|
154
|
+
}
|
|
155
|
+
/** 历史页记录(dsh SessionHistoryRecord = {type:'event', event})。 */
|
|
156
|
+
interface WireHistoryRecord {
|
|
157
|
+
readonly type: 'event';
|
|
158
|
+
readonly event: WireSessionEvent;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* follow 流帧(dsh:`packages/api/session-controller/src/types.ts:570-578`
|
|
162
|
+
* SessionFollowFrame——opening snapshot(header + cursor + records + hasMore +
|
|
163
|
+
* projections + assistantStream 基线)→ 有序 event 帧 → assistant-stream 帧)。
|
|
164
|
+
*/
|
|
165
|
+
type WireFollowFrame = {
|
|
166
|
+
readonly type: 'snapshot';
|
|
167
|
+
readonly header: WireSessionHeader;
|
|
168
|
+
readonly cursor: number;
|
|
169
|
+
readonly records: readonly WireHistoryRecord[];
|
|
170
|
+
readonly hasMore: boolean;
|
|
171
|
+
readonly projections: WireJson;
|
|
172
|
+
readonly assistantStream?: WireAssistantStreamBaseline;
|
|
173
|
+
} | WireHistoryRecord | {
|
|
174
|
+
readonly type: 'assistant-stream';
|
|
175
|
+
readonly frame: WireAssistantStreamFrame;
|
|
176
|
+
};
|
|
177
|
+
/** 回看页(dsh:`packages/api/session-controller/src/types.ts:564-568` SessionPage——gap 补齐通道)。 */
|
|
178
|
+
interface WirePage {
|
|
179
|
+
readonly records: readonly WireHistoryRecord[];
|
|
180
|
+
readonly hasMore: boolean;
|
|
181
|
+
}
|
|
182
|
+
declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
183
|
+
declare function parseWireSessionEvent(raw: unknown): WireSessionEvent | null;
|
|
184
|
+
declare function parseWireHistoryRecord(raw: unknown): WireHistoryRecord | null;
|
|
185
|
+
declare function parseWireFollowFrame(raw: unknown): WireFollowFrame | null;
|
|
186
|
+
declare function parseWirePage(raw: unknown): WirePage | null;
|
|
187
|
+
/** $events ready 帧(clientId + host——连接代际身份)。 */
|
|
188
|
+
interface WireEventReadyFrame {
|
|
189
|
+
readonly type: 'ready';
|
|
190
|
+
readonly clientId: string;
|
|
191
|
+
readonly host: {
|
|
192
|
+
readonly home: string;
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/** $events 单向通知帧(event = allowlist 词汇;args = 载荷数组)。 */
|
|
196
|
+
interface WireEventEmitFrame {
|
|
197
|
+
readonly type: 'emit';
|
|
198
|
+
readonly event: string;
|
|
199
|
+
readonly args: readonly WireJson[];
|
|
200
|
+
}
|
|
201
|
+
/** $events waterfall 帧(双向事件——answerer 应答经 $events/result)。 */
|
|
202
|
+
interface WireEventWaterfallFrame {
|
|
203
|
+
readonly type: 'waterfall';
|
|
204
|
+
readonly event: string;
|
|
205
|
+
readonly eventId: string;
|
|
206
|
+
readonly agentId: string;
|
|
207
|
+
readonly request: Readonly<Record<string, WireJson>>;
|
|
208
|
+
}
|
|
209
|
+
/** waterfall 取消帧(宿主侧取消在途请求)。 */
|
|
210
|
+
interface WireEventCancellationFrame {
|
|
211
|
+
readonly type: 'cancel';
|
|
212
|
+
readonly eventId: string;
|
|
213
|
+
}
|
|
214
|
+
type WireEventFrame = WireEventReadyFrame | WireEventEmitFrame | WireEventWaterfallFrame | WireEventCancellationFrame;
|
|
215
|
+
declare function parseWireEventFrame(raw: unknown): WireEventFrame | null;
|
|
216
|
+
/** waterfall 应答 outcome 三态(dsh:`packages/api/gateway/src/stream-protocol.ts:102-140`)。 */
|
|
217
|
+
type WireEventOutcome = {
|
|
218
|
+
readonly kind: 'next';
|
|
219
|
+
} | {
|
|
220
|
+
readonly kind: 'result';
|
|
221
|
+
readonly value?: WireJson;
|
|
222
|
+
} | {
|
|
223
|
+
readonly kind: 'rejected';
|
|
224
|
+
readonly error: {
|
|
225
|
+
readonly code?: string;
|
|
226
|
+
readonly message: string;
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
//#endregion
|
|
230
|
+
//#region src/carrier.d.ts
|
|
231
|
+
/** dsh Remote 错误({ok:false,error} 面——mapRpcError 的载体二输入)。 */
|
|
232
|
+
interface CarrierRpcErrorShape {
|
|
233
|
+
readonly code: string;
|
|
234
|
+
readonly message: string;
|
|
235
|
+
readonly details?: unknown;
|
|
236
|
+
}
|
|
237
|
+
declare class CarrierRpcError extends Error {
|
|
238
|
+
readonly code: string;
|
|
239
|
+
readonly details: unknown;
|
|
240
|
+
constructor(shape: CarrierRpcErrorShape);
|
|
241
|
+
}
|
|
242
|
+
/** 传输层错误(非 JSON-RPC 面:HTTP 非 200 / WS 关闭 / envelope 畸形)。 */
|
|
243
|
+
declare class CarrierTransportError extends Error {
|
|
244
|
+
constructor(message: string);
|
|
245
|
+
}
|
|
246
|
+
interface StreamHandlers<T> {
|
|
247
|
+
onItem(value: T): void;
|
|
248
|
+
onEnd?(): void;
|
|
249
|
+
onError?(error: CarrierRpcErrorShape): void;
|
|
250
|
+
onClose?(hadError: boolean): void;
|
|
251
|
+
}
|
|
252
|
+
interface StreamHandle {
|
|
253
|
+
/** 取消(上行 cancel 帧 + 关闭插座;幂等)。 */
|
|
254
|
+
cancel(): void;
|
|
255
|
+
}
|
|
256
|
+
interface EventStreamHandlers {
|
|
257
|
+
onReady(frame: WireEventReadyFrame): void;
|
|
258
|
+
onEmit(frame: WireEventEmitFrame): void;
|
|
259
|
+
onWaterfall(frame: WireEventWaterfallFrame): void;
|
|
260
|
+
onCancel(frame: WireEventCancellationFrame): void;
|
|
261
|
+
onClose?(hadError: boolean): void;
|
|
262
|
+
}
|
|
263
|
+
interface EventStreamHandle {
|
|
264
|
+
/** waterfall 应答($events/result unary——outcome 三态)。 */
|
|
265
|
+
respond(eventId: string, outcome: WireEventOutcome): Promise<void>;
|
|
266
|
+
close(): void;
|
|
267
|
+
}
|
|
268
|
+
interface DshCarrierOptions {
|
|
269
|
+
/** dsh web 根(http://127.0.0.1:<port>——loopback 上游硬约束)。 */
|
|
270
|
+
baseUrl: string;
|
|
271
|
+
/** v2 API cookie(Supervisor.connect() 交付;HttpOnly 值原样注入)。 */
|
|
272
|
+
cookie: string;
|
|
273
|
+
/**
|
|
274
|
+
* 凭据再交换(可选——mux 断开销毁 PeerId 后的自愈通道)。R0 定案:dsh
|
|
275
|
+
* peer 生命周期绑定连接面(admitConnection release 即 peers.delete +
|
|
276
|
+
* peer.dispose),mux 断开后旧 cookie 永久 401;注入此通道后 carrier 在
|
|
277
|
+
* 重开 mux 前自动再交换,unary 遇 401 亦触发单飞刷新 + 一次重试。
|
|
278
|
+
*/
|
|
279
|
+
refreshCredentials?: () => Promise<{
|
|
280
|
+
baseUrl: string;
|
|
281
|
+
cookie: string;
|
|
282
|
+
}>;
|
|
283
|
+
}
|
|
284
|
+
declare class DshCarrier {
|
|
285
|
+
#private;
|
|
286
|
+
constructor(options: DshCarrierOptions);
|
|
287
|
+
/** unary RPC(args 内层 = 方法签名参数名原样——wire 陷阱的调用方契约)。 */
|
|
288
|
+
unary<T extends WireJson>(method: string, args: Record<string, WireJson>): Promise<T>;
|
|
289
|
+
/**
|
|
290
|
+
* 通用 stream(单 mux 多路复用:open → item/end/error;cancel = 上行
|
|
291
|
+
* cancel 帧——插座为全体流共享,不随单流关闭)。mux 断开时所有活跃流
|
|
292
|
+
* 收 onError + onClose(hadError)——重开由调用方退避逻辑承接(重开经
|
|
293
|
+
* ensureMux 自动完成凭据再交换)。
|
|
294
|
+
*/
|
|
295
|
+
openStream<T>(endpoint: string, args: Record<string, WireJson>, handlers: StreamHandlers<T>): StreamHandle;
|
|
296
|
+
/**
|
|
297
|
+
* `$events` 事件流(跨切事件通道——allowlist 词汇:waterfall 两件 answerer
|
|
298
|
+
* 真通道 + emit 十余件;session 事件词汇走 follow 流,S2a probe ② 定案)。
|
|
299
|
+
*/
|
|
300
|
+
openEvents(handlers: EventStreamHandlers): EventStreamHandle;
|
|
301
|
+
/** 释放全部插座(网关停机路径——mux 关闭即 server 侧 peer 释放)。 */
|
|
302
|
+
dispose(): void;
|
|
303
|
+
}
|
|
304
|
+
//#endregion
|
|
305
|
+
//#region src/decode.d.ts
|
|
306
|
+
/** 消费面 brand(brand-cast 唯一 cast 点的编译标记)。 */
|
|
307
|
+
declare const CONSUMABLE_EVENT_BRAND: unique symbol;
|
|
308
|
+
/** 过分类门的项目事件(brand 后交投影管线——sdk 外不得自造)。 */
|
|
309
|
+
type ConsumableSessionEvent = WireSessionEvent & {
|
|
310
|
+
readonly [CONSUMABLE_EVENT_BRAND]: true;
|
|
311
|
+
};
|
|
312
|
+
type DecodedWireEvent = {
|
|
313
|
+
readonly kind: 'consumable';
|
|
314
|
+
readonly event: ConsumableSessionEvent;
|
|
315
|
+
} | {
|
|
316
|
+
readonly kind: 'opaque';
|
|
317
|
+
readonly event: WireSessionEvent;
|
|
318
|
+
readonly level: 'debug' | 'warn';
|
|
319
|
+
};
|
|
320
|
+
interface DecodeStats {
|
|
321
|
+
invalid: number;
|
|
322
|
+
opaqueDebug: number;
|
|
323
|
+
opaqueWarn: number;
|
|
324
|
+
consumable: number;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* wire 事件解码:envelope 校验 → 分类门 → project 消费字段守卫(data 必为
|
|
328
|
+
* JSON 对象——投影鸭子读的最小前提;字段级形状归 wireFixtures 等价 runner
|
|
329
|
+
* 与投影自身鸭子读域)→ brand-cast。skip / unknown → opaque 降级分级。
|
|
330
|
+
*/
|
|
331
|
+
declare function decodeWireEvent(raw: unknown, stats?: DecodeStats): DecodedWireEvent | null;
|
|
332
|
+
//#endregion
|
|
333
|
+
//#region src/gateway/follow-pool.d.ts
|
|
334
|
+
interface FollowPoolHandlers {
|
|
335
|
+
/** opening snapshot 首达(每条流生命周期一次;重开再达)。 */
|
|
336
|
+
onSnapshot(header: WireSessionHeader, cursor: number, projections: WireJson, baseline?: WireAssistantStreamBaseline): void;
|
|
337
|
+
/** 过分类门的 journal 事件(按 seq 有序;opaque 不回调)。 */
|
|
338
|
+
onEvent(event: ConsumableSessionEvent): void;
|
|
339
|
+
/** assistant-stream 呈现帧(衔接校验:live 首 frame.revision === baseline.revision + 1)。 */
|
|
340
|
+
onAssistantStream(frame: WireAssistantStreamFrame): void;
|
|
341
|
+
/** 流断(重开由池负责——error/close/error 帧三入口归一)。 */
|
|
342
|
+
onDown(reason: string): void;
|
|
343
|
+
}
|
|
344
|
+
interface FollowHandle {
|
|
345
|
+
close(): void;
|
|
346
|
+
}
|
|
347
|
+
interface FollowPoolStats {
|
|
348
|
+
live: number;
|
|
349
|
+
reopening: number;
|
|
350
|
+
decoded: DecodeStats;
|
|
351
|
+
gapsRepaired: number;
|
|
352
|
+
}
|
|
353
|
+
declare class FollowPool {
|
|
354
|
+
#private;
|
|
355
|
+
constructor(carrier: DshCarrier, options?: {
|
|
356
|
+
reopenBaseMs?: number;
|
|
357
|
+
});
|
|
358
|
+
/** 打开(幂等——已 live 返回既有订阅句柄;重开由池内部接管)。 */
|
|
359
|
+
open(sessionId: string, handlers: FollowPoolHandlers): FollowHandle;
|
|
360
|
+
close(sessionId: string): void;
|
|
361
|
+
stats(): FollowPoolStats;
|
|
362
|
+
/**
|
|
363
|
+
* 全量读取:follow snapshot + page 环拼接到 hasMore=false → seq 去重排序 +
|
|
364
|
+
* 连续性断言(dense zero-based 前缀——跳号即 CarrierRpcError fail-fast)。
|
|
365
|
+
*/
|
|
366
|
+
readAll(sessionId: string): Promise<{
|
|
367
|
+
header: WireSessionHeader;
|
|
368
|
+
events: ConsumableSessionEvent[];
|
|
369
|
+
projections: WireJson;
|
|
370
|
+
}>;
|
|
371
|
+
}
|
|
372
|
+
//#endregion
|
|
373
|
+
//#region src/gateway/extension-points.d.ts
|
|
374
|
+
/** 连接上下文(钩子签名——request 面 = server→client 请求,answerer 切片 6 消费)。 */
|
|
375
|
+
interface ConnContext {
|
|
376
|
+
readonly connId: string;
|
|
377
|
+
readonly caps: {
|
|
378
|
+
elicitation: boolean;
|
|
379
|
+
};
|
|
380
|
+
request(method: string, params: unknown): Promise<unknown>;
|
|
381
|
+
notify(method: string, params: unknown): Promise<void>;
|
|
382
|
+
}
|
|
383
|
+
interface AcpGatewayHooks {
|
|
384
|
+
/** 入站参数变换(box 资源解析对位——schema 校验前面)。null = 拒绝。 */
|
|
385
|
+
transformInbound?(method: string, params: unknown, conn: ConnContext): Promise<unknown | null> | unknown | null;
|
|
386
|
+
/** 出站 update 变换(box 呈现派生对位)。null = 该连接丢弃。 */
|
|
387
|
+
transformOutbound?(update: SessionUpdate, conn: ConnContext): SessionUpdate | null;
|
|
388
|
+
/** `_tbox.cn/*` 本地方法注册表(box 平台方法——不 forward server)。 */
|
|
389
|
+
methods?: Record<string, (params: unknown, conn: ConnContext) => Promise<unknown>>;
|
|
390
|
+
/** 入站 content block 变换(image/tbox_url codec——载体一 contentCodec 对位)。 */
|
|
391
|
+
decodeContent?(block: unknown, conn: ConnContext): Promise<unknown> | unknown;
|
|
392
|
+
/** 扇出覆写(默认 = 会话亲和集 − echo 抑制)。 */
|
|
393
|
+
fanout?(update: SessionUpdate, defaultTargets: readonly string[]): readonly string[] | undefined;
|
|
394
|
+
/** 亲和生命周期钩子(answerer 宽限重问触发面——bind 即 attach、unbind 即失联)。 */
|
|
395
|
+
onSessionBind?(connId: string, sessionId: string): void;
|
|
396
|
+
onSessionUnbind?(connId: string, sessionId: string): void;
|
|
397
|
+
}
|
|
398
|
+
/** fail-open 执行器:throw → warn + fallback(钩子纪律的单一实现点)。 */
|
|
399
|
+
declare function runHookOpen<T>(logger: {
|
|
400
|
+
warn(m: string): void;
|
|
401
|
+
}, label: string, hook: () => T, fallback: T): Promise<T>;
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/gateway/fanout.d.ts
|
|
404
|
+
type RouterLogger = {
|
|
405
|
+
warn(message: string): void;
|
|
406
|
+
info(message: string): void;
|
|
407
|
+
debug(message: string): void;
|
|
408
|
+
};
|
|
409
|
+
declare class FanoutRouter {
|
|
410
|
+
#private;
|
|
411
|
+
constructor(logger: RouterLogger, hooks?: AcpGatewayHooks);
|
|
412
|
+
attachConnection(connId: string, send: (frame: unknown) => void, ctx: ConnContext): void;
|
|
413
|
+
detachConnection(connId: string): void;
|
|
414
|
+
/** 会话亲和登记(uplink 泵——session/new|load|resume 成功响应)。 */
|
|
415
|
+
bind(connId: string, sessionId: string): void;
|
|
416
|
+
unbind(connId: string, sessionId: string): void;
|
|
417
|
+
/** 会话当前绑定连接读面(answerer 竞速的 eligible 数据源)。 */
|
|
418
|
+
boundConnIds(sessionId: string): readonly string[];
|
|
419
|
+
/** 连接的 ConnContext 读面(answerer dispatch——server→client 请求直发)。 */
|
|
420
|
+
ctxOf(connId: string): ConnContext | undefined;
|
|
421
|
+
/** 结算通知扇出(answerer resolved——_tbox.cn 扩展帧)。 */
|
|
422
|
+
routeResolved(method: string, payload: Record<string, unknown>, excludeConnId?: string): void;
|
|
423
|
+
/** 回放计数(uplink load 生命周期——begin 于请求、take 于响应)。 */
|
|
424
|
+
beginReplayCount(connId: string): void;
|
|
425
|
+
takeReplayCount(connId: string): number | undefined;
|
|
426
|
+
/** turn origin 记账(uplink prompt 钩子——echo 抑制窗口开启/关闭)。 */
|
|
427
|
+
setTurnOrigin(sessionId: string, connId: string): void;
|
|
428
|
+
clearTurnOrigin(sessionId: string): void;
|
|
429
|
+
/** 共享核 io.notify 唯一入口(session/update 帧路由)。 */
|
|
430
|
+
route(update: SessionUpdate & {
|
|
431
|
+
sessionId?: string;
|
|
432
|
+
}): void;
|
|
433
|
+
/** 共享核 io.extNotify 出口(`_tbox.cn/*`——payload.sessionId 在场则亲和路由)。 */
|
|
434
|
+
routeExt(notification: {
|
|
435
|
+
method: string;
|
|
436
|
+
payload: Record<string, unknown>;
|
|
437
|
+
}, opts?: {
|
|
438
|
+
excludeConnId?: string;
|
|
439
|
+
}): void;
|
|
440
|
+
stats(): {
|
|
441
|
+
connections: number;
|
|
442
|
+
dropped: number;
|
|
443
|
+
suppressed: number;
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
//#endregion
|
|
447
|
+
//#region src/gateway/session-deps.d.ts
|
|
448
|
+
type GatewayLogger = {
|
|
449
|
+
warn(message: string): void;
|
|
450
|
+
info(message: string): void;
|
|
451
|
+
debug(message: string): void;
|
|
452
|
+
};
|
|
453
|
+
/** followup 鸭子面(桥经 cast 调用——载体一 host agent 同款,见 SessionChannel#runPromptPath)。 */
|
|
454
|
+
type GatewayAgentLike = AgentLike & {
|
|
455
|
+
followup(message: {
|
|
456
|
+
id: string;
|
|
457
|
+
content: readonly unknown[];
|
|
458
|
+
}): void;
|
|
459
|
+
};
|
|
460
|
+
/** 网关侧会话状态(句柄注册表值——follow 事件交付的身份锚)。 */
|
|
461
|
+
interface RemoteSessionState {
|
|
462
|
+
readonly id: string;
|
|
463
|
+
readonly session: SessionLike;
|
|
464
|
+
readonly agent: GatewayAgentLike;
|
|
465
|
+
header: WireSessionHeader;
|
|
466
|
+
projections: WireJson;
|
|
467
|
+
/** installModelSelection 注册的 'agent/request' 钩子(selection 请求时点提取)。 */
|
|
468
|
+
selectionProbe: ((payload: unknown, next: () => Promise<unknown>) => Promise<unknown>) | undefined;
|
|
469
|
+
lastPushedSelection: string | undefined;
|
|
470
|
+
/** 挂起 prompt 记账(pushPrompt 置位 / turn/end 复位——中断状态机观测面)。 */
|
|
471
|
+
promptInflight: boolean;
|
|
472
|
+
}
|
|
473
|
+
declare class RpcSessionDeps implements SessionDeps {
|
|
474
|
+
#private;
|
|
475
|
+
readonly logger: GatewayLogger;
|
|
476
|
+
constructor(deps: {
|
|
477
|
+
carrier: DshCarrier;
|
|
478
|
+
pool: FollowPool;
|
|
479
|
+
logger: GatewayLogger;
|
|
480
|
+
});
|
|
481
|
+
createAgent(options: Parameters<SessionDeps['createAgent']>[0]): Promise<HostAgentHandle>;
|
|
482
|
+
resumeAgent(options: Parameters<SessionDeps['resumeAgent']>[0]): Promise<HostAgentHandle>;
|
|
483
|
+
readonly persistence: {
|
|
484
|
+
stat: (sessionId: string, _opts: {
|
|
485
|
+
signal?: AbortSignal;
|
|
486
|
+
}) => Promise<{
|
|
487
|
+
header: PersistedHeader;
|
|
488
|
+
} | undefined>;
|
|
489
|
+
list: (_opts: {
|
|
490
|
+
signal?: AbortSignal;
|
|
491
|
+
}) => Promise<Array<{
|
|
492
|
+
header: PersistedHeader;
|
|
493
|
+
}>>;
|
|
494
|
+
open: (sessionId: string, _opts: {
|
|
495
|
+
signal?: AbortSignal;
|
|
496
|
+
}) => Promise<{
|
|
497
|
+
read(opts?: {
|
|
498
|
+
signal?: AbortSignal;
|
|
499
|
+
}): Promise<{
|
|
500
|
+
events: readonly never[];
|
|
501
|
+
}>;
|
|
502
|
+
close(): Promise<void>;
|
|
503
|
+
}>;
|
|
504
|
+
};
|
|
505
|
+
readonly sessionStore: {
|
|
506
|
+
get: (sessionId: string) => unknown;
|
|
507
|
+
flush: (session: SessionLike) => Promise<void>;
|
|
508
|
+
};
|
|
509
|
+
readonly llm: LlmCatalogDeps;
|
|
510
|
+
applyModeKnobs(session: SessionLike, _agent: AgentLike, knobs: ModeKnobs): void | Promise<void>;
|
|
511
|
+
defaultSelection(): ConfigModelSelection | undefined;
|
|
512
|
+
executeCommand(agent: AgentLike, line: string, _signal?: AbortSignal): Promise<{
|
|
513
|
+
commandId: string;
|
|
514
|
+
} | undefined>;
|
|
515
|
+
listCommands(agent: AgentLike): Promise<ReadonlyArray<CommandDescriptorLike>>;
|
|
516
|
+
listUserInvocableSkills(agent: AgentLike): Promise<ReadonlyArray<SkillSummaryLike>>;
|
|
517
|
+
onSessionEvent(listener: (session: never, event: never) => void): () => void;
|
|
518
|
+
onAssistantStream(listener: (payload: {
|
|
519
|
+
agent: AgentLike;
|
|
520
|
+
frame: HostStreamFrame;
|
|
521
|
+
}) => void): () => void;
|
|
522
|
+
onInboxClaimed(listener: (payload: {
|
|
523
|
+
agent: AgentLike;
|
|
524
|
+
message: {
|
|
525
|
+
id?: string;
|
|
526
|
+
};
|
|
527
|
+
turn: number;
|
|
528
|
+
}) => void): () => void;
|
|
529
|
+
onAgentError(listener: (payload: {
|
|
530
|
+
agent: AgentLike;
|
|
531
|
+
turn: number;
|
|
532
|
+
error: unknown;
|
|
533
|
+
}) => void): () => void;
|
|
534
|
+
/** caps 门控——serve 形态恒 [](目录层部署期静态;answerer 层逐请求判定) */
|
|
535
|
+
sessionToolDenies(): ReadonlyArray<string>;
|
|
536
|
+
/** 命令表面变更 = $events commands/change + skills.watch 流(payload-free 重取) */
|
|
537
|
+
onCommandSurfaceChanged(listener: () => void): () => void;
|
|
538
|
+
/** 会话 id 集(受管注册表)。 */
|
|
539
|
+
sessionIds(): readonly string[];
|
|
540
|
+
/** 该会话是否有挂起 prompt(pushPrompt 置位 / turn/end 复位)。 */
|
|
541
|
+
hasInflightPrompt(sessionId: string): boolean;
|
|
542
|
+
/** follow 池健康(live = 至少一条流在泵;entries = 受管会话数)。 */
|
|
543
|
+
poolLive(): boolean;
|
|
544
|
+
poolEntries(): number;
|
|
545
|
+
/** 结算通道(合成 agent/error——桥内 inflight.fail -32603,诊断走 message)。 */
|
|
546
|
+
settlePrompt(sessionId: string, error: unknown): void;
|
|
547
|
+
/** 网关关停(流取消——follow 池由各会话句柄 dispose 承载) */
|
|
548
|
+
dispose(): void;
|
|
549
|
+
}
|
|
550
|
+
/** $events commands/change 订阅(命令表面变更流源——skills.watch 由此并存) */
|
|
551
|
+
declare function openCommandsChangeEventStream(carrier: DshCarrier, onEvent: () => void, logger: GatewayLogger): EventStreamHandle;
|
|
552
|
+
//#endregion
|
|
553
|
+
//#region src/gateway/interruption.d.ts
|
|
554
|
+
/**
|
|
555
|
+
* 载体中断状态机(网关承接——对齐 acp-bridge 完成相关性连接中断分支)。
|
|
556
|
+
*
|
|
557
|
+
* 作用域:gateway↔dsh carrier 断(follow 池失联)——浏览器 WS 断不归此
|
|
558
|
+
* (AbortSignal 解耦:响应丢失 + 重连回放恢复,零网关动作)。
|
|
559
|
+
*
|
|
560
|
+
* 迁移:CARRIER_LIVE ──(池全断)──> CARRIER_DOWN(t0) ──(池恢复 live)──>
|
|
561
|
+
* LIVE(挂起 prompt 继续等 turn/end——零动作)| ──(now − t0 > 阈值)──>
|
|
562
|
+
* 结算:对每个 in-flight 会话合成 agent/error(桥 onAgentError → 挂起
|
|
563
|
+
* prompt fail -32603,诊断走 message:tboxcode carrier-timeout + downMs +
|
|
564
|
+
* lastCursor——_meta 专用错误数据面为首版后援注记项)。
|
|
565
|
+
*
|
|
566
|
+
* in-flight 观测:RpcSessionDeps 层记账(pushPrompt 置位、turn/end 事件
|
|
567
|
+
* 复位——桥内挂起态的 deps 侧镜像,零 bridge 改动)。
|
|
568
|
+
*/
|
|
569
|
+
/** 可观测面(RpcSessionDeps 提供)。 */
|
|
570
|
+
interface InterruptionSource {
|
|
571
|
+
/** 会话 id 集(含在途 prompt 判定)。 */
|
|
572
|
+
sessionIds(): readonly string[];
|
|
573
|
+
/** 该会话是否有挂起 prompt(pushPrompt 置位 / turn/end 复位)。 */
|
|
574
|
+
hasInflightPrompt(sessionId: string): boolean;
|
|
575
|
+
/** follow 池健康(live = 至少一条流在泵;entries = 受管会话数)。 */
|
|
576
|
+
poolLive(): boolean;
|
|
577
|
+
poolEntries(): number;
|
|
578
|
+
/** 结算通道(合成 agent/error——桥内 inflight.fail)。 */
|
|
579
|
+
settle(sessionId: string, error: unknown): void;
|
|
580
|
+
}
|
|
581
|
+
interface InterruptionMonitorOptions {
|
|
582
|
+
/** 结算阈值(缺省 120s;测试注入短值)。 */
|
|
583
|
+
timeoutMs?: number;
|
|
584
|
+
/** 轮询间隔(缺省 1s;测试注入)。 */
|
|
585
|
+
tickMs?: number;
|
|
586
|
+
now?: () => number;
|
|
587
|
+
logger?: {
|
|
588
|
+
warn(m: string): void;
|
|
589
|
+
info(m: string): void;
|
|
590
|
+
debug(m: string): void;
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
declare class InterruptionMonitor {
|
|
594
|
+
#private;
|
|
595
|
+
constructor(source: InterruptionSource, options?: InterruptionMonitorOptions);
|
|
596
|
+
start(): void;
|
|
597
|
+
stop(): void;
|
|
598
|
+
/** 状态推进(start 的定时入口;测试可直接调)。 */
|
|
599
|
+
tick(): void;
|
|
600
|
+
/** 观测(doctor/health 面)。 */
|
|
601
|
+
snapshot(): {
|
|
602
|
+
down: boolean;
|
|
603
|
+
downSince: number | undefined;
|
|
604
|
+
settled: boolean;
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
//#endregion
|
|
608
|
+
//#region src/gateway/answerer.d.ts
|
|
609
|
+
/** 宽限窗(全员出局后等待切回/attach 的时长——终态前最后机会)。 */
|
|
610
|
+
declare const GRACE_WINDOW_MS = 60000;
|
|
611
|
+
/** 单 question 交互总预算(跨重问累计——防永久循环)。 */
|
|
612
|
+
declare const FORM_BUDGET_MS = 3600000;
|
|
613
|
+
/** permission 单成员应答超时(超时出局——不阻塞其余成员)。 */
|
|
614
|
+
declare const PERMISSION_MEMBER_TIMEOUT_MS = 30000;
|
|
615
|
+
/** 成员弃权 RPC 错误码(客户端显式让位——不计入结算)。 */
|
|
616
|
+
declare const ABSTAIN_RPC_ERROR = -32001;
|
|
617
|
+
type InteractionKind = 'elicitation' | 'permission';
|
|
618
|
+
interface MemberAttempt {
|
|
619
|
+
readonly connId: string;
|
|
620
|
+
timer?: ReturnType<typeof setTimeout>;
|
|
621
|
+
}
|
|
622
|
+
interface PendingInteraction {
|
|
623
|
+
readonly kind: InteractionKind;
|
|
624
|
+
readonly sessionId: string;
|
|
625
|
+
readonly eventId: string;
|
|
626
|
+
readonly frame: WireEventWaterfallFrame;
|
|
627
|
+
/** 已派发成员(abstain/失联即出局)。 */
|
|
628
|
+
readonly asked: Map<string, MemberAttempt>;
|
|
629
|
+
state: 'active' | 'grace' | 'settled';
|
|
630
|
+
graceTimer?: ReturnType<typeof setTimeout>;
|
|
631
|
+
readonly budgetStartedAt: number;
|
|
632
|
+
settledOutcome?: WireEventOutcome;
|
|
633
|
+
/** 结算通知的排除面(应答者已见结果)。 */
|
|
634
|
+
respondedBy?: string;
|
|
635
|
+
}
|
|
636
|
+
interface InteractionRegistryDeps {
|
|
637
|
+
now(): number;
|
|
638
|
+
timers: {
|
|
639
|
+
set(fn: () => void, ms: number): ReturnType<typeof setTimeout>;
|
|
640
|
+
clear(timer: ReturnType<typeof setTimeout>): void;
|
|
641
|
+
};
|
|
642
|
+
/** 会话当前绑定连接(fanout 亲和表)。 */
|
|
643
|
+
eligibleConns(sessionId: string): readonly string[];
|
|
644
|
+
/** 连接的 elicitation 能力(question 派发前置;permission 不要求)。 */
|
|
645
|
+
capsOf(connId: string): boolean;
|
|
646
|
+
/** server→client 请求直发(ConnContext.request——drainUpdates 先行由上游承载)。 */
|
|
647
|
+
dispatch(connId: string, kind: InteractionKind, params: unknown): Promise<unknown>;
|
|
648
|
+
/** $events/result unary(outcome 三态)。 */
|
|
649
|
+
respond(eventId: string, outcome: WireEventOutcome): Promise<void>;
|
|
650
|
+
/** 结算扇出(_tbox.cn/acp_{elicitation,permission}_resolved——排除应答者)。 */
|
|
651
|
+
resolvedNotify(kind: InteractionKind, payload: Record<string, unknown>, excludeConnId?: string): void;
|
|
652
|
+
/** waterfall agentId → 网关 sessionId(session-deps 采纳映射)。 */
|
|
653
|
+
sessionIdOfAgent(agentId: string): string | undefined;
|
|
654
|
+
/** question 形状构造(bridge-core buildElicitationSchema 方言映射)。 */
|
|
655
|
+
buildQuestionParams(sessionId: string, frame: WireEventWaterfallFrame): {
|
|
656
|
+
message: string;
|
|
657
|
+
requestedSchema: unknown;
|
|
658
|
+
};
|
|
659
|
+
logger: {
|
|
660
|
+
warn(message: string): void;
|
|
661
|
+
info(message: string): void;
|
|
662
|
+
debug(message: string): void;
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
declare class InteractionRegistry {
|
|
666
|
+
#private;
|
|
667
|
+
constructor(deps: InteractionRegistryDeps);
|
|
668
|
+
/** 在册交互数(观测面)。 */
|
|
669
|
+
get size(): number;
|
|
670
|
+
/** pendingOf——会话当前在途交互(观测/测试面)。 */
|
|
671
|
+
pendingOf(sessionId: string): PendingInteraction | undefined;
|
|
672
|
+
/** waterfall 帧入口($events onWaterfall)。 */
|
|
673
|
+
begin(frame: WireEventWaterfallFrame): void;
|
|
674
|
+
/** $events cancel 帧——宿主取消(turn 中止链),结算 cancelled 优先于一切。 */
|
|
675
|
+
cancel(frame: WireEventCancellationFrame): void;
|
|
676
|
+
/** 连接入册/会话切回(router.bind / load·resume·new 成功)——GRACE 重问触发点。 */
|
|
677
|
+
attach(connId: string, sessionId: string): void;
|
|
678
|
+
/** switchBack——同 attach 语义(会话重新绑定的显式形态)。 */
|
|
679
|
+
switchBack(connId: string, sessionId: string): void;
|
|
680
|
+
/** 连接失联(ws close)——成员出局;active 空员进 GRACE。 */
|
|
681
|
+
disconnect(connId: string): void;
|
|
682
|
+
/** 停机清算(dispose——全 pending 终态 cancelled)。 */
|
|
683
|
+
dispose(): void;
|
|
684
|
+
}
|
|
685
|
+
//#endregion
|
|
686
|
+
//#region src/gateway/uplink.d.ts
|
|
687
|
+
type UplinkLogger = {
|
|
688
|
+
warn(message: string): void;
|
|
689
|
+
info(message: string): void;
|
|
690
|
+
debug(message: string): void;
|
|
691
|
+
};
|
|
692
|
+
interface AttachAcpGatewayOptions {
|
|
693
|
+
core: SharedAcpCore;
|
|
694
|
+
hooks?: AcpGatewayHooks;
|
|
695
|
+
/** 连接鉴权(box 注入;缺省全放——demo 面 Origin 校验) */
|
|
696
|
+
authenticate?: (req: IncomingMessage) => boolean | Promise<boolean>;
|
|
697
|
+
logger: UplinkLogger;
|
|
698
|
+
}
|
|
699
|
+
interface AcpGatewayHandle {
|
|
700
|
+
close(): void;
|
|
701
|
+
/** 会话亲和读面(answerer eligibleConns——组合根经此装配竞速面)。 */
|
|
702
|
+
boundConnIds(sessionId: string): readonly string[];
|
|
703
|
+
/** server→client 请求面(answerer dispatch 经 ConnContext.request)。 */
|
|
704
|
+
ctxOf(connId: string): ConnContext | undefined;
|
|
705
|
+
/** 结算通知扇出(answerer resolvedNotify)。 */
|
|
706
|
+
routeResolved(method: string, payload: Record<string, unknown>, excludeConnId?: string): void;
|
|
707
|
+
}
|
|
708
|
+
declare function attachAcpGateway(server: Server, path: string, options: AttachAcpGatewayOptions): AcpGatewayHandle;
|
|
709
|
+
//#endregion
|
|
710
|
+
//#region src/index.d.ts
|
|
711
|
+
/**
|
|
712
|
+
* tboxcode-dsh-sdk:agtcodingbox 唯一依赖面。
|
|
713
|
+
* - Supervisor:dsh server 子进程生命线监护(信封协议 v2.2 消费面——ready-channel-v2 /
|
|
714
|
+
* integration design Supervisor 契约节;切片 2)
|
|
715
|
+
* - 薄 carrier:unary POST envelope + WS mux + $events waterfall 应答(运行时零
|
|
716
|
+
* dsh 包依赖——spike-gateway-assembly 定型手写路线;切片 3)
|
|
717
|
+
* - wire 契约手写子集 + decodeWireEvent(全仓唯一合法 cast 点——bridge-typing-
|
|
718
|
+
* boundary-hardening 类型边界;切片 3)
|
|
719
|
+
*/
|
|
720
|
+
declare const PACKAGE_NAME = "@tbox.cn/tboxcode-dsh-sdk";
|
|
721
|
+
//#endregion
|
|
722
|
+
export { ABSTAIN_RPC_ERROR, type AcpGatewayHandle, type AcpGatewayHooks, type AttachAcpGatewayOptions, CarrierRpcError, type CarrierRpcErrorShape, CarrierTransportError, type ConnContext, type ConnectionCredentials, type ConsumableSessionEvent, type DecodeStats, type DecodedWireEvent, DshCarrier, type DshCarrierOptions, type EventStreamHandle, type EventStreamHandlers, FORM_BUDGET_MS, FanoutRouter, type FollowHandle, FollowPool, type FollowPoolHandlers, type FollowPoolStats, GRACE_WINDOW_MS, type GatewayLogger, type InteractionKind, InteractionRegistry, type InteractionRegistryDeps, InterruptionMonitor, type InterruptionMonitorOptions, type InterruptionSource, PACKAGE_NAME, PERMISSION_MEMBER_TIMEOUT_MS, type PendingInteraction, type RemoteSessionState, RpcSessionDeps, type StreamHandle, type StreamHandlers, Supervisor, type SupervisorChild, SupervisorDeploymentError, type SupervisorOptions, type SupervisorPhase, type SupervisorSpawner, type WireAssistantStreamAttempt, type WireAssistantStreamBaseline, type WireAssistantStreamFrame, type WireEventCancellationFrame, type WireEventEmitFrame, type WireEventFrame, type WireEventOutcome, type WireEventReadyFrame, type WireEventWaterfallFrame, type WireFollowFrame, type WireFollowRequest, type WireHistoryRecord, type WireJson, type WirePage, type WireSessionAddress, type WireSessionEvent, type WireSessionHeader, attachAcpGateway, decodeWireEvent, exchangeCredentialsViaConnect, isRecord, openCommandsChangeEventStream, parseWireEventFrame, parseWireFollowFrame, parseWireHistoryRecord, parseWirePage, parseWireSessionEvent, runHookOpen };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{spawn as e}from"node:child_process";import{randomUUID as t}from"node:crypto";import n,{WebSocketServer as r}from"ws";import{MODE_TABLE as i,classify as a,isIgnorable as o}from"@tbox.cn/dsh-acp-bridge-core";var s=class extends Error{kind;report;constructor(e,t,n){super(t),this.name=`SupervisorDeploymentError`,this.kind=e,this.report=n}};function c(e){let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!=`object`||!t||Array.isArray(t))return null;let n=t;return n.v===1&&(n.event===`standby`||n.event===`ready`&&typeof n.port==`number`&&typeof n.token==`string`)?t:null}async function l(e,t){let n=await fetch(`http://127.0.0.1:${e}/connect?token=${encodeURIComponent(t)}&interactions=answer`,{redirect:`manual`});if(n.status!==302)throw Error(`/connect 凭据交换期待 302,实得 ${n.status}(port ${e})`);let r=n.headers.get(`set-cookie`);if(r===null)throw Error(`/connect 凭据交换缺 Set-Cookie`);let i=r.split(`;`)[0]??``;if(i===``)throw Error(`/connect 凭据交换缺 Set-Cookie`);return i}var u=class{#e;#t;#n;#r;#i=`idle`;#a=[];#o;#s=!1;#c=!1;#l=0;#u=[];#d=[];#f=[];#p;#m=0;#h=[];#g=!1;#_;constructor(e={},t,n){this.#e={startMode:`immediate`,readyTimeoutMs:12e4,backoffBaseMs:1e3,backoffMaxMs:5e3,maxRestartAttempts:3,ringBufferLines:1e3,...e},this.#t=t??d(e),this.#n=n??l,this.#r=e.log??(()=>{})}phase(){return this.#i}onPhaseChange(e){return this.#a.push(e),()=>{this.#a=this.#a.filter(t=>t!==e)}}async start(){if(this.#i!==`idle`)throw Error(`Supervisor.start 仅 idle 态可调(当前 ${this.#i})`);this.#w(),await this.#x()}async connect(){this.#y(),this.#s=!0,this.#i===`standby`&&!this.#c&&this.#e.startMode===`on-first-connection`&&this.#D(),this.#i!==`ready`&&await this.#x();let e=this.#p;if(e!==void 0&&e.generation===this.#m)return e;let t=this.#v;if(t===void 0)throw Error(`ready 凭据缺席(状态机时序违例)`);let n=await this.#n(t.port,t.token),r={baseUrl:`http://127.0.0.1:${t.port}`,cookie:n,port:t.port,generation:this.#m};return this.#p=r,this.#r(`凭据交换完成(generation ${this.#m},port ${t.port})`),r}async reconnect(){this.#y(),this.#i!==`ready`&&await this.#x();let e=this.#v;if(e===void 0)throw Error(`ready 凭据缺席(状态机时序违例)`);let t=await this.#n(e.port,e.token),n={baseUrl:`http://127.0.0.1:${e.port}`,cookie:t,port:e.port,generation:this.#m};return this.#p=n,this.#r(`凭据再交换完成(generation ${this.#m},port ${e.port})`),n}crashReport(){return[`phase=${this.#i} restarts=${this.#l} generation=${this.#m}`,`exitCodes=${JSON.stringify(this.#u)}`,`phaseHistory=${this.#d.join(` → `)}`,`stderr(环形缓冲尾部 ${this.#f.length} 行):`,...this.#f.map(e=>` ${e}`)].join(`
|
|
2
|
+
`)}async dispose(){if(this.#g)return;this.#g=!0,this.#_=void 0;let e=this.#o;e!==void 0&&(e.kill(`SIGTERM`),await new Promise(t=>{let n=setTimeout(()=>{e.kill(`SIGKILL`),t()},3e3);e.onExit(()=>{clearTimeout(n),t()})})),this.#C(Error(`Supervisor 已停机`)),this.#b(`disposed`)}#v;#y(){if(this.#g)throw Error(`Supervisor 已停机`);if(this.#i===`idle`)throw Error(`先调用 start()(connect 挂靠 spawn 生命周期)`);if(this.#_!==void 0)throw this.#_.error;if(this.#i===`failed-permanent`||this.#i===`failed-protocol`)throw new s(this.#i===`failed-permanent`?`permanent`:`protocol`,`Supervisor 终态 ${this.#i}`,this.crashReport())}#b(e){this.#i=e,this.#d.push(`${e}@${Date.now()}`),this.#a.forEach(t=>t(e))}#x(){return this.#i===`ready`?Promise.resolve():new Promise((e,t)=>{this.#h.push({generation:this.#m,resolve:e,reject:t})})}#S(){this.#h.splice(0).forEach(e=>e.resolve())}#C(e){this.#h.splice(0).forEach(t=>t.reject(e))}async#w(){for(;;){if(this.#g)return;if(await this.#E(),this.#_!==void 0){this.#b(this.#_.kind===`protocol`?`failed-protocol`:`failed-permanent`);return}return}}#T(e){if(this.#g)return;if(this.#l+=1,this.#l>this.#e.maxRestartAttempts){this.#_={kind:`permanent`,error:new s(`exhausted`,`崩溃退避序列耗尽(${this.#e.maxRestartAttempts} 次)——最后原因:${e}`,this.crashReport())},this.#b(`failed-permanent`),this.#C(this.#_.error);return}let t=Math.min(this.#e.backoffBaseMs*2**(this.#l-1),this.#e.backoffMaxMs);this.#b(`restarting`),this.#r(`瞬时失败(${e})——${t}ms 后第 ${this.#l} 次重启`),setTimeout(()=>{this.#g||this.#E().then(()=>{this.#_!==void 0&&(this.#b(this.#_.kind===`protocol`?`failed-protocol`:`failed-permanent`),this.#C(this.#_.error))})},t)}async#E(){this.#m+=1,this.#p=void 0,this.#c=!1,this.#v=void 0;let e=this.#m;this.#b(`booting`);let t=this.#e.command??[`tboxcode-dsh`],n=this.#t([...t,`server`]);this.#o=n;let r=!1,i;clearTimeout(i),i=setTimeout(()=>{this.#m!==e||this.#i===`ready`||(this.#r(`就绪确认超时——kill 子进程(瞬时面)`),n.kill(`SIGKILL`))},this.#e.readyTimeoutMs),n.onStdoutLine(t=>{if(this.#m!==e)return;let a=c(t);if(!r){if(a===null||a.event!==`standby`){this.#_={kind:`protocol`,error:new s(`protocol`,`首行校验失败(期待 standby 信封,实得 "${t.slice(0,80)}")`,this.crashReport())},this.#b(`failed-protocol`),this.#C(this.#_.error),n.kill(`SIGKILL`);return}r=!0,this.#b(`standby`),(this.#e.startMode===`immediate`||this.#s)&&this.#D();return}if(a===null){this.#i===`ready`&&this.#r(`stdout 违约(ready 后非静默): ${t.slice(0,120)}`),this.#O(`[stdout] ${t}`);return}a.event!==`standby`&&this.#i!==`ready`&&(this.#v=a,this.#b(`ready`),clearTimeout(i),this.#S())}),n.onStderrLine(t=>{this.#m===e&&this.#O(t)}),n.onExit(t=>{if(this.#m===e&&(clearTimeout(i),this.#u.push(t),!this.#g&&this.#_===void 0)){if(t===2){this.#_={kind:`permanent`,error:new s(`permanent`,`server 永久失败(退出码 2——config 非法 / 未设 model / profile 损坏)`,this.crashReport())},this.#b(`failed-permanent`),this.#C(this.#_.error);return}if(t===3){this.#_={kind:`protocol`,error:new s(`protocol`,`server 协议版本偏斜(退出码 3——部署错误最显眼信号)`,this.crashReport())},this.#b(`failed-protocol`),this.#C(this.#_.error);return}this.#T(`退出码 ${t??`signal`}`)}})}#D(){this.#c||this.#o===void 0||(this.#c=!0,this.#b(`starting`),this.#o.writeStdin(`${JSON.stringify({v:1,cmd:`start`})}\n`),this.#r(`start 已释放`))}#O(e){this.#f.push(`${Date.now()} ${e}`),this.#f.length>this.#e.ringBufferLines&&this.#f.splice(0,this.#f.length-this.#e.ringBufferLines)}};function d(t){return n=>{let r=e(n[0],n.slice(1),{stdio:[`pipe`,`pipe`,`pipe`],env:{...process.env,...t.env??{}}}),i=``,a=``,o=[],s=[],c=[],l=(e,t,n)=>{for(e+=t.toString();;){let t=e.indexOf(`
|
|
3
|
+
`);if(t<0)break;let r=e.slice(0,t);e=e.slice(t+1),n.forEach(e=>e(r))}return e};return r.stdout?.on(`data`,e=>{i=l(i,e.toString(),o)}),r.stderr?.on(`data`,e=>{a=l(a,e.toString(),s)}),r.on(`close`,e=>{i!==``&&o.forEach(e=>e(i)),a!==``&&s.forEach(e=>e(a)),c.forEach(t=>t(e))}),{writeStdin:e=>r.stdin?.write(e),onStdoutLine:e=>o.push(e),onStderrLine:e=>s.push(e),onExit:e=>c.push(e),kill:e=>r.kill(e??`SIGTERM`)}}}function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function p(e){return!f(e)||typeof e.type!=`string`||e.type===``||typeof e.seq!=`number`||!Number.isInteger(e.seq)||typeof e.time!=`number`||!(`data`in e)?null:e}function m(e){if(!f(e)||e.type!==`event`)return null;let t=p(e.event);return t===null?null:{type:`event`,event:t}}function h(e){if(!f(e))return null;if(e.type===`snapshot`){let t=f(e.header)?e.header:null;if(t===null||typeof e.cursor!=`number`||typeof e.hasMore!=`boolean`)return null;let n=[];if(Array.isArray(e.records))for(let t of e.records){let e=m(t);if(e===null)return null;n.push(e)}else return null;return{type:`snapshot`,header:t,cursor:e.cursor,records:n,hasMore:e.hasMore,projections:e.projections,...f(e.assistantStream)?{assistantStream:e.assistantStream}:{}}}return e.type===`assistant-stream`?f(e.frame)?{type:`assistant-stream`,frame:e.frame}:null:m(e)}function g(e){if(!f(e)||typeof e.hasMore!=`boolean`||!Array.isArray(e.records))return null;let t=[];for(let n of e.records){let e=m(n);if(e===null)return null;t.push(e)}return{records:t,hasMore:e.hasMore}}function _(e){return f(e)&&(e.type===`ready`&&typeof e.clientId==`string`&&f(e.host)||e.type===`emit`&&typeof e.event==`string`&&Array.isArray(e.args)||e.type===`waterfall`&&typeof e.eventId==`string`&&typeof e.agentId==`string`&&typeof e.event==`string`&&f(e.request)||e.type===`cancel`&&typeof e.eventId==`string`)?e:null}var v=class extends Error{code;details;constructor(e){super(e.message),this.name=`CarrierRpcError`,this.code=e.code,this.details=e.details}},y=class extends Error{constructor(e){super(e),this.name=`CarrierTransportError`}},b=class{#e;#t;#n;#r;#i;#a;#o=!1;#s=!1;constructor(e){this.#e=e.baseUrl.replace(/\/$/,``),this.#t=e.cookie,this.#n=e.refreshCredentials}async unary(e,t){this.#p();try{return await this.#c(e,t)}catch(n){if(!(n instanceof y&&n.message.endsWith(`HTTP 401`))||this.#n===void 0)throw n;return await this.#f(),this.#c(e,t)}}async#c(e,n){let r=t(),i;try{i=await fetch(`${this.#e}/api/${e}`,{method:`POST`,headers:{"content-type":`application/json`,cookie:this.#t},body:JSON.stringify({type:`client-request`,rpcId:r,method:e,payload:{args:n}}),signal:AbortSignal.timeout(6e4)})}catch(t){throw t instanceof Error&&t.name===`TimeoutError`?new y(`unary ${e} 超时(上游 60s 无响应)`):t}if(i.status!==200)throw new y(`unary ${e} HTTP ${i.status}`);let a=await i.json();if(a.type!==`server-response`||a.rpcId!==r)throw new y(`unary ${e} envelope 畸形(type/rpcId 失配)`);if(a.result.ok)return a.result.value;throw new v(a.result.error)}openStream(e,r,i){this.#p();let a=t(),o=!1,s={canceled:!1,onFrame:e=>{e.type===`item`?i.onItem(e.value):e.type===`end`?(s.canceled=!0,i.onEnd?.()):e.type===`error`&&(s.canceled=!0,i.onError?.(e.error??{code:`gateway/internal`,message:`stream error 帧缺 error 字段`}))},onDown:e=>{s.canceled||(s.canceled=!0,e&&i.onError?.({code:`carrier/mux-closed`,message:`mux 插座意外关闭`}),i.onClose?.(e))}};return this.#l().then(t=>{if(o||s.canceled){process.stderr.write(`[carrier] open ABORTED (canceled=${String(o)} entry=${String(s.canceled)}) ${e}\n`);return}t.streams.set(a,s),t.socket.readyState===n.OPEN?(t.socket.send(JSON.stringify({type:`open`,streamId:a,endpoint:e,payload:{args:r}})),process.env.CARRIER_WIRE_DEBUG===`1`&&process.stderr.write(`[carrier] open sent ${e} streamId=${a.slice(0,8)}\n`)):process.stderr.write(`[carrier] open SKIPPED (readyState ${t.socket.readyState}) ${e}\n`)}).catch(e=>{o||s.canceled||(s.canceled=!0,i.onError?.({code:`carrier/mux-open`,message:e.message}),i.onClose?.(!0))}),{cancel:()=>{o=!0,s.canceled=!0;let e=this.#r;e!==void 0&&e.streams.delete(a)&&e.socket.readyState===n.OPEN&&e.socket.send(JSON.stringify({type:`cancel`,streamId:a}))}}}async#l(){let e=this.#r;if(e!==void 0&&e.socket.readyState===n.OPEN)return e;if(this.#i!==void 0)return this.#i;let t=this.#u().finally(()=>{this.#i===t&&(this.#i=void 0)});return this.#i=t,t}async#u(){this.#p(),this.#o&&this.#n!==void 0&&await this.#f();let e=new n(`${x(this.#e)}/api/remote.mux`,{headers:{cookie:this.#t}});await new Promise((t,n)=>{let r=setTimeout(()=>n(new y(`mux 插座打开超时`)),15e3);r.unref(),e.once(`open`,()=>{clearTimeout(r),t()}),e.once(`error`,e=>{clearTimeout(r),n(new y(`mux 插座打开失败: ${e.message}`))}),e.once(`unexpected-response`,(e,t)=>{clearTimeout(r),n(new y(`mux 升级被拒 HTTP ${t.statusCode??`?`}`))})});let t={socket:e,streams:new Map};e.on(`message`,e=>{let n;try{n=JSON.parse(String(e))}catch{return}typeof n.streamId==`string`&&t.streams.get(n.streamId)?.onFrame(n)});let r=!1;return e.on(`close`,()=>this.#d(t,r)),e.on(`error`,()=>{r=!0}),this.#r=t,this.#o=!0,t}#d(e,t){if(this.#r===e){this.#r=void 0;for(let n of e.streams.values())n.onDown(t);e.streams.clear()}}#f(){if(this.#a!==void 0)return this.#a;let e=(async()=>{let e=this.#n;if(e===void 0)return;let t=await e();this.#t=t.cookie,this.#e=t.baseUrl.replace(/\/$/,``)})().finally(()=>{this.#a===e&&(this.#a=void 0)});return this.#a=e,e}openEvents(e){let t,n=n=>{switch(n.type){case`ready`:t=n.clientId,e.onReady(n);return;case`emit`:e.onEmit(n);return;case`waterfall`:e.onWaterfall(n);return;case`cancel`:e.onCancel(n);return}},r=this.openStream(`$events`,{},{onItem:t=>{let i=_(t);if(i===null){e.onClose?.(!1),r.cancel();return}n(i)},onClose:t=>e.onClose?.(t)});return{respond:async(e,n)=>{if(t===void 0)throw new y(`waterfall 应答先于 ready 帧(clientId 缺席)`);await this.unary(`$events/result`,{clientId:t,eventId:e,outcome:n})},close:()=>r.cancel()}}dispose(){this.#s=!0,this.#r?.socket.close(),this.#r=void 0}#p(){if(this.#s)throw new y(`carrier 已释放`)}};function x(e){if(e.startsWith(`https://`))return`wss://${e.slice(8)}`;if(e.startsWith(`http://`))return`ws://${e.slice(7)}`;throw new y(`baseUrl 非法(期待 http(s)://,实得 ${e})`)}function S(e,t){let n=p(e);if(n===null)return t!==void 0&&(t.invalid+=1),null;if(a(n.type)===`project`)return typeof n.data!=`object`||n.data===null||Array.isArray(n.data)?(t!==void 0&&(t.opaqueWarn+=1),{kind:`opaque`,event:n,level:`warn`}):(t!==void 0&&(t.consumable+=1),{kind:`consumable`,event:n});let r=o(n)?`debug`:`warn`;return r===`debug`?t!==void 0&&(t.opaqueDebug+=1):t!==void 0&&(t.opaqueWarn+=1),{kind:`opaque`,event:n,level:r}}var C=class{#e;#t;#n={invalid:0,opaqueDebug:0,opaqueWarn:0,consumable:0};#r=new Map;#i=0;constructor(e,t){this.#e=e,this.#t=t?.reopenBaseMs??1e3}open(e,t){let n=this.#r.get(e);if(n!==void 0&&!n.closed)return n.handlers=t,{close:()=>this.close(e)};let r={sessionId:e,handlers:t,handle:void 0,cursor:void 0,baseline:void 0,streamSeenRevision:!1,reopening:!1,backoffMs:this.#t,closed:!1,pending:[]};return this.#r.set(e,r),this.#a(r),{close:()=>this.close(e)}}close(e){let t=this.#r.get(e);t!==void 0&&(t.closed=!0,t.handle?.cancel(),this.#r.delete(e))}stats(){let e=0,t=0;for(let n of this.#r.values())n.closed||(n.reopening||n.cursor===void 0?t++:e++);return{live:e,reopening:t,decoded:{...this.#n},gapsRepaired:this.#i}}#a(e){e.closed||(e.reopening=e.cursor!==void 0,e.handle=this.#e.openStream(`session/follow`,{request:{address:{kind:`session`,sessionId:e.sessionId},assistantStream:!0}},{onItem:t=>this.#s(e,t),onEnd:()=>this.#o(e,`stream end`),onError:t=>this.#o(e,`${t.code}: ${t.message}`),onClose:t=>{t&&this.#o(e,`socket error`)}}))}#o(e,t){if(e.closed)return;e.handle=void 0,e.handlers.onDown(t);let n=e.backoffMs;e.backoffMs=Math.min(e.backoffMs*2,3e4),e.baseline=void 0,e.streamSeenRevision=!1,e.reopening=!0,setTimeout(()=>{e.closed||this.#a(e)},n)}#s(e,t){if(t.type===`snapshot`){this.#c(e,t);return}if(e.cursor!==void 0){if(e.reopening){e.pending.push(t);return}this.#d(e,t)}}#c(e,t){let n=e.cursor;if(n!==void 0&&t.cursor<n){e.handlers.onDown(`cursor 回退:${String(t.cursor)} < ${String(n)}`);return}e.baseline=t.assistantStream,e.streamSeenRevision=!1,e.reopening=!0,e.handlers.onSnapshot(t.header,t.cursor,t.projections,t.assistantStream),this.#l(e,t,n)}async#l(e,t,n){try{let r=[];if(n!==void 0&&t.records.length>0){let i=t.records[0]?.event.seq??t.cursor;i>n+1&&(r.push(...await this.#u(e,n+1,i)),this.#i+=r.length)}for(let e of t.records)r.push(e.event);for(let t of r)this.#f(e,t);let i=e.pending;e.pending=[],e.reopening=!1,e.cursor=t.cursor,e.backoffMs=this.#t;for(let t of i)this.#d(e,t)}catch(t){e.handlers.onDown(`backlog 补齐失败:${String(t)}`)}}async#u(e,t,n){let r=[],i=n;for(;i>t;){let n=g(await this.#e.unary(`session/page`,{request:{address:{kind:`session`,sessionId:e.sessionId},throughSeq:i-1,beforeSeq:t,maxMessages:200}}));if(n===null)throw new y(`session/page 帧畸形(records/hasMore 缺失)`);for(let e of n.records)r.push(e.event);let a=n.records[0]?.event.seq;if(a===void 0||a<=t||(i=a,!n.hasMore))break}return r.sort((e,t)=>e.seq-t.seq),r}#d(e,t){if(t.type===`assistant-stream`){if(!e.streamSeenRevision){e.streamSeenRevision=!0;let n=(e.baseline?.revision??-1)+1;if(e.baseline!==void 0&&t.frame.revision!==n){e.handlers.onDown(`assistant-stream 衔接断裂:revision ${String(t.frame.revision)} ≠ ${String(n)}`);return}}e.handlers.onAssistantStream(t.frame);return}t.type===`event`&&this.#f(e,t.event)}#f(e,t){let n=S(t,this.#n);n!==null&&n.kind===`consumable`&&e.handlers.onEvent(n.event)}async readAll(e){return await new Promise((t,n)=>{let r=new Map,i,a,o=!1,s=this.#e.openStream(`session/follow`,{request:{address:{kind:`session`,sessionId:e},assistantStream:!1}},{onItem:c=>{o||c.type===`snapshot`&&(o=!0,i=c.header,a=c.projections,s.cancel(),this.#p(e,c,r).then(e=>t({header:i,events:e,projections:a}),e=>n(e)))},onEnd:()=>{o||(o=!0,n(new y(`session/follow 在 snapshot 前关闭`)))},onError:e=>{o||(o=!0,n(new v(e)))}})})}async#p(e,t,n){let r=[];for(let e of t.records)r.push(e.event);let i=t.records.length>0?t.records[0]?.event.seq:void 0;for(;t.hasMore===!0;){let n=g(await this.#e.unary(`session/page`,{request:{address:{kind:`session`,sessionId:e},throughSeq:t.cursor,...i===void 0?{}:{beforeSeq:i},maxMessages:200}}));if(n===null)throw new y(`session/page 帧畸形(records/hasMore 缺失)`);for(let e of n.records)r.push(e.event);if(!n.hasMore||n.records.length===0)break;let a=n.records[0]?.event.seq;if(a===void 0||a===0)break;i=a}let a=new Map;for(let e of r)a.set(e.seq,e);let o=[...a.values()].sort((e,t)=>e.seq-t.seq);for(let e=0;e<o.length;e++){let t=o[e];if(t?.seq!==e)throw new v({code:`gateway/internal`,message:`journal 连续性断裂:位置 ${String(e)} 实得 seq ${String(t?.seq)}`});let r=S(t,this.#n);r?.kind===`consumable`&&n.set(t.seq,r.event)}return[...n.values()]}},w=class{#e=new Map;#t=new Map;#n=new Map;#r=new Map;#i;#a;#o=0;#s=0;constructor(e,t){this.#i=e,this.#a=t}attachConnection(e,t,n){this.#e.set(e,{connId:e,send:t,ctx:n})}detachConnection(e){this.#e.delete(e);for(let[t,n]of this.#t)n.delete(e),n.size===0&&this.#t.delete(t),this.#a?.onSessionUnbind?.(e,t);for(let[t,n]of this.#n)n===e&&this.#n.delete(t)}bind(e,t){let n=this.#t.get(t);n===void 0&&(n=new Set,this.#t.set(t,n)),n.add(e),this.#a?.onSessionBind?.(e,t)}unbind(e,t){this.#t.get(t)?.delete(e),this.#a?.onSessionUnbind?.(e,t)}boundConnIds(e){return[...this.#t.get(e)??[]]}ctxOf(e){return this.#e.get(e)?.ctx}routeResolved(e,t,n){this.routeExt({method:e,payload:t},n===void 0?void 0:{excludeConnId:n})}beginReplayCount(e){this.#r.set(e,0)}takeReplayCount(e){let t=this.#r.get(e);return this.#r.delete(e),t}setTurnOrigin(e,t){this.#n.set(e,t)}clearTurnOrigin(e){this.#n.delete(e)}route(e){let t=e.sessionId,n;if(t===void 0)n=[...this.#e.keys()];else{let r=this.#n.get(t),i=e.update?.sessionUpdate===`user_message_chunk`;n=[...this.#t.get(t)??[]],r!==void 0&&i&&(n=n.filter(e=>e!==r),this.#s++);let a=this.#a?.fanout===void 0?void 0:T(this.#i,`fanout`,()=>this.#a?.fanout?.(e,n));if(a!==void 0&&(n=[...a]),n.length===0){this.#o++;return}}for(let t of n){let n=this.#e.get(t);if(n===void 0)continue;let r=e;if(this.#a?.transformOutbound!==void 0){let t=T(this.#i,`transformOutbound`,()=>this.#a?.transformOutbound?.(e,n.ctx));if(t===null)continue;t!==void 0&&(r=t)}n.send({jsonrpc:`2.0`,method:`session/update`,params:r});let i=this.#r.get(t);i!==void 0&&this.#r.set(t,i+1)}}routeExt(e,t){let n=typeof e.payload.sessionId==`string`?e.payload.sessionId:void 0,r=n===void 0?[...this.#e.keys()]:[...this.#t.get(n)??[]];t?.excludeConnId!==void 0&&(r=r.filter(e=>e!==t.excludeConnId));for(let t of r)this.#e.get(t)?.send({jsonrpc:`2.0`,method:e.method,params:e.payload})}stats(){return{connections:this.#e.size,dropped:this.#o,suppressed:this.#s}}};function T(e,t,n){try{return n()}catch(n){e.warn(`gateway hook ${t} failed (fail-open): ${String(n)}`);return}}const E=1e3,D=3e4;function O(e){return{id:e.id,get header(){let t=e.header;return{...t?.cwd===void 0?{}:{cwd:t.cwd},...t?.origin===void 0?{}:{origin:t.origin},...t?.parentSession===void 0?{}:{parentSession:t.parentSession},...t?.createdAt===void 0?{}:{createdAt:t.createdAt}}},requestHeader(){let t=e.projections?.modelSelection,n=t?.pending??t?.lastUsed;if(!(n==null||typeof n.provider!=`string`||typeof n.model!=`string`))return{config:{provider:n.provider,model:n.model,...typeof n.reasoningEffort==`string`?{reasoningEffort:n.reasoningEffort}:{}}}}}}function k(e,t,n){return{id:e.id,session:e.session,cancel:async n=>{await t.unary(`session/cancel`,{request:{sessionId:e.id}})},followup:t=>{n(e,t)}}}var A=class{logger;#e;#t;#n;#r=new Map;#i=new Set;#a=new Set;#o=new Set;#s=new Set;#c=new Set;#l;#u=E;#d;#f=E;#p;#m={groups:[],failures:[]};#h=0;#g;constructor(e){this.#e=e.carrier,this.#t=e.pool,this.#n=e.logger,this.logger=e.logger,this.#S(),this.#w(),this.#E()}async createAgent(e){return await this.#_(e)}async resumeAgent(e){return await this.#_(e)}async#_(e){let t=(await this.#e.unary(`session/create`,{request:{sessionId:e.sessionId,cwd:e.cwd}})).sessionId,n=this.#r.get(t);if(n!==void 0)return await e.configureScope?.(this.#y(n),n.agent),{agent:n.agent,dispose:async()=>this.#v(t)};let r={id:t,header:{version:1,id:t,createdAt:0,cwd:e.cwd,isSeeded:!1},projections:{},selectionProbe:void 0,lastPushedSelection:void 0,promptInflight:!1};r.session=O(r),r.agent=k(r,this.#e,(e,t)=>this.#b(e,t));let i=r;return this.#r.set(t,i),await e.configureScope?.(this.#y(i),i.agent),this.#t.open(t,this.#C(i)),{agent:i.agent,dispose:async()=>this.#v(t)}}#v(e){return this.#t.close(e),this.#r.delete(e),Promise.resolve()}#y(e){return{on:(t,n)=>(t===`agent/request`&&(e.selectionProbe=n),()=>{}),tools:{restrict:e=>void 0}}}async#b(e,t){if(e.promptInflight=!0,e.selectionProbe!==void 0)try{let t=await e.selectionProbe(void 0,async()=>({}));if(typeof t.provider==`string`&&typeof t.model==`string`){let n=JSON.stringify([t.provider,t.model,t.reasoningEffort]);n!==e.lastPushedSelection&&(await this.#e.unary(`session/selectModel`,{request:{sessionId:e.id,provider:t.provider,model:t.model,...typeof t.reasoningEffort==`string`?{reasoningEffort:t.reasoningEffort}:{}}}),e.lastPushedSelection=n)}}catch(e){this.#n.debug(`selection probe failed: ${String(e)}`)}await this.#e.unary(`session/prompt`,{request:{requestId:t.id,sessionId:e.id,mode:`steer`,content:t.content}})}persistence={stat:async(e,t)=>{let n=await this.#e.unary(`tboxcode/sessions.stat`,{request:{sessionId:e}});if(n!==null)return{header:n.header}},list:async e=>(await this.#e.unary(`session/list`,{_request:{}})).items.map(e=>({header:{id:e.sessionId,...e.cwd===void 0?{}:{cwd:e.cwd},...e.origin===void 0?{}:{origin:e.origin},...e.parentSessionId===void 0?{}:{parentSession:e.parentSessionId},createdAt:e.updatedAt}})),open:async(e,t)=>{let n=await this.#t.readAll(e);return{read:async()=>({events:n.events}),close:async()=>{}}}};sessionStore={get:e=>this.#r.get(e)?.session,flush:async e=>{await this.#e.unary(`tboxcode/sessions.flush`,{request:{sessionId:e.id}})}};llm={listProviders:()=>this.#x().groups.map(e=>({id:e.id,name:e.name})),listModels:async e=>(this.#x().groups.find(t=>t.id===e)?.models??[]).map(e=>({id:String(e.id),name:String(e.name),...e.description===void 0?{}:{description:String(e.description)}})),resolveModelInfo:async(e,t)=>{let n=this.#x().groups.find(t=>t.id===e)?.models.find(e=>e.id===t)?.reasoning;return{reasoning:{defaultEffort:n?.defaultEffort,efforts:n?.efforts??[]}}},resolveCallConfig:async e=>e};#x(){return Date.now()-this.#h>3e4&&this.#S(),this.#m}async#S(){try{this.#m=await this.#e.unary(`session/modelCatalog`,{}),this.#h=Date.now();let e=await this.#e.unary(`tboxcode/selection.default`,{});this.#g=typeof e.provider==`string`&&typeof e.model==`string`?{provider:e.provider,model:e.model,...e.reasoningEffort===void 0?{}:{reasoningEffort:e.reasoningEffort}}:void 0}catch(e){this.#n.warn(`catalog warm failed: ${String(e)}`)}}applyModeKnobs(e,t,n){let r=Object.entries(i).find(([,e])=>e.sandbox===n.sandbox&&e.approval===n.approval)?.[0];if(r===void 0)throw Error(`tboxcode: mode knobs 无对位(${String(n.sandbox)}/${String(n.approval)}——MODE_TABLE 外组合)`);return this.#e.unary(`tboxcode/mode`,{request:{agentId:e.id,mode:r}}).then(()=>void 0)}defaultSelection(){return this.#g}async executeCommand(e,t,n){let r=await this.#e.unary(`tboxcode/commands.execute`,{request:{agentId:e.id,line:t}});return r?.commandId===void 0?void 0:{commandId:r.commandId}}async listCommands(e){return await this.#e.unary(`tboxcode/commands.list`,{request:{agentId:e.id}})}async listUserInvocableSkills(e){return await this.#e.unary(`tboxcode/skills.userInvocable`,{request:{agentId:e.id}})}onSessionEvent(e){let t=e;return this.#i.add(t),()=>this.#i.delete(t)}onAssistantStream(e){return this.#a.add(e),()=>this.#a.delete(e)}onInboxClaimed(e){return this.#o.add(e),()=>this.#o.delete(e)}onAgentError(e){return this.#s.add(e),()=>this.#s.delete(e)}sessionToolDenies(){return[]}onCommandSurfaceChanged(e){return this.#c.add(e),()=>this.#c.delete(e)}sessionIds(){return[...this.#r.keys()]}hasInflightPrompt(e){return this.#r.get(e)?.promptInflight===!0}poolLive(){return this.#t.stats().live>0}poolEntries(){return this.#r.size}settlePrompt(e,t){let n=this.#r.get(e);if(!(n===void 0||!n.promptInflight)){n.promptInflight=!1;for(let e of this.#s)e({agent:n.agent,turn:0,error:t})}}#C(e){return{onSnapshot:(t,n,r)=>{e.header=t,e.projections=r},onEvent:t=>{t.type===`turn/end`&&(e.promptInflight=!1);for(let n of this.#i)n(e.session,t)},onAssistantStream:t=>{let n={type:t.finish===void 0?t.index===0?`start`:`chunk`:`end`,attemptId:t.attemptId,...t.chunk===void 0?{}:{chunk:t.chunk}};for(let t of this.#a)t({agent:e.agent,frame:n})},onDown:t=>this.#n.warn(`follow pool down (${e.id}): ${t}`)}}#w(){this.#l=this.#e.openStream(`tboxcode/agent.watch`,{},{onItem:e=>{this.#n.debug(`agent.watch item: ${JSON.stringify(e).slice(0,160)} states=${[...this.#r.keys()].join(`,`)}`);let t=this.#r.get(e.sessionId);if(t!==void 0){if(e.kind===`inboxClaimed`)for(let n of this.#o)n({agent:t.agent,message:{...e.messageId===void 0?{}:{id:e.messageId}},turn:e.turn??0});else if(e.kind===`error`)for(let n of this.#s)n({agent:t.agent,turn:0,error:e.error??`unknown agent error`})}},onError:e=>{this.#n.warn(`agent.watch stream error: ${JSON.stringify(e).slice(0,200)}`),this.#T()},onClose:e=>{e&&(this.#n.warn(`agent.watch stream closed`),this.#T())}})}#T(){let e=this.#u;this.#u=Math.min(this.#u*2,D),setTimeout(()=>{this.#w(),this.#u=E},e)}#E(){let e=()=>{for(let e of this.#c)e()};this.#d=j(this.#e,e,this.#n),this.#p=this.#e.openStream(`tboxcode/skills.watch`,{},{onItem:()=>e(),onError:()=>this.#D(),onClose:e=>{e&&this.#D()}})}#D(){let e=this.#f;this.#f=Math.min(this.#f*2,D),setTimeout(()=>{this.#E(),this.#f=E},e)}dispose(){this.#l?.cancel(),this.#d?.close(),this.#p?.cancel()}};function j(e,t,n){return e.openEvents({onReady:()=>n.debug(`commands/change $events ready`),onEmit:e=>{e.event===`commands/change`&&t()},onWaterfall:()=>{},onCancel:()=>{},onClose:e=>{e&&n.warn(`commands/change $events closed with error`)}})}var M=class{#e;#t;#n;#r;#i;#a;#o=!1;#s;constructor(e,t){this.#e=e,this.#t=t?.timeoutMs??12e4,this.#n=t?.tickMs??1e3,this.#r=t?.now??Date.now,this.#i=t?.logger??{warn:()=>{},info:()=>{},debug:()=>{}}}start(){this.#s=setInterval(()=>this.tick(),this.#n)}stop(){this.#s!==void 0&&clearInterval(this.#s),this.#s=void 0}tick(){if(!(this.#e.poolEntries()>0&&!this.#e.poolLive())){this.#a=void 0,this.#o=!1;return}if(this.#a===void 0){this.#a=this.#r();return}if(this.#o||this.#r()-this.#a<this.#t)return;this.#o=!0;let e=this.#r()-this.#a;for(let t of this.#e.sessionIds())this.#e.hasInflightPrompt(t)&&(this.#i.warn(`carrier timeout settle (${t}): downMs=${String(e)}`),this.#e.settle(t,Error(`tboxcode carrier-timeout (downMs=${String(e)})`)))}snapshot(){return{down:this.#a!==void 0,downSince:this.#a,settled:this.#o}}};const N=6e4,P=36e5,F=3e4,I=-32001;var L=class{#e=new Map;#t;constructor(e){this.#t=e}get size(){return this.#e.size}pendingOf(e){for(let t of this.#e.values())if(t.sessionId===e)return t}begin(e){let t=e.event===`user-questions/request`?`elicitation`:e.event===`approval/request`?`permission`:void 0;if(t===void 0||this.#e.has(e.eventId))return;let n=this.#t.sessionIdOfAgent(e.agentId);if(n===void 0){this.#l(e.eventId,{kind:`rejected`,error:{code:`gateway/agent-not-found`,message:`agent ${e.agentId} not managed by gateway`}});return}let r={kind:t,sessionId:n,eventId:e.eventId,frame:e,asked:new Map,state:`active`,budgetStartedAt:this.#t.now()};this.#e.set(e.eventId,r),this.#n(r),this.#s(r)}cancel(e){let t=this.#e.get(e.eventId);t===void 0||t.state===`settled`||this.#c(t,{kind:`result`,value:`cancelled`},`turn`)}attach(e,t){for(let n of this.#e.values()){if(n.sessionId!==t||n.state!==`grace`)continue;let r=n.graceTimer;n.graceTimer=void 0,r!==void 0&&this.#t.timers.clear(r),n.state=`active`,this.#t.logger.info(`answerer: grace broken by attach (${n.eventId} conn=${e})`),this.#n(n)}}switchBack(e,t){this.attach(e,t)}disconnect(e){for(let t of this.#e.values())t.asked.delete(e)&&t.state===`active`&&t.asked.size===0&&this.#o(t,`member disconnected`)}dispose(){for(let e of[...this.#e.values()])e.state!==`settled`&&this.#c(e,{kind:`result`,value:`cancelled`},`dispose`);this.#e.clear()}#n(e){let t=this.#t.eligibleConns(e.sessionId).filter(t=>!e.asked.has(t)).filter(t=>e.kind===`permission`||this.#t.capsOf(t));if(t.length===0){this.#o(e,`no eligible connections`);return}for(let n of t){let t={connId:n};e.kind===`permission`&&(t.timer=this.#t.timers.set(()=>{e.state!==`active`||!e.asked.has(n)||(e.asked.delete(n),this.#t.logger.info(`answerer: member timeout (${e.eventId} conn=${n})`),e.asked.size===0&&this.#o(e,`all members timed out`))},F)),e.asked.set(n,t),this.#r(e,n)}}async#r(e,t){let n=e.kind===`elicitation`?this.#t.buildQuestionParams(e.sessionId,e.frame):{callId:e.frame.request.callId};try{let r=await this.#t.dispatch(t,e.kind,n);if(e.state===`settled`||!e.asked.has(t))return;let i=this.#i(e,r);if(i.abstain){this.#a(e,t,`abstained`);return}this.#c(e,i.outcome,t)}catch(n){if(e.state===`settled`||!e.asked.has(t))return;if(n.code===I){this.#a(e,t,`abstained`);return}this.#t.logger.warn(`answerer: dispatch failed (${e.eventId} conn=${t}): ${n instanceof Error?n.message:String(n)}`),this.#a(e,t,`dispatch failed`)}}#i(e,t){if(e.kind===`permission`){let e=t?.outcome;return e?.outcome===`cancelled`?{abstain:!1,outcome:{kind:`result`,value:`cancelled`}}:{abstain:!1,outcome:{kind:`result`,value:e?.optionId===`allow-once`?`allowed-once`:`rejected`}}}let n=t;return n?.action===`accept`?{abstain:!1,outcome:{kind:`result`,value:n.content??{}}}:{abstain:!1,outcome:{kind:`rejected`,error:{code:n?.action===`decline`?`ASK_DECLINED`:`ASK_ABORTED`,message:`ask_user_question ${n?.action===`decline`?`declined`:`cancelled`} by client`}}}}#a(e,t,n){let r=e.asked.get(t);r?.timer!==void 0&&this.#t.timers.clear(r.timer),e.asked.delete(t),this.#t.logger.debug(`answerer: member dropped (${e.eventId} conn=${t} ${n})`),e.state===`active`&&e.asked.size===0&&this.#o(e,`all members out (${n})`)}#o(e,t){e.state===`active`&&(e.state=`grace`,e.graceTimer=this.#t.timers.set(()=>{this.#c(e,e.kind===`elicitation`?{kind:`rejected`,error:{code:`ASK_ABORTED`,message:`ask_user_question grace window expired`}}:{kind:`result`,value:`cancelled`},`grace`)},N),this.#t.logger.info(`answerer: grace entered (${e.eventId} ${t})`))}#s(e){let t=P-(this.#t.now()-e.budgetStartedAt);if(t<=0){this.#c(e,e.kind===`elicitation`?{kind:`rejected`,error:{code:`ASK_ABORTED`,message:`ask_user_question form budget exhausted`}}:{kind:`result`,value:`cancelled`},`budget`);return}this.#t.timers.set(()=>{e.state!==`settled`&&(this.#t.logger.warn(`answerer: form budget exhausted (${e.eventId})`),this.#c(e,e.kind===`elicitation`?{kind:`rejected`,error:{code:`ASK_ABORTED`,message:`ask_user_question form budget exhausted`}}:{kind:`result`,value:`cancelled`},`budget`))},t)}#c(e,t,n){if(e.state!==`settled`){e.state=`settled`,e.settledOutcome=t,e.respondedBy=n,e.graceTimer!==void 0&&(this.#t.timers.clear(e.graceTimer),e.graceTimer=void 0);for(let t of e.asked.values())t.timer!==void 0&&this.#t.timers.clear(t.timer);e.asked.clear(),this.#l(e.eventId,t),this.#t.resolvedNotify(e.kind,{sessionId:e.sessionId,eventId:e.eventId,outcome:t,respondedBy:n},typeof n==`string`&&n!==`grace`&&n!==`turn`&&n!==`dispose`&&n!==`budget`?n:void 0),this.#t.logger.info(`answerer: settled (${e.eventId} by=${n} kind=${t.kind})`)}}async#l(e,t){try{await this.#t.respond(e,t)}catch(t){this.#t.logger.warn(`answerer: respond failed (${e}): ${t instanceof Error?t.message:String(t)}`)}}};function R(e,t,n){let{core:i,hooks:a,authenticate:o,logger:s}=n,c=new w(s,a),l=new r({noServer:!0}),u=new Set;return i.io.notify=async e=>{c.route(e)},i.io.extNotify=async e=>{c.routeExt(e)},e.on(`upgrade`,(e,n,r)=>{new URL(e.url??`/`,`http://localhost`).pathname===t&&(async()=>{if(!(o===void 0||await z(o,e,s))){n.write(`HTTP/1.1 401 Unauthorized\r
|
|
4
|
+
\r
|
|
5
|
+
`),n.destroy();return}l.handleUpgrade(e,n,r,e=>{B(e,i,a,c,s,u)})})().catch(e=>{s.warn(`gateway upgrade failed: ${String(e)}`),n.destroy()})}),{close:()=>{for(let e of u)e.socket.close();l.close()},boundConnIds:e=>c.boundConnIds(e),ctxOf:e=>c.ctxOf(e),routeResolved:(e,t,n)=>c.routeResolved(e,t,n)}}async function z(e,t,n){try{return await e(t)}catch(e){return n.warn(`gateway authenticate failed: ${String(e)}`),!1}}function B(e,n,r,i,a,o){let s=t(),c={elicitation:!1},l=t=>{e.readyState===e.OPEN&&e.send(JSON.stringify(t))},u={connId:s,get caps(){return c},request:async(e,t)=>{throw Error(`tboxcode: server→client request 面直通由 attach 后覆写(answerer 切片消费)`)},notify:async(e,t)=>{l({jsonrpc:`2.0`,method:e,params:t})}};i.attachConnection(s,l,u);let d=new TransformStream,f=d.writable.getWriter(),p={writable:new WritableStream({write:e=>{V(e,h,i,l)}}),readable:d.readable},m=n.attachConnection(p,{beforePrompt:e=>i.setTurnOrigin(e,s),afterPrompt:e=>i.clearTurnOrigin(e)}),h={connId:s,socket:e,conn:m,ctx:u,pending:new Map,get caps(){return c}};u.request=(e,t)=>m.client.request(e,t),o.add(h),e.on(`message`,e=>{let t=typeof e==`string`?e:Buffer.isBuffer(e)?e.toString(`utf8`):void 0;if(t===void 0)return;let n;try{n=JSON.parse(t)}catch{l({jsonrpc:`2.0`,id:null,error:{code:-32700,message:`Parse error`}});return}H(n,h,f,r,i,a)}),e.on(`close`,()=>{o.delete(h),i.detachConnection(s),f.close().catch(()=>{}),a.debug(`gateway connection detached (${s})`)}),e.on(`error`,e=>{a.warn(`gateway socket error (${s}): ${String(e)}`)})}function V(e,t,n,r){if(e.method===void 0&&e.id!==void 0){let r=t.pending.get(String(e.id));if(r!==void 0&&(t.pending.delete(String(e.id)),e.error===void 0)){let i=e.result?.sessionId??r.params?.sessionId;if(r.method===`session/close`)i!==void 0&&n.unbind(t.connId,i);else if(i!==void 0&&(n.bind(t.connId,i),r.method===`session/load`)){let e=n.takeReplayCount(t.connId)??0;setImmediate(()=>{n.routeExt({method:`_tbox.cn/acp_replay_complete`,payload:{sessionId:i,notificationCount:e}})})}}}r(e)}async function H(e,t,n,r,i,a){let o=e.method;if(o===void 0){await n.write(e);return}if(o===`initialize`){let n=e.params?.clientCapabilities;t.caps.elicitation=n?.elicitation!=null}if(o.startsWith(`_tbox.cn/`)){let n=r?.methods?.[o];if(e.id===void 0)return;if(n===void 0){t.socket.send(JSON.stringify({jsonrpc:`2.0`,id:e.id,error:{code:-32601,message:`Method not found: ${o}`}}));return}try{let r=await n(e.params,t.ctx);t.socket.send(JSON.stringify({jsonrpc:`2.0`,id:e.id,result:r??{}}))}catch(n){t.socket.send(JSON.stringify({jsonrpc:`2.0`,id:e.id,error:{code:-32603,message:n instanceof Error?n.message:String(n)}}))}return}if(r?.transformInbound!==void 0&&e.id!==void 0){let n;try{n=await r.transformInbound(o,e.params,t.ctx)}catch(t){a.warn(`gateway hook transformInbound failed (fail-open): ${String(t)}`),n=e.params}if(n===null){t.socket.send(JSON.stringify({jsonrpc:`2.0`,id:e.id,error:{code:-32602,message:`Invalid params: ${o} rejected by gateway`}}));return}e.params=n}if((o===`session/new`||o===`session/load`||o===`session/resume`||o===`session/close`)&&e.id!==void 0&&(t.pending.set(String(e.id),{method:o,params:e.params}),o===`session/load`&&i.beginReplayCount(t.connId),o===`session/close`)){let n=e.params?.sessionId;n!==void 0&&i.unbind(t.connId,n)}if(await n.write(e),o===`session/close`&&e.id===void 0){let n=e.params?.sessionId;n!==void 0&&i.unbind(t.connId,n)}}async function U(e,t,n,r){try{return await n()}catch(n){return e.warn(`gateway hook ${t} failed (fail-open): ${String(n)}`),r}}const W=`@tbox.cn/tboxcode-dsh-sdk`;export{I as ABSTAIN_RPC_ERROR,v as CarrierRpcError,y as CarrierTransportError,b as DshCarrier,P as FORM_BUDGET_MS,w as FanoutRouter,C as FollowPool,N as GRACE_WINDOW_MS,L as InteractionRegistry,M as InterruptionMonitor,W as PACKAGE_NAME,F as PERMISSION_MEMBER_TIMEOUT_MS,A as RpcSessionDeps,u as Supervisor,s as SupervisorDeploymentError,R as attachAcpGateway,S as decodeWireEvent,l as exchangeCredentialsViaConnect,f as isRecord,j as openCommandsChangeEventStream,_ as parseWireEventFrame,h as parseWireFollowFrame,m as parseWireHistoryRecord,g as parseWirePage,p as parseWireSessionEvent,U as runHookOpen};
|
package/package.json
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tbox.cn/tboxcode-dsh-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
3
|
+
"version": "0.1.0-rc.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "AcpGateway 扩展点 + Supervisor + 直连 RPC 面(薄 carrier:POST envelope + WS mux + /connect 凭据交换,运行时零 dsh 包依赖)+ 上链 ACP server 面 + wire 契约与 decodeWireEvent;agtcodingbox 唯一依赖面",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"lib"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"ws": "^8.19.0",
|
|
19
|
+
"@tbox.cn/dsh-acp-bridge-core": "0.1.0-rc.1",
|
|
20
|
+
"@tbox.cn/dsh-acp-full": "0.1.0-rc.1"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/ws": "^8.18.1",
|
|
24
|
+
"@agentclientprotocol/sdk": "1.8.0"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsdown",
|
|
28
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
29
|
+
}
|
|
6
30
|
}
|
package/README.md
DELETED