@dshremote/protocol 0.1.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.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @dshremote/protocol
2
+
3
+ DshRemote 共享协议包:**单一事实来源**,同时被 Connector Plugin 与 Control Plane 引用。
4
+
5
+ ## 内容
6
+
7
+ | 文件 | 说明 |
8
+ | --- | --- |
9
+ | `schemas/dshremote-event-v1.schema.json` | 事件契约 v1(技术方案 §3):Connector 上传到 Control Plane 的结构化 Session 事件信封与全部 kind 的 payload |
10
+ | `schemas/dshremote-protocol-v1.schema.json` | 通信协议 v1(技术方案 §4):C2C 消息信封与全部消息类型的 payload |
11
+ | `src/types.ts` | 上述两个 Schema 的 TS 投影(`DshRemoteEvent` / `C2CMessage` 判别联合) |
12
+
13
+ ## 维护约束
14
+
15
+ - **三处同步**:修改契约必须同时更新 `src/types.ts`、对应 schema JSON、以及《DshRemote 技术方案》§3/§4。
16
+ - **兼容性**:任何 breaking 变更必须升 `version`/`protocolVersion`/`schemaVersion` 并走连接握手协商(`hello`/`helloAck`),不允许静默改字段。
17
+ - **敏感性**:契约只允许结构化安全子集(脱敏、截断);完整 Prompt、环境变量、Provider 凭据、不必要的完整命令输出一律禁止进入本契约(FR-009.7)。
package/lib/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './types.js';
@@ -0,0 +1 @@
1
+ export * from './types.js';
@@ -0,0 +1,572 @@
1
+ /**
2
+ * @dshremote/protocol —— DshRemote 共享协议类型。
3
+ *
4
+ * 单一事实来源:`schemas/dshremote-event-v1.schema.json`(事件契约 v1)
5
+ * 与 `schemas/dshremote-protocol-v1.schema.json`(Connector↔Control Plane 通信协议)。
6
+ * 本文件是这些 Schema 的 TS 投影;改动必须三处同步(types.ts / 两个 schema / 设计文档 §3、§4)。
7
+ *
8
+ * 对应《DshRemote 技术方案 v0.1》§3(事件契约)与 §4(通信协议)。
9
+ */
10
+ export type JsonValue = null | boolean | number | string | JsonValue[] | {
11
+ [key: string]: JsonValue;
12
+ };
13
+ /** 通用标识(connectionId / sessionId / runId / taskId / projectId 等)。 */
14
+ export type DshRemoteId = string;
15
+ export declare const EVENT_KINDS: readonly ["sessionMeta", "turnStart", "turnEnd", "stepStart", "stepEnd", "userMessage", "assistantMessage", "toolCall", "toolResult", "error", "approvalAsked", "approvalDecided", "runStatus", "artifactRef"];
16
+ export type EventKind = (typeof EVENT_KINDS)[number];
17
+ /** 文本内容块。 */
18
+ export interface TextBlock {
19
+ type: 'text';
20
+ text: string;
21
+ }
22
+ /** 思考/推理内容块(对应 Harness ContentBlock 的 reasoning 类型,渲染为可折叠 "Think")。 */
23
+ export interface ReasoningBlock {
24
+ type: 'reasoning';
25
+ text: string;
26
+ }
27
+ /** 内容块:v1 仅 text + reasoning(与 Harness ContentBlock 对齐);图片/附件引用留待 v1.1。 */
28
+ export type ContentBlock = TextBlock | ReasoningBlock;
29
+ /** 脱敏后的 token 用量摘要(不允许出现 Provider 原始账单元数据)。 */
30
+ export interface TokenUsageSummary {
31
+ inputTokens?: number;
32
+ outputTokens?: number;
33
+ /** 缓存命中读取 token(provider 回报该桶时才有)。 */
34
+ cacheReadTokens?: number;
35
+ /** 缓存写入 token(provider 回报该桶时才有)。 */
36
+ cacheWriteTokens?: number;
37
+ /** 推理输出 token 子集(provider 回报该桶时才有)。 */
38
+ reasoningTokens?: number;
39
+ /** 输入 + 输出精确合计(provider 回报或可推导时才有)。 */
40
+ totalTokens?: number;
41
+ /** 本轮贡献的 provider/model 路由(去重,供「提供方/模型」展示)。 */
42
+ routes?: Array<{
43
+ provider?: string;
44
+ model?: string;
45
+ }>;
46
+ }
47
+ /**
48
+ * 单步 LLM 耗时快照(由 connector 在采集时从 harness 事件时间推导,对齐官方
49
+ * sessionStats 口径:step/start → assistant/message = llmMs;首个 token delta →
50
+ * ttftMs;随后到 assistant/message = decodeMs)。web 侧据此折叠每轮/全程统计。
51
+ */
52
+ export interface LLMTiming {
53
+ /** step/start → assistant/message 的模型墙钟耗时(ms)。 */
54
+ llmMs: number;
55
+ /** step/start → 首个 token delta(ms);该步未产出 token delta 时缺省。 */
56
+ ttftMs?: number;
57
+ /** 首个 token delta → assistant/message(ms);无首 token 时缺省。 */
58
+ decodeMs?: number;
59
+ }
60
+ /** turn 结束原因,映射自 Harness TurnEndReasonMap(session.md)。 */
61
+ export type TurnEndReason = 'completed' | 'aborted' | 'blocked' | 'error' | 'max-tokens' | 'interrupted';
62
+ /** Run 状态,映射自需求 FR-007。 */
63
+ export type RunStatus = 'Queued' | 'Running' | 'WaitingForApproval' | 'Completed' | 'Failed' | 'Stopped' | 'ConnectionLost' | 'TimedOut' | 'LimitReached';
64
+ /** 审批结果,映射自 Harness ApprovalOutcome(approval.md)。 */
65
+ export type ApprovalOutcome = 'allowed-once' | 'rejected' | 'cancelled' | 'unavailable';
66
+ export interface ErrorSummary {
67
+ message: string;
68
+ code?: string;
69
+ /** 可关联的错误标识(不泄露 Secret)。 */
70
+ errorId?: string;
71
+ }
72
+ export interface SessionMetaPayload {
73
+ title?: string;
74
+ /** cwd 摘要:只允许目录名等非敏感摘要,禁止绝对路径。 */
75
+ cwdSummary?: string;
76
+ projectId?: string;
77
+ createdBy: 'local' | 'webhook' | 'cloud';
78
+ }
79
+ export interface TurnStartPayload {
80
+ turn: number;
81
+ }
82
+ export interface TurnEndPayload {
83
+ turn: number;
84
+ reason: TurnEndReason;
85
+ error?: ErrorSummary;
86
+ }
87
+ export interface StepStartPayload {
88
+ turn: number;
89
+ step: number;
90
+ }
91
+ export interface StepEndPayload {
92
+ turn: number;
93
+ step: number;
94
+ }
95
+ export interface UserMessagePayload {
96
+ content: ContentBlock[];
97
+ source: 'user' | 'inject' | 'webhook' | 'plugin';
98
+ /** source 为 'plugin' 时的插件名(远程投递记 'dshremote';harness 上下文快照记
99
+ * '@deepseek-ai/dsh-system-prompt')。web 据此把「远程用户消息」与「上下文注入」区分。 */
100
+ sourcePlugin?: string;
101
+ /** source 为 'plugin' 时的 form(如 'snapshot'),用于标注上下文快照。 */
102
+ sourceForm?: string;
103
+ }
104
+ export interface AssistantMessagePayload {
105
+ content: ContentBlock[];
106
+ usage?: TokenUsageSummary;
107
+ interrupted?: boolean;
108
+ /** 单步 LLM 耗时(第 3 步采集;被中断/无 timing 时缺省)。 */
109
+ timing?: LLMTiming;
110
+ }
111
+ export interface ToolCallPayload {
112
+ callId: string;
113
+ name: string;
114
+ /** 模型原始 arguments JSON 字符串(脱敏 + 截断后)。 */
115
+ arguments: string;
116
+ }
117
+ export interface ToolResultPayload {
118
+ callId: string;
119
+ /** 结果摘要(非完整输出)。 */
120
+ summary?: string;
121
+ error?: {
122
+ name: string;
123
+ code: string;
124
+ };
125
+ /** 白名单字段(如 dsh-tool-fs 的上下文 diff),其余丢弃。 */
126
+ meta?: Record<string, JsonValue>;
127
+ }
128
+ export interface ErrorEventPayload {
129
+ error: ErrorSummary;
130
+ /** 关联的 turn(若有)。 */
131
+ turn?: number;
132
+ }
133
+ export interface ApprovalAskedPayload {
134
+ requestId: string;
135
+ toolName: string;
136
+ callId?: string;
137
+ reason?: string;
138
+ }
139
+ export interface ApprovalDecidedPayload {
140
+ requestId: string;
141
+ outcome: ApprovalOutcome;
142
+ }
143
+ export interface RunStatusPayload {
144
+ runId: string;
145
+ status: RunStatus;
146
+ reason?: string;
147
+ }
148
+ export interface ArtifactRefPayload {
149
+ artifactId: string;
150
+ name: string;
151
+ size: number;
152
+ type: string;
153
+ retentionMs?: number;
154
+ downloadAuthorized: boolean;
155
+ }
156
+ export interface EventEnvelopeBase {
157
+ schema: 'dshremote.event';
158
+ version: 1;
159
+ connectionId: DshRemoteId;
160
+ sessionId: DshRemoteId;
161
+ runId?: DshRemoteId;
162
+ /** Connector 本地分配,按 session 单调递增(seq = 已上传数)。 */
163
+ seq: number;
164
+ /** Unix epoch ms。 */
165
+ time: number;
166
+ /** 幂等键 = `${connectionId}:${sessionId}:${seq}`。 */
167
+ msgId: string;
168
+ }
169
+ export type DshRemoteEvent = (EventEnvelopeBase & {
170
+ kind: 'sessionMeta';
171
+ payload: SessionMetaPayload;
172
+ }) | (EventEnvelopeBase & {
173
+ kind: 'turnStart';
174
+ payload: TurnStartPayload;
175
+ }) | (EventEnvelopeBase & {
176
+ kind: 'turnEnd';
177
+ payload: TurnEndPayload;
178
+ }) | (EventEnvelopeBase & {
179
+ kind: 'stepStart';
180
+ payload: StepStartPayload;
181
+ }) | (EventEnvelopeBase & {
182
+ kind: 'stepEnd';
183
+ payload: StepEndPayload;
184
+ }) | (EventEnvelopeBase & {
185
+ kind: 'userMessage';
186
+ payload: UserMessagePayload;
187
+ }) | (EventEnvelopeBase & {
188
+ kind: 'assistantMessage';
189
+ payload: AssistantMessagePayload;
190
+ }) | (EventEnvelopeBase & {
191
+ kind: 'toolCall';
192
+ payload: ToolCallPayload;
193
+ }) | (EventEnvelopeBase & {
194
+ kind: 'toolResult';
195
+ payload: ToolResultPayload;
196
+ }) | (EventEnvelopeBase & {
197
+ kind: 'error';
198
+ payload: ErrorEventPayload;
199
+ }) | (EventEnvelopeBase & {
200
+ kind: 'approvalAsked';
201
+ payload: ApprovalAskedPayload;
202
+ }) | (EventEnvelopeBase & {
203
+ kind: 'approvalDecided';
204
+ payload: ApprovalDecidedPayload;
205
+ }) | (EventEnvelopeBase & {
206
+ kind: 'runStatus';
207
+ payload: RunStatusPayload;
208
+ }) | (EventEnvelopeBase & {
209
+ kind: 'artifactRef';
210
+ payload: ArtifactRefPayload;
211
+ });
212
+ export declare const C2C_MESSAGE_TYPES: readonly ["hello", "helloAck", "pairing.consume", "pairing.ack", "credential.rotate", "connection.revoke", "project.sync", "session.event", "session.reconcile", "session.gap", "gap.unrecoverable", "session.settings", "session.settingsResult", "session.command", "session.commandResult", "session.create", "session.createResult", "session.queue", "session.queueUpdate", "task.dispatch", "task.sync", "run.ack", "run.control", "run.status", "approval.request", "approval.answer", "approval.localDecided", "artifact.register", "artifact.fetch", "artifact.content", "ping", "pong"];
213
+ export type C2CMessageType = (typeof C2C_MESSAGE_TYPES)[number];
214
+ export interface C2CMessageBase {
215
+ v: 1;
216
+ /** 幂等键(uuid),两端各自去重。 */
217
+ msgId: string;
218
+ ackId?: string;
219
+ }
220
+ export interface HelloPayload {
221
+ protocolVersion: 1;
222
+ schemaVersion: 1;
223
+ connectionId: DshRemoteId;
224
+ /** 一次性 nonce,签名原文 = connectionId + ':' + nonce。 */
225
+ nonce: string;
226
+ /** 长期凭证(Ed25519 私钥)对 nonce 的签名,base64。 */
227
+ signature: string;
228
+ capabilities: {
229
+ harnessVersion: string;
230
+ pluginVersion: string;
231
+ profile: string;
232
+ providers: string[];
233
+ };
234
+ /** 节点友好名(hostname / 自定义),供云端多节点识别;缺省回退 connectionId 略称。 */
235
+ nodeName?: string;
236
+ }
237
+ export interface HelloAckPayload {
238
+ accepted: boolean;
239
+ protocolVersion: 1;
240
+ schemaVersion: 1;
241
+ reason?: string;
242
+ }
243
+ export interface PairingConsumePayload {
244
+ ticket: string;
245
+ /** 本机生成的 Ed25519 公钥(base64),注册到 Control Plane。 */
246
+ publicKey: string;
247
+ }
248
+ /** P→C:配对消费结果。 */
249
+ export interface PairingAckPayload {
250
+ connectionId: DshRemoteId;
251
+ accepted: boolean;
252
+ reason?: string;
253
+ }
254
+ export interface CredentialRotatePayload {
255
+ requestId: string;
256
+ /** P→C 触发时省略;C→P 应答时携带新公钥。 */
257
+ publicKey?: string;
258
+ }
259
+ export interface ConnectionRevokePayload {
260
+ reason?: string;
261
+ }
262
+ export interface ProjectSummary {
263
+ projectId: DshRemoteId;
264
+ displayName: string;
265
+ repoSummary?: string;
266
+ branchSummary?: string;
267
+ available: boolean;
268
+ lastSyncedAt: number;
269
+ }
270
+ export interface ProjectSyncPayload {
271
+ projects: ProjectSummary[];
272
+ /** 本机移除/不可用的 projectId。 */
273
+ removed: DshRemoteId[];
274
+ }
275
+ export interface SessionEventPayload {
276
+ event: DshRemoteEvent;
277
+ }
278
+ export interface SessionReconcileEntry {
279
+ sessionId: DshRemoteId;
280
+ /** 已同步的最大 seq;-1 表示尚未同步。 */
281
+ lastSyncedSeq: number;
282
+ status: 'active' | 'ended' | 'unknown';
283
+ }
284
+ export interface SessionReconcilePayload {
285
+ sessions: SessionReconcileEntry[];
286
+ /** 当前 connector 进程拥有的云端会话 id(createRemoteSession 创建的 agent 句柄)。
287
+ * 供云端判定会话是否可写:非 owned 的会话设置控件在 UI 上应禁用。 */
288
+ ownedSessionIds?: string[];
289
+ }
290
+ /** P→C:云端发现缺口后请求补拉(fromSeq 不含、toSeq 含)。 */
291
+ export interface SessionGapPayload {
292
+ sessionId: DshRemoteId;
293
+ fromSeq: number;
294
+ toSeq: number;
295
+ }
296
+ /**
297
+ * C→P:缺口不可完整补拉(FR-005.9 v1.1)。
298
+ * Connector 配置了重放上限(cap>0)且请求区间早于保留窗口时回发——
299
+ * 避免云端静默拿到部分数据造成永久缺口。云端收到后应记录并告警
300
+ * (不无限重试同一区间)。
301
+ */
302
+ export interface GapUnrecoverablePayload {
303
+ sessionId: DshRemoteId;
304
+ /** 云端请求的 fromSeq(不含)。 */
305
+ fromSeq: number;
306
+ /** Connector 本地保留的最早 seq(含);缺失部分为 [fromSeq+1, oldestSeq-1]。 */
307
+ oldestSeq: number;
308
+ /** 云端请求的 toSeq(含),用于记录区间。 */
309
+ toSeq: number;
310
+ }
311
+ export interface TaskDispatchPayload {
312
+ deliveryId: string;
313
+ /** Control Plane 派发时即创建的 Run 记录 id(run.ack 回填)。 */
314
+ runId: DshRemoteId;
315
+ taskId: string;
316
+ projectId: DshRemoteId;
317
+ prompt: string;
318
+ /** 允许范围内的策略覆盖(FR-006.5)。 */
319
+ policyOverrides?: Record<string, JsonValue>;
320
+ offlinePolicy: 'skip' | 'deliver_later' | 'queue';
321
+ /** 重试时递增;同一 deliveryId 的首次尝试为 1。 */
322
+ attempt: number;
323
+ }
324
+ /**
325
+ * 本地 Harness 任务投影(FR-006.10):Connector 把授权范围内本地创建的
326
+ * 临时/定时任务(Harness schedule 事件折叠)同步到云端,仅作只读展示,
327
+ * 不参与云端调度(FR-006.4:云端定时器是权威,本地 schedule 不自动等同)。
328
+ */
329
+ export interface LocalTaskSummary {
330
+ /** 本地稳定标识(Harness ScheduleId)。 */
331
+ localTaskId: string;
332
+ /** 所属本地 Session。 */
333
+ sessionId: DshRemoteId;
334
+ name: string;
335
+ prompt: string;
336
+ /** 一次性(after/at)或重复(every)。 */
337
+ kind: 'after' | 'at' | 'every';
338
+ /** RFC3339 或 afterSeconds 摘要,仅展示。 */
339
+ scheduleSummary?: string;
340
+ /** 最近一次活动(创建/派发)时刻。 */
341
+ updatedAt: number;
342
+ }
343
+ export interface TaskSyncPayload {
344
+ /** 授权范围内全部本地任务(全量快照,替换式)。 */
345
+ tasks: LocalTaskSummary[];
346
+ }
347
+ export interface RunAckPayload {
348
+ deliveryId: string;
349
+ accepted: boolean;
350
+ reason?: string;
351
+ runId?: DshRemoteId;
352
+ sessionId?: DshRemoteId;
353
+ }
354
+ export interface RunControlPayload {
355
+ runId: DshRemoteId;
356
+ sessionId?: DshRemoteId;
357
+ action: 'stop' | 'resume' | 'retry';
358
+ /** resume/retry 时的下一条用户消息。 */
359
+ message?: string;
360
+ }
361
+ /** P→C:云端修改会话设置(FR-005.x)。model/reasoningEffort 随时可改;preset 仅空白会话可改。 */
362
+ export interface SessionSettingsPayload {
363
+ sessionId: DshRemoteId;
364
+ provider?: string;
365
+ model?: string;
366
+ reasoningEffort?: string;
367
+ /** 仅当会话尚未产生首条消息(turn/start 未提交)时可设置;否则 Harness 抛 agent-preset-locked。 */
368
+ preset?: string;
369
+ }
370
+ /** C→P:会话设置应用结果。 */
371
+ export interface SessionSettingsResultPayload {
372
+ sessionId: DshRemoteId;
373
+ ok: boolean;
374
+ reason?: string;
375
+ }
376
+ /** P→C:会话命令(goal/plan)。由 Harness 插件(dsh-goal / dsh-plan-mode)真实执行。 */
377
+ export interface SessionCommandPayload {
378
+ sessionId: DshRemoteId;
379
+ command: 'plan' | 'goal';
380
+ /** plan:目标状态(缺省则切换当前);goal:目标文本(objective 必填)。 */
381
+ active?: boolean;
382
+ objective?: string;
383
+ }
384
+ /** C→P:会话命令执行结果。 */
385
+ export interface SessionCommandResultPayload {
386
+ sessionId: DshRemoteId;
387
+ command: 'plan' | 'goal';
388
+ ok: boolean;
389
+ reason?: string;
390
+ /** 结果摘要(流程:plan 目标状态 / goal 目标摘要)。 */
391
+ detail?: string;
392
+ }
393
+ /** P→C:同步创建远程会话(connector 建好 agent 会话并返回 sessionId,供 UI 直接进入)。 */
394
+ export interface SessionCreatePayload {
395
+ projectId: DshRemoteId;
396
+ prompt: string;
397
+ /** 创建时指定模型(可缺省,connector 用默认 deepseek-v4-flash)。 */
398
+ model?: string;
399
+ /** 创建时指定思考强度(reasoningEffort,如 off/low/high/max)。 */
400
+ effort?: string;
401
+ }
402
+ /** C→P:同步创建会话结果。 */
403
+ export interface SessionCreateResultPayload {
404
+ ok: boolean;
405
+ sessionId?: DshRemoteId;
406
+ reason?: string;
407
+ }
408
+ /** C→P:审批已在本地(dsh)决定——通知云端撤销该 pending 审批,云端弹窗随之关闭。 */
409
+ export interface ApprovalLocalDecidedPayload {
410
+ requestId: string;
411
+ outcome: ApprovalOutcome;
412
+ }
413
+ /** C→P:会话排队消息快照(来自 harness agent.inbox.nextTurn,云端镜像显示,刷新不丢)。 */
414
+ export interface SessionQueuePayload {
415
+ sessionId: DshRemoteId;
416
+ items: Array<{
417
+ id: string;
418
+ text: string;
419
+ }>;
420
+ }
421
+ /** P→C:对会话排队消息的操作(编辑/删除/插队),落 harness agent.inbox。 */
422
+ export interface SessionQueueUpdatePayload {
423
+ sessionId: DshRemoteId;
424
+ itemId?: string;
425
+ action: 'edit' | 'remove' | 'insert';
426
+ /** edit 或 insert 的文本内容。 */
427
+ text?: string;
428
+ }
429
+ export interface ApprovalRequestPayload {
430
+ requestId: string;
431
+ agentId?: string;
432
+ sessionId?: DshRemoteId;
433
+ runId?: DshRemoteId;
434
+ toolName: string;
435
+ callId?: string;
436
+ reason?: string;
437
+ /** 审批有效期(epoch ms),过期按 rejected 处理。 */
438
+ expiresAt: number;
439
+ }
440
+ export interface ApprovalAnswerPayload {
441
+ requestId: string;
442
+ outcome: ApprovalOutcome;
443
+ }
444
+ export interface ArtifactRegisterPayload {
445
+ artifactId: string;
446
+ runId: DshRemoteId;
447
+ name: string;
448
+ size: number;
449
+ type: string;
450
+ retentionMs?: number;
451
+ }
452
+ /** FR-009.6:云端发起制品受控下载(CP → Connector)。 */
453
+ export interface ArtifactFetchPayload {
454
+ requestId: string;
455
+ artifactId: string;
456
+ runId: DshRemoteId;
457
+ /** 单次下载最大字节(Connector 超限拒绝);缺省用协议默认值。 */
458
+ maxBytes?: number;
459
+ }
460
+ /** FR-009.6:Connector 回传制品内容(base64,小文件/文本结果)。 */
461
+ export interface ArtifactContentPayload {
462
+ requestId: string;
463
+ ok: boolean;
464
+ error?: string;
465
+ name?: string;
466
+ type?: string;
467
+ size?: number;
468
+ /** base64 编码的制品内容。 */
469
+ contentBase64?: string;
470
+ }
471
+ export interface PingPayload {
472
+ t: number;
473
+ }
474
+ export type C2CMessage = (C2CMessageBase & {
475
+ type: 'hello';
476
+ payload: HelloPayload;
477
+ }) | (C2CMessageBase & {
478
+ type: 'helloAck';
479
+ payload: HelloAckPayload;
480
+ }) | (C2CMessageBase & {
481
+ type: 'pairing.consume';
482
+ payload: PairingConsumePayload;
483
+ }) | (C2CMessageBase & {
484
+ type: 'pairing.ack';
485
+ payload: PairingAckPayload;
486
+ }) | (C2CMessageBase & {
487
+ type: 'credential.rotate';
488
+ payload: CredentialRotatePayload;
489
+ }) | (C2CMessageBase & {
490
+ type: 'connection.revoke';
491
+ payload: ConnectionRevokePayload;
492
+ }) | (C2CMessageBase & {
493
+ type: 'project.sync';
494
+ payload: ProjectSyncPayload;
495
+ }) | (C2CMessageBase & {
496
+ type: 'session.event';
497
+ payload: SessionEventPayload;
498
+ }) | (C2CMessageBase & {
499
+ type: 'session.reconcile';
500
+ payload: SessionReconcilePayload;
501
+ }) | (C2CMessageBase & {
502
+ type: 'session.gap';
503
+ payload: SessionGapPayload;
504
+ }) | (C2CMessageBase & {
505
+ type: 'gap.unrecoverable';
506
+ payload: GapUnrecoverablePayload;
507
+ }) | (C2CMessageBase & {
508
+ type: 'session.settings';
509
+ payload: SessionSettingsPayload;
510
+ }) | (C2CMessageBase & {
511
+ type: 'session.settingsResult';
512
+ payload: SessionSettingsResultPayload;
513
+ }) | (C2CMessageBase & {
514
+ type: 'session.command';
515
+ payload: SessionCommandPayload;
516
+ }) | (C2CMessageBase & {
517
+ type: 'session.commandResult';
518
+ payload: SessionCommandResultPayload;
519
+ }) | (C2CMessageBase & {
520
+ type: 'session.create';
521
+ payload: SessionCreatePayload;
522
+ }) | (C2CMessageBase & {
523
+ type: 'session.createResult';
524
+ payload: SessionCreateResultPayload;
525
+ }) | (C2CMessageBase & {
526
+ type: 'session.queue';
527
+ payload: SessionQueuePayload;
528
+ }) | (C2CMessageBase & {
529
+ type: 'session.queueUpdate';
530
+ payload: SessionQueueUpdatePayload;
531
+ }) | (C2CMessageBase & {
532
+ type: 'task.dispatch';
533
+ payload: TaskDispatchPayload;
534
+ }) | (C2CMessageBase & {
535
+ type: 'task.sync';
536
+ payload: TaskSyncPayload;
537
+ }) | (C2CMessageBase & {
538
+ type: 'run.ack';
539
+ payload: RunAckPayload;
540
+ }) | (C2CMessageBase & {
541
+ type: 'run.control';
542
+ payload: RunControlPayload;
543
+ }) | (C2CMessageBase & {
544
+ type: 'run.status';
545
+ payload: RunStatusPayload;
546
+ }) | (C2CMessageBase & {
547
+ type: 'approval.request';
548
+ payload: ApprovalRequestPayload;
549
+ }) | (C2CMessageBase & {
550
+ type: 'approval.answer';
551
+ payload: ApprovalAnswerPayload;
552
+ }) | (C2CMessageBase & {
553
+ type: 'approval.localDecided';
554
+ payload: ApprovalLocalDecidedPayload;
555
+ }) | (C2CMessageBase & {
556
+ type: 'artifact.register';
557
+ payload: ArtifactRegisterPayload;
558
+ }) | (C2CMessageBase & {
559
+ type: 'artifact.fetch';
560
+ payload: ArtifactFetchPayload;
561
+ }) | (C2CMessageBase & {
562
+ type: 'artifact.content';
563
+ payload: ArtifactContentPayload;
564
+ }) | (C2CMessageBase & {
565
+ type: 'ping';
566
+ payload: PingPayload;
567
+ }) | (C2CMessageBase & {
568
+ type: 'pong';
569
+ payload: PingPayload;
570
+ });
571
+ /** 生成 msgId 幂等键:`${connectionId}:${sessionId}:${seq}`(事件)或 uuid(控制消息)。 */
572
+ export declare function eventMsgId(connectionId: DshRemoteId, sessionId: DshRemoteId, seq: number): string;
package/lib/types.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @dshremote/protocol —— DshRemote 共享协议类型。
3
+ *
4
+ * 单一事实来源:`schemas/dshremote-event-v1.schema.json`(事件契约 v1)
5
+ * 与 `schemas/dshremote-protocol-v1.schema.json`(Connector↔Control Plane 通信协议)。
6
+ * 本文件是这些 Schema 的 TS 投影;改动必须三处同步(types.ts / 两个 schema / 设计文档 §3、§4)。
7
+ *
8
+ * 对应《DshRemote 技术方案 v0.1》§3(事件契约)与 §4(通信协议)。
9
+ */
10
+ // ---------------------------------------------------------------------------
11
+ // 事件契约 v1(技术方案 §3)
12
+ // ---------------------------------------------------------------------------
13
+ export const EVENT_KINDS = [
14
+ 'sessionMeta',
15
+ 'turnStart',
16
+ 'turnEnd',
17
+ 'stepStart',
18
+ 'stepEnd',
19
+ 'userMessage',
20
+ 'assistantMessage',
21
+ 'toolCall',
22
+ 'toolResult',
23
+ 'error',
24
+ 'approvalAsked',
25
+ 'approvalDecided',
26
+ 'runStatus',
27
+ 'artifactRef',
28
+ ];
29
+ // ---------------------------------------------------------------------------
30
+ // 通信协议 v1(技术方案 §4)
31
+ // ---------------------------------------------------------------------------
32
+ export const C2C_MESSAGE_TYPES = [
33
+ // 握手与版本协商
34
+ 'hello',
35
+ 'helloAck',
36
+ // 配对与凭证
37
+ 'pairing.consume',
38
+ 'pairing.ack',
39
+ 'credential.rotate',
40
+ 'connection.revoke',
41
+ // 项目
42
+ 'project.sync',
43
+ // Session 事件与对账
44
+ 'session.event',
45
+ 'session.reconcile',
46
+ 'session.gap',
47
+ 'gap.unrecoverable',
48
+ // 会话设置
49
+ 'session.settings',
50
+ 'session.settingsResult',
51
+ // 会话命令(goal/plan)
52
+ 'session.command',
53
+ 'session.commandResult',
54
+ // 同步创建远程会话
55
+ 'session.create',
56
+ 'session.createResult',
57
+ // 会话排队消息(镜像 harness agent.inbox)
58
+ 'session.queue',
59
+ 'session.queueUpdate',
60
+ // 任务与 Run
61
+ 'task.dispatch',
62
+ 'task.sync',
63
+ 'run.ack',
64
+ 'run.control',
65
+ 'run.status',
66
+ // 审批
67
+ 'approval.request',
68
+ 'approval.answer',
69
+ 'approval.localDecided',
70
+ // 制品
71
+ 'artifact.register',
72
+ 'artifact.fetch',
73
+ 'artifact.content',
74
+ // 心跳
75
+ 'ping',
76
+ 'pong',
77
+ ];
78
+ /** 生成 msgId 幂等键:`${connectionId}:${sessionId}:${seq}`(事件)或 uuid(控制消息)。 */
79
+ export function eventMsgId(connectionId, sessionId, seq) {
80
+ return `${connectionId}:${sessionId}:${seq}`;
81
+ }