@x-otto/service 0.0.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,617 @@
1
+ import { Context, Hono } from "hono";
2
+ import { TypedEventEmitter } from "@x-otto/shared";
3
+ import { ProjectorState, SessionEvent, createProjectorState } from "@x-otto/session-contract";
4
+ import { Devtools, PauseResumePayload } from "@x-otto/devtools";
5
+ import { AgentSessionEvent, GrillAnswer, TraceEvent } from "@x-otto/agent";
6
+ import { IncomingMessage, Server } from "node:http";
7
+ import { StorageHost } from "@x-otto/persistence";
8
+ import { AgentSession, ServiceHostPort } from "@x-otto/coding";
9
+ import { Socket } from "node:net";
10
+
11
+ //#region src/message-serializer.d.ts
12
+ interface SerializedToolCall {
13
+ id: string;
14
+ name: string;
15
+ parameters: Record<string, unknown>;
16
+ }
17
+ interface SerializedMessage {
18
+ role: string;
19
+ content: string;
20
+ timestamp: number | undefined;
21
+ toolCalls: SerializedToolCall[];
22
+ /**
23
+ * RFC-210 D5(M4,评审 A5 REST 水合缺口修复):消息 content 数组中的 a2ui block
24
+ * 组件树透传(此前 extractContent 只取 text block,a2ui 数据在历史水合路径丢失)。
25
+ * 无 a2ui block 时字段缺省(不占 wire 体积)。web-ui 水合层(message-hydration)按
26
+ * 此字段渲染 React catalog(M5)。
27
+ */
28
+ a2ui?: unknown[][];
29
+ }
30
+ //#endregion
31
+ //#region src/types.d.ts
32
+ type WebSocketMessage = {
33
+ type: 'Runtime.connected';
34
+ data: {
35
+ clientId: string;
36
+ };
37
+ } | {
38
+ type: 'Runtime.pong';
39
+ data: {
40
+ timestamp: number;
41
+ };
42
+ } | {
43
+ type: 'Runtime.error';
44
+ data: {
45
+ sessionId?: string;
46
+ message: string;
47
+ code?: string; /** RFC-335 S4:WRITE_LEASE_DENIED 之持有者客户端 id(拒绝反馈(非广播——同一 clientId 呈报) */
48
+ leaseOwner?: string;
49
+ };
50
+ } | {
51
+ type: 'Runtime.writeLease';
52
+ data: {
53
+ sessionId: string;
54
+ state: 'acquired' | 'denied' | 'released' | 'not-held';
55
+ reason?: string; /** 当前持有者 clientId(acquired/denied/not-held 都为非空——语义否定据以下判定);released 则为 undefined */
56
+ leaseOwner?: string;
57
+ };
58
+ } | {
59
+ type: 'Session.event';
60
+ data: SessionEvent & {
61
+ seq?: number;
62
+ };
63
+ } | {
64
+ type: 'Chat.nestedToolCall';
65
+ data: {
66
+ sessionId: string;
67
+ id: string;
68
+ name: string;
69
+ arguments: Record<string, unknown>;
70
+ };
71
+ } | {
72
+ type: 'Chat.nestedToolResult';
73
+ data: {
74
+ sessionId: string;
75
+ id: string;
76
+ isError: boolean;
77
+ };
78
+ } | {
79
+ type: 'Chat.planContent';
80
+ data: {
81
+ sessionId: string;
82
+ content: string;
83
+ };
84
+ } | {
85
+ type: 'Chat.subagentStart';
86
+ data: {
87
+ sessionId: string;
88
+ agentName: string;
89
+ };
90
+ } | {
91
+ type: 'Chat.subagentComplete';
92
+ data: {
93
+ sessionId: string;
94
+ agentName: string;
95
+ };
96
+ } | {
97
+ type: 'Chat.parallelAgentsStart';
98
+ data: {
99
+ sessionId: string;
100
+ count: number;
101
+ };
102
+ } | {
103
+ type: 'Chat.parallelAgentsDone';
104
+ data: {
105
+ sessionId: string;
106
+ };
107
+ } | {
108
+ type: 'Chat.taskCompleted';
109
+ data: {
110
+ sessionId: string;
111
+ taskId: string;
112
+ };
113
+ } | {
114
+ type: 'MCP.statusUpdate';
115
+ data: {
116
+ serverId: string;
117
+ status: string;
118
+ };
119
+ } | {
120
+ type: 'MCP.serversUpdate';
121
+ data: {
122
+ servers: unknown[];
123
+ };
124
+ } | {
125
+ type: 'Debugger.paused';
126
+ data: {
127
+ reason: string;
128
+ pauseId: string;
129
+ point?: unknown;
130
+ snapshot?: Record<string, unknown>;
131
+ timestamp: string;
132
+ };
133
+ } | {
134
+ type: 'Debugger.resumed';
135
+ data: {
136
+ pauseId: string;
137
+ command?: unknown;
138
+ timestamp: string;
139
+ };
140
+ } | {
141
+ type: 'Debugger.commandRejected';
142
+ data: {
143
+ code: string;
144
+ pauseId?: string;
145
+ command?: unknown;
146
+ timestamp: string;
147
+ };
148
+ } | {
149
+ type: 'Debugger.breakpointsChanged';
150
+ data: {
151
+ breakpoints: unknown[];
152
+ };
153
+ } | {
154
+ type: 'Log.entryAdded';
155
+ data: {
156
+ entry: LogEntryData;
157
+ };
158
+ } | {
159
+ type: 'Trace.event';
160
+ data: {
161
+ sessionId: string;
162
+ seq: number;
163
+ event: TraceEvent;
164
+ };
165
+ };
166
+ interface LogEntryData {
167
+ id: number;
168
+ timestamp: string;
169
+ level: string;
170
+ module: string;
171
+ message: string;
172
+ data?: Record<string, unknown>;
173
+ }
174
+ /**
175
+ * 客户端发来的消息在传输层统一为此形式,data 字段在各 handler 中按协议解析。
176
+ * 具体各消息的 data shape 见 WebSocketClientData 类型映射。
177
+ */
178
+ interface WebSocketClientMessage {
179
+ type: WebSocketClientMessageType;
180
+ data: Record<string, unknown>;
181
+ }
182
+ type WebSocketClientMessageType = 'Runtime.ping' | 'Chat.query' | 'Chat.approval' | 'Chat.askUserResponse' | 'Chat.planApprovalResponse' | 'Session.subscribe' | 'Session.unsubscribe' | 'Session.writeLease.acquire' | 'Session.writeLease.release' | 'Session.writeLease.force_acquire' | 'Debugger.resume' | 'Debugger.stepOver' | 'Debugger.stepInto' | 'Debugger.disable' | 'Debugger.setBreakpoint' | 'Debugger.setBreakpointsActive';
183
+ interface ChatQueryData {
184
+ message: string;
185
+ sessionId?: string;
186
+ }
187
+ interface ChatApprovalData {
188
+ approvalId: string;
189
+ approved: boolean;
190
+ sessionId?: string;
191
+ }
192
+ interface ChatAskUserResponseData {
193
+ requestId: string;
194
+ answers: GrillAnswer | null;
195
+ cancelled?: boolean;
196
+ sessionId?: string;
197
+ }
198
+ interface ChatPlanApprovalResponseData {
199
+ requestId: string;
200
+ action: string;
201
+ feedback?: string;
202
+ sessionId?: string;
203
+ }
204
+ interface SessionSubscribeData {
205
+ sessionId: string;
206
+ /**
207
+ * RFC-335 M3:客户端已消费到的事件游标(取自 `SessionSnapshot.cursor`)。
208
+ * 服务端补发其后的事件再转实时流;缺省 = 只要实时流(旧客户端行为)。
209
+ */
210
+ since?: number;
211
+ }
212
+ interface DebuggerCommandData {
213
+ seq?: number;
214
+ pauseId?: string;
215
+ depth?: number;
216
+ }
217
+ interface DebuggerSetBreakpointData {
218
+ point: string;
219
+ enabled: boolean;
220
+ }
221
+ interface DebuggerSetBreakpointsActiveData {
222
+ active: boolean;
223
+ }
224
+ /**
225
+ * RFC-335 M1:服务实例的只读 Authority 身份。客户端只能以此描述符识别
226
+ * 唯一 Session Authority,不能据此构造或持有 AgentSession。
227
+ */
228
+ interface AuthorityDescriptor {
229
+ /** 每个 CodingService 实例生命周期内稳定;进程/服务重启后必变。非鉴权 token。 */
230
+ instanceId: string;
231
+ /** authority 所属 workspace;客户端不得把它当作跨 workspace 路由许可。 */
232
+ workspaceDir: string;
233
+ /** 当前只声明快照与 session 事件订阅能力。cursor 原子接续在 RFC-335 M3 才引入。 */
234
+ protocolVersion: 1;
235
+ capabilities: readonly ('session.snapshot' | 'session.subscribe')[];
236
+ }
237
+ /** RFC-335 M1 的只读 session 水合 DTO。它不是与 WS 增量原子接续的 cursor;M3 解决该竞态。 */
238
+ interface SessionSnapshot {
239
+ authority: AuthorityDescriptor;
240
+ session: {
241
+ id: string;
242
+ status: string;
243
+ messageCount: number; /** 与 `GET /api/sessions/:id/messages` 同一序列化契约(单一真源,消费方无需 assert)。 */
244
+ messages: SerializedMessage[];
245
+ };
246
+ /**
247
+ * RFC-335 M3:快照时刻的 `Session.event` 序列号。订阅时作为 `Session.subscribe.since`
248
+ * 传回,服务端据此补发期间事件,实现 snapshot→subscribe 无缝接续。
249
+ *
250
+ * 边界:只保证 `Session.event` 域;`Trace.event`/`Debugger.*` 不在其中(见
251
+ * `session-event-log.ts` 头注释)。
252
+ *
253
+ * 客户端 **MUST 按 `seq` 排序并去重**——补发走定向通道、实时流走订阅通道,
254
+ * 到达顺序不保证等于 seq 顺序。
255
+ */
256
+ cursor: number;
257
+ snapshotAt: string;
258
+ }
259
+ interface CodingServiceOptions {
260
+ host?: string;
261
+ port: number;
262
+ /** 测试/嵌入式宿主可注入稳定 identity;生产默认由服务实例生成。 */
263
+ authorityId?: string;
264
+ staticDir?: string;
265
+ cors?: string;
266
+ wsAuthToken?: string;
267
+ apiToken?: string;
268
+ }
269
+ interface IMessageSender {
270
+ broadcast(message: WebSocketMessage): void;
271
+ sendToSession(sessionId: string, message: WebSocketMessage): void;
272
+ sendToSubscribers(sessionId: string, message: WebSocketMessage): void;
273
+ }
274
+ //#endregion
275
+ //#region src/session-event-log.d.ts
276
+ /** 单条已编号事件。`seq` 在单个 session 内单调递增,从 1 开始。 */
277
+ interface SequencedEvent {
278
+ seq: number;
279
+ message: WebSocketMessage;
280
+ }
281
+ type EventLogRead = /** 成功:`events` 是 cursor 之后的全部事件(可能为空,表示客户端已是最新)。 */{
282
+ ok: true;
283
+ events: SequencedEvent[];
284
+ }
285
+ /**
286
+ * 失败:请求的 cursor 已被环形缓冲逐出,无法补齐中间缺口。
287
+ * 调用方**必须**让客户端重新全量水合,不得降级为部分补发。
288
+ */
289
+ | {
290
+ ok: false;
291
+ reason: 'gap';
292
+ oldestAvailable: number;
293
+ };
294
+ declare class SessionEventLog {
295
+ private readonly capacity;
296
+ private readonly buffers;
297
+ private readonly cursors;
298
+ constructor(capacity?: number);
299
+ /** 追加一条事件并返回其序列号。序列号由本方法唯一分配,调用方不得自行编号。 */
300
+ append(sessionId: string, message: WebSocketMessage): number;
301
+ /** 当前游标(= 已分配的最大序列号)。session 无事件时为 0。 */
302
+ cursorOf(sessionId: string): number;
303
+ /**
304
+ * 读取 `after` 之后的事件。
305
+ *
306
+ * `after === cursorOf()` → 成功且为空(客户端已最新)。
307
+ * `after` 早于缓冲区最旧一条 → `gap` 失败(中间已被逐出,无法诚实补齐)。
308
+ */
309
+ readFrom(sessionId: string, after: number): EventLogRead;
310
+ /** 会话结束/detach 时清理,避免 Map 无界增长。 */
311
+ clear(sessionId: string): void;
312
+ }
313
+ //#endregion
314
+ //#region src/websocket-manager.d.ts
315
+ interface WebSocketManagerEvents {
316
+ message: (clientId: string, message: WebSocketClientMessage) => void;
317
+ }
318
+ interface WebSocketManagerOptions {
319
+ allowedOrigins?: string[];
320
+ authToken?: string;
321
+ maxPayloadBytes?: number;
322
+ maxMessagesPerSecond?: number;
323
+ maxConnections?: number;
324
+ }
325
+ declare class WebSocketManager extends TypedEventEmitter<WebSocketManagerEvents> {
326
+ private readonly wss;
327
+ private readonly clients;
328
+ private readonly sessionSubscriptions;
329
+ private readonly options;
330
+ private readonly maxMessagesPerSecond;
331
+ private readonly maxConnections;
332
+ private clientId;
333
+ /** RFC-335 S4:client 断连触发点——InboundRouter 释放 write-lease。 */
334
+ onClientDisconnected?: (clientId: string) => void;
335
+ get clientCount(): number;
336
+ constructor(options?: WebSocketManagerOptions);
337
+ handleUpgrade(request: IncomingMessage, socket: Socket, head: Buffer, pathname: string): boolean;
338
+ private rejectUpgrade;
339
+ private isOriginAllowed;
340
+ private isTokenValid;
341
+ broadcast(message: WebSocketMessage): void;
342
+ sendToSession(sessionId: string, message: WebSocketMessage): void;
343
+ sendToSubscribers(sessionId: string, message: WebSocketMessage): void;
344
+ subscribeClient(clientId: string, sessionId: string): void;
345
+ unsubscribeClient(clientId: string, sessionId: string): void;
346
+ clearSessionSubscriptions(sessionId: string): void;
347
+ sendToClient(clientId: string, message: WebSocketMessage): void;
348
+ close(): void;
349
+ private onConnection;
350
+ private handleSystemClientMessage;
351
+ private handleRuntimePing;
352
+ private normalizeClientMessage;
353
+ private asRecord;
354
+ }
355
+ //#endregion
356
+ //#region src/debug-bridge.d.ts
357
+ interface DebugBridgeEvents {
358
+ 'Debugger.paused': (data: Record<string, unknown>) => void;
359
+ 'Debugger.resumed': (data: Record<string, unknown>) => void;
360
+ 'Debugger.commandRejected': (data: Record<string, unknown>) => void;
361
+ 'Log.entryAdded': (entry: LogEntryData) => void;
362
+ }
363
+ interface SendCommand {
364
+ type: string;
365
+ seq: number;
366
+ depth?: number;
367
+ [extra: string]: unknown;
368
+ }
369
+ declare class DebugBridge extends TypedEventEmitter<DebugBridgeEvents> {
370
+ private readonly devtools;
371
+ private readonly sender;
372
+ private logId;
373
+ private attached;
374
+ private readonly unsubs;
375
+ private readonly logs;
376
+ /**
377
+ * RFC-222 D3:`pauseId → sessionId` 映射——`Debugger.paused` 事件携带完整
378
+ * snapshot(`metadata.sessionId`),但 `Debugger.resumed`/`commandRejected`
379
+ * 只携带 `pauseId`/`command`,不重复携带 snapshot。记录映射使后两者也能按
380
+ * session 路由;`resumed` 触发后该 pauseId 已终结,随即清理避免无界增长。
381
+ */
382
+ private readonly pauseSessionMap;
383
+ constructor(devtools: Devtools, sender: IMessageSender);
384
+ attach(): void;
385
+ detach(): void;
386
+ /** snapshot.metadata.sessionId 提取(RFC-222 D3,缺省/非字符串时返回 undefined)。 */
387
+ private extractSessionId;
388
+ /** 进程内直连:attach 即可达(旧语义=worker WS socket 打开)。REST 端点据此判断可送达。 */
389
+ get isConnected(): boolean;
390
+ send(command: SendCommand, payload?: PauseResumePayload): void;
391
+ getLogs(): LogEntryData[];
392
+ /**
393
+ * RFC-222 D3:`sessionId` 已知时定向路由到该 session 的订阅者(`sendToSession`),
394
+ * 避免调试事件跨 session 泄漏;`sessionId` 未知(如 snapshot 未携带 metadata.sessionId
395
+ * 的历史/边缘调用点)时降级为 `broadcast`,不强行拆分导致事件丢失可见性。
396
+ */
397
+ private forwardDebugEvent;
398
+ private handleLogMessage;
399
+ private normalizeLevel;
400
+ }
401
+ //#endregion
402
+ //#region src/coding-service.d.ts
403
+ declare class CodingService {
404
+ readonly app: ServiceHostPort;
405
+ private readonly httpApp;
406
+ private readonly server;
407
+ private readonly host;
408
+ private readonly port;
409
+ private readonly staticDir?;
410
+ private readonly apiToken?;
411
+ private readonly wsAuthToken?;
412
+ /** RFC-335 M1:本 Authority 实例的非秘密身份;只用于 lifecycle state 与客户端重连判别。 */
413
+ private readonly authority;
414
+ /** RFC-335 M3:per-session 事件序列号 + 有界历史,支撑 snapshot→subscribe 无缝接续。 */
415
+ private readonly eventLog;
416
+ private readonly bridges;
417
+ private readonly traceBridges;
418
+ private readonly router;
419
+ private started;
420
+ readonly bridge: DebugBridge | null;
421
+ readonly ws: WebSocketManager;
422
+ get httpServer(): Server;
423
+ constructor(app: ServiceHostPort, options: CodingServiceOptions);
424
+ registerHooks(app: ServiceHostPort): void;
425
+ unregisterHooks(app: ServiceHostPort): void;
426
+ getSession(sessionId: string): AgentSession | undefined;
427
+ getActiveSession(): AgentSession | undefined;
428
+ /** RFC-335 M1:可序列化的唯一 session authority 描述符。 */
429
+ getAuthorityDescriptor(): AuthorityDescriptor;
430
+ /**
431
+ * RFC-335 M1/M3:只读水合快照,携带 `cursor`(拍摄快照时该 session 的事件序列号)。
432
+ *
433
+ * 客户端凭 `cursor` 订阅(`Session.subscribe` 带 `since`)即可获得**无缝接续**:
434
+ * 服务端先补发 cursor 之后的事件,再转实时流。若 cursor 已被环形缓冲逐出,服务端
435
+ * 会明确回报 gap 而非静默少发(见 `SessionEventLog`)。
436
+ */
437
+ getSessionSnapshot(sessionId: string): SessionSnapshot | undefined;
438
+ /** RFC-335 M3:读取 cursor 之后的事件(供 WS 订阅补发)。 */
439
+ readSessionEventsSince(sessionId: string, after: number): EventLogRead;
440
+ private readonly onUpgrade;
441
+ private readonly onWsMessage;
442
+ start(): Promise<void>;
443
+ stop(): Promise<void>;
444
+ attachSession(session: AgentSession): void;
445
+ detachSession(sessionId: string): void;
446
+ static(c: Context): Response;
447
+ }
448
+ declare function createCodingService(app: ServiceHostPort, options: CodingServiceOptions): CodingService;
449
+ //#endregion
450
+ //#region src/event-bridge.d.ts
451
+ declare class EventBridge {
452
+ private readonly session;
453
+ private readonly sender;
454
+ /**
455
+ * 可选——供 `pulse-survey.show` 触发判定读取 `mars.getPulseSurveyConfig()`
456
+ * 与 `mars.isFeedbackAvailable()`。测试/未来其他消费方可不传(该判定分支静默跳过)。
457
+ */
458
+ private readonly app?;
459
+ private unsubscribeSession?;
460
+ /** per-session 投影累加器(delegated/todoList/turn)。 */
461
+ private projector;
462
+ /**
463
+ * RFC-209 §2.5:满意度脉冲调查触发状态(进程内存态,per-session,不持久化跨会话——
464
+ * 同 CLI 侧 `interactive-events.ts` 的 `pulseSurveyTriggerState` 语义,各自独立维护
465
+ * 互不干扰:TUI 与 web-ui 是两个并发客户端,各自的展示节奏不应互相耦合)。
466
+ */
467
+ private pulseSurveyState;
468
+ constructor(session: AgentSession, sender: IMessageSender,
469
+ /**
470
+ * 可选——供 `pulse-survey.show` 触发判定读取 `mars.getPulseSurveyConfig()`
471
+ * 与 `mars.isFeedbackAvailable()`。测试/未来其他消费方可不传(该判定分支静默跳过)。
472
+ */
473
+
474
+ app?: ServiceHostPort | undefined);
475
+ attach(): void;
476
+ /**
477
+ * RFC-210 D5(M4):`tool.call.end` 之后的旁路编排(同 maybeSendPulseSurvey 模式,
478
+ * 不进 encodeSessionEvent 纯投影)——对该工具调用的结果消息跑插件 `a2ui.renderer`
479
+ * toPayload,命中则追加 `a2ui.payload` 事件下发。web-ui 经 React catalog 渲染(M5)。
480
+ * fail-soft:无 mars / 无插件命中 / toPayload 全部失败 → 静默跳过(默认渲染兜底)。
481
+ * async fire-and-forget:toPayload 有 2s 超时(ui-renderer-loader),不阻塞事件主流。
482
+ */
483
+ private maybeSendA2uiRendererPayload;
484
+ /**
485
+ * RFC-209 §2.5:`prompt.end` 之后的旁路编排——不是 `encodeSessionEvent` 投影产出的分支
486
+ * (该函数保持纯投影职责不变),而是本类在收到投影消息之后**额外**追加的判定+发送。
487
+ * Feedback 插件未装载时 `isFeedbackAvailable()` 为 false,静默跳过(fail-soft,同 §2.6)。
488
+ * web-ui 无 TUI 的 forced-upgrade Band A 硬模态概念,`forcedUpgradeActive` 恒 false。
489
+ */
490
+ private maybeSendPulseSurvey;
491
+ detach(): void;
492
+ }
493
+ //#endregion
494
+ //#region src/inbound-router.d.ts
495
+ declare class InboundRouter {
496
+ private readonly ws;
497
+ private readonly app;
498
+ private readonly bridge;
499
+ /**
500
+ * RFC-335 M3:按 cursor 读取待补发事件。以回调注入而非直接依赖 CodingService,
501
+ * 避免 router ↔ service 循环依赖(CodingService 已持有 router)。
502
+ * 未注入时 `since` 参数被忽略,退化为纯实时订阅(旧行为)。
503
+ */
504
+ private readonly readEventsSince?;
505
+ /** RFC-335 S4 协议面:session 写租约 per-session 单持有者裁决。仅由 dispatch 路径 mutation。 */
506
+ private readonly writeLease;
507
+ constructor(ws: WebSocketManager, app: ServiceHostPort, bridge: DebugBridge | null,
508
+ /**
509
+ * RFC-335 M3:按 cursor 读取待补发事件。以回调注入而非直接依赖 CodingService,
510
+ * 避免 router ↔ service 循环依赖(CodingService 已持有 router)。
511
+ * 未注入时 `since` 参数被忽略,退化为纯实时订阅(旧行为)。
512
+ */
513
+
514
+ readEventsSince?: ((sessionId: string, after: number) => EventLogRead) | undefined);
515
+ dispatch(clientId: string, message: WebSocketClientMessage): void;
516
+ /**
517
+ * RFC-335 M3:补发 `after` 之后的事件,衔接 snapshot 与实时流。
518
+ *
519
+ * 缺口(cursor 已被环形缓冲逐出)时**必须**显式告知客户端重新水合,绝不静默补发
520
+ * "能补的那部分"——那会让客户端以为序列完整,实则中间缺一段且永远无法察觉。
521
+ */
522
+ private replaySince;
523
+ private resolveSession;
524
+ /**
525
+ * RFC-222 D2:prompt 被拒绝(如并发 isBusy 守卫)时的错误必须**定向**发给触发本次
526
+ * 请求的客户端(`sendToClient`),不得广播给该 session 的全部订阅者(`sendToSession`)
527
+ * ——多端场景下正在正常执行中的其他客户端不应收到与自己无关的 "prompt failed"。
528
+ */
529
+ private handleQuery;
530
+ private handleApproval;
531
+ private handleAskUserResponse;
532
+ private handlePlanApprovalResponse;
533
+ private handleDebugCommand;
534
+ private handleDebugSetBreakpoint;
535
+ private handleDebugSetBreakpointsActive;
536
+ }
537
+ //#endregion
538
+ //#region src/session-event-wire.d.ts
539
+ /** 投影 + 脱敏 + 包装为 WS `Session.event`。projector 为调用方持有的 per-session 累加器。 */
540
+ declare function encodeSessionEvent(event: AgentSessionEvent, projector: ProjectorState): WebSocketMessage[];
541
+ //#endregion
542
+ //#region src/persistenced-app.d.ts
543
+ interface PersistencedOptions {
544
+ dir: string;
545
+ port?: number;
546
+ /** 必填,fail-closed。 */
547
+ token: string;
548
+ /** 默认 sessions;knowledge/archive namespace 已退场,memory=文件。 */
549
+ namespaces?: string[];
550
+ /** 默认 127.0.0.1;0.0.0.0 = 公网暴露。 */
551
+ host?: string;
552
+ /** 默认不启用 CORS。 */
553
+ corsOrigin?: string;
554
+ rateLimitRps?: number;
555
+ maxBodyBytes?: number;
556
+ }
557
+ /** persistenced 服务默认监听端口——族内单源(cli/persistenced.ts 复用,消除双源漂移)。 */
558
+ declare const PERSISTENCED_DEFAULT_PORT = 3001;
559
+ /**
560
+ * 启动 persistenced 独立服务。
561
+ *
562
+ * 返回 { app, server, host: StorageHost } 供测试注入/优雅退出。
563
+ */
564
+ declare function startPersistenced(options: PersistencedOptions): Promise<{
565
+ app: Hono;
566
+ server: Server;
567
+ host: StorageHost;
568
+ url: string;
569
+ }>;
570
+ //#endregion
571
+ //#region src/event-bus.d.ts
572
+ /**
573
+ * 进程内事件总线(M29-04-01)。
574
+ *
575
+ * SSE 路由和 storage append 路由共享此实例:
576
+ * - SSE: `eventBus.on(topic, cb)` 订阅 append 事件 → SSE push
577
+ * - Storage: `eventBus.emit(event)` 发布 append 事件 → 广播给所有 SSE 订阅者
578
+ *
579
+ * 设计决策:模块级单例而非 CodingService 成员——
580
+ * 两个独立路由(events.ts 和 storage.ts)都需要访问同一实例,
581
+ * 单例避免了通过 CodingService 传参的耦合。
582
+ */
583
+ interface AppendEvent {
584
+ /** topic,如 'sessions'。 */
585
+ namespace: string;
586
+ /**
587
+ * workspace 分区键。SSE live-push 据此按订阅者 wsKey 过滤——缺省(legacy/单租户)
588
+ * 不携带则订阅者收全量。多租户下 emit 必带,订阅者按 wsKey 隔离(防 B12 跨 workspace 泄漏)。
589
+ */
590
+ wsKey?: string;
591
+ docId: string;
592
+ entry: unknown;
593
+ /** Unix ms。 */
594
+ ts: number;
595
+ }
596
+ type Unsubscribe = () => void;
597
+ declare class EventBus {
598
+ private listeners;
599
+ /**
600
+ * 订阅某个 namespace 的 append 事件。
601
+ * @returns 取消订阅函数。
602
+ */
603
+ on(namespace: string, callback: (event: AppendEvent) => void): Unsubscribe;
604
+ /**
605
+ * 发布 append 事件到所有订阅了对应 namespace 的监听器。
606
+ * 单个监听器异常不影响其他监听器。
607
+ */
608
+ emit(event: AppendEvent): void;
609
+ /** 仅测试使用。 */
610
+ reset(): void;
611
+ /** 调试/测试用。 */
612
+ get listenerCount(): number;
613
+ }
614
+ declare const eventBus: EventBus;
615
+ //#endregion
616
+ export { type AppendEvent, type AuthorityDescriptor, type ChatApprovalData, type ChatAskUserResponseData, type ChatPlanApprovalResponseData, type ChatQueryData, CodingService, type CodingServiceOptions, DebugBridge, type DebuggerCommandData, type DebuggerSetBreakpointData, type DebuggerSetBreakpointsActiveData, EventBridge, EventBus, type EventLogRead, type IMessageSender, InboundRouter, type LogEntryData, PERSISTENCED_DEFAULT_PORT, type PersistencedOptions, type ProjectorState, type SequencedEvent, type SerializedMessage, type SerializedToolCall, SessionEventLog, type SessionSnapshot, type SessionSubscribeData, type Unsubscribe, type WebSocketClientMessage, type WebSocketClientMessageType, WebSocketManager, type WebSocketMessage, createCodingService, createProjectorState, encodeSessionEvent, eventBus, startPersistenced };
617
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/message-serializer.ts","../src/types.ts","../src/session-event-log.ts","../src/websocket-manager.ts","../src/debug-bridge.ts","../src/coding-service.ts","../src/event-bridge.ts","../src/inbound-router.ts","../src/session-event-wire.ts","../src/persistenced-app.ts","../src/event-bus.ts"],"mappings":"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"}