@agent-phonon/protocol 0.9.1 → 0.10.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.
Files changed (145) hide show
  1. package/README.md +35 -1
  2. package/dist/index.d.ts +12 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +12 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/native-version.d.ts +6 -0
  7. package/dist/native-version.d.ts.map +1 -0
  8. package/dist/native-version.js +41 -0
  9. package/dist/native-version.js.map +1 -0
  10. package/dist/schemas/capabilities.d.ts +9 -0
  11. package/dist/schemas/capabilities.d.ts.map +1 -1
  12. package/dist/schemas/capabilities.js +3 -0
  13. package/dist/schemas/capabilities.js.map +1 -1
  14. package/dist/schemas/common.d.ts +4 -4
  15. package/dist/schemas/common.d.ts.map +1 -1
  16. package/dist/schemas/common.js +9 -0
  17. package/dist/schemas/common.js.map +1 -1
  18. package/dist/schemas/compression.d.ts +191 -0
  19. package/dist/schemas/compression.d.ts.map +1 -0
  20. package/dist/schemas/compression.js +18 -0
  21. package/dist/schemas/compression.js.map +1 -0
  22. package/dist/schemas/conversation-archive.d.ts +1021 -0
  23. package/dist/schemas/conversation-archive.d.ts.map +1 -0
  24. package/dist/schemas/conversation-archive.js +148 -0
  25. package/dist/schemas/conversation-archive.js.map +1 -0
  26. package/dist/schemas/conversation-board.d.ts +428 -0
  27. package/dist/schemas/conversation-board.d.ts.map +1 -0
  28. package/dist/schemas/conversation-board.js +32 -0
  29. package/dist/schemas/conversation-board.js.map +1 -0
  30. package/dist/schemas/conversation-message.d.ts +658 -0
  31. package/dist/schemas/conversation-message.d.ts.map +1 -0
  32. package/dist/schemas/conversation-message.js +42 -0
  33. package/dist/schemas/conversation-message.js.map +1 -0
  34. package/dist/schemas/conversation-workflow.d.ts +1201 -0
  35. package/dist/schemas/conversation-workflow.d.ts.map +1 -0
  36. package/dist/schemas/conversation-workflow.js +68 -0
  37. package/dist/schemas/conversation-workflow.js.map +1 -0
  38. package/dist/schemas/device.d.ts +198 -2
  39. package/dist/schemas/device.d.ts.map +1 -1
  40. package/dist/schemas/device.js +29 -1
  41. package/dist/schemas/device.js.map +1 -1
  42. package/dist/schemas/discovery.d.ts +107 -0
  43. package/dist/schemas/discovery.d.ts.map +1 -1
  44. package/dist/schemas/discovery.js +2 -0
  45. package/dist/schemas/discovery.js.map +1 -1
  46. package/dist/schemas/document.d.ts +56 -26
  47. package/dist/schemas/document.d.ts.map +1 -1
  48. package/dist/schemas/document.js +11 -0
  49. package/dist/schemas/document.js.map +1 -1
  50. package/dist/schemas/employee.d.ts +139 -0
  51. package/dist/schemas/employee.d.ts.map +1 -0
  52. package/dist/schemas/employee.js +17 -0
  53. package/dist/schemas/employee.js.map +1 -0
  54. package/dist/schemas/env.d.ts +15 -15
  55. package/dist/schemas/env.d.ts.map +1 -1
  56. package/dist/schemas/env.js +1 -1
  57. package/dist/schemas/env.js.map +1 -1
  58. package/dist/schemas/file.d.ts +6 -6
  59. package/dist/schemas/hook.d.ts +4 -4
  60. package/dist/schemas/interaction.d.ts +363 -2
  61. package/dist/schemas/interaction.d.ts.map +1 -1
  62. package/dist/schemas/interaction.js +28 -1
  63. package/dist/schemas/interaction.js.map +1 -1
  64. package/dist/schemas/jsonrpc.d.ts +19 -19
  65. package/dist/schemas/maintenance.d.ts +822 -0
  66. package/dist/schemas/maintenance.d.ts.map +1 -0
  67. package/dist/schemas/maintenance.js +166 -0
  68. package/dist/schemas/maintenance.js.map +1 -0
  69. package/dist/schemas/managed-mcp.d.ts +116 -0
  70. package/dist/schemas/managed-mcp.d.ts.map +1 -0
  71. package/dist/schemas/managed-mcp.js +23 -0
  72. package/dist/schemas/managed-mcp.js.map +1 -0
  73. package/dist/schemas/methods.d.ts +22186 -2362
  74. package/dist/schemas/methods.d.ts.map +1 -1
  75. package/dist/schemas/methods.js +181 -6
  76. package/dist/schemas/methods.js.map +1 -1
  77. package/dist/schemas/native-stop.d.ts +162 -0
  78. package/dist/schemas/native-stop.d.ts.map +1 -0
  79. package/dist/schemas/native-stop.js +14 -0
  80. package/dist/schemas/native-stop.js.map +1 -0
  81. package/dist/schemas/policy.d.ts +42 -2
  82. package/dist/schemas/policy.d.ts.map +1 -1
  83. package/dist/schemas/policy.js +20 -0
  84. package/dist/schemas/policy.js.map +1 -1
  85. package/dist/schemas/project-coordination.d.ts +1956 -0
  86. package/dist/schemas/project-coordination.d.ts.map +1 -0
  87. package/dist/schemas/project-coordination.js +81 -0
  88. package/dist/schemas/project-coordination.js.map +1 -0
  89. package/dist/schemas/project.d.ts +771 -53
  90. package/dist/schemas/project.d.ts.map +1 -1
  91. package/dist/schemas/project.js +60 -5
  92. package/dist/schemas/project.js.map +1 -1
  93. package/dist/schemas/reasoning.d.ts +26 -0
  94. package/dist/schemas/reasoning.d.ts.map +1 -0
  95. package/dist/schemas/reasoning.js +10 -0
  96. package/dist/schemas/reasoning.js.map +1 -0
  97. package/dist/schemas/schedule.d.ts +15148 -5022
  98. package/dist/schemas/schedule.d.ts.map +1 -1
  99. package/dist/schemas/schedule.js +46 -5
  100. package/dist/schemas/schedule.js.map +1 -1
  101. package/dist/schemas/session.d.ts +1558 -49
  102. package/dist/schemas/session.d.ts.map +1 -1
  103. package/dist/schemas/session.js +27 -16
  104. package/dist/schemas/session.js.map +1 -1
  105. package/dist/schemas/skill.d.ts +1009 -8
  106. package/dist/schemas/skill.d.ts.map +1 -1
  107. package/dist/schemas/skill.js +39 -0
  108. package/dist/schemas/skill.js.map +1 -1
  109. package/dist/schemas/stream.d.ts +1060 -67
  110. package/dist/schemas/stream.d.ts.map +1 -1
  111. package/dist/schemas/stream.js +18 -3
  112. package/dist/schemas/stream.js.map +1 -1
  113. package/dist/schemas/workflow.d.ts +2764 -255
  114. package/dist/schemas/workflow.d.ts.map +1 -1
  115. package/dist/schemas/workflow.js +69 -1
  116. package/dist/schemas/workflow.js.map +1 -1
  117. package/package.json +1 -1
  118. package/src/index.ts +12 -0
  119. package/src/native-version.ts +30 -0
  120. package/src/schemas/capabilities.ts +3 -0
  121. package/src/schemas/common.ts +9 -0
  122. package/src/schemas/compression.ts +19 -0
  123. package/src/schemas/conversation-archive.ts +155 -0
  124. package/src/schemas/conversation-board.ts +36 -0
  125. package/src/schemas/conversation-message.ts +46 -0
  126. package/src/schemas/conversation-workflow.ts +62 -0
  127. package/src/schemas/device.ts +32 -1
  128. package/src/schemas/discovery.ts +2 -0
  129. package/src/schemas/document.ts +13 -0
  130. package/src/schemas/employee.ts +19 -0
  131. package/src/schemas/env.ts +1 -1
  132. package/src/schemas/interaction.ts +32 -1
  133. package/src/schemas/maintenance.ts +204 -0
  134. package/src/schemas/managed-mcp.ts +25 -0
  135. package/src/schemas/methods.ts +208 -1
  136. package/src/schemas/native-stop.ts +16 -0
  137. package/src/schemas/policy.ts +20 -0
  138. package/src/schemas/project-coordination.ts +90 -0
  139. package/src/schemas/project.ts +72 -5
  140. package/src/schemas/reasoning.ts +13 -0
  141. package/src/schemas/schedule.ts +54 -5
  142. package/src/schemas/session.ts +30 -18
  143. package/src/schemas/skill.ts +52 -0
  144. package/src/schemas/stream.ts +22 -3
  145. package/src/schemas/workflow.ts +82 -1
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import {SkillSelection} from "./skill.js";
2
3
  import { AgentId, ProjectId, SessionId, TenantId } from "./common.js";
3
4
  import { WorkflowId, WorkflowPlan } from "./workflow.js";
4
5
 
@@ -72,9 +73,17 @@ export type ScheduleTrigger = z.infer<typeof ScheduleTrigger>;
72
73
  // Target(到点后要发起的 run 的「配方」)
73
74
  // ---------------------------------------------------------------------------
74
75
 
76
+ export const ScheduleDispatch = z.object({
77
+ key: z.string().min(1).max(255),
78
+ revision: z.number().int().positive(),
79
+ contentHash: z.string().regex(/^[a-f0-9]{64}$/),
80
+ expiresAt: z.string().datetime({ offset: true }).optional(),
81
+ });
82
+ export type ScheduleDispatch = z.infer<typeof ScheduleDispatch>;
83
+
75
84
  export const ScheduleTarget = z.object({
76
85
  /** 复用 L1 session 还是 L3 workflow。 */
77
- runKind: z.enum(["session", "workflow"]).default("session"),
86
+ runKind: z.enum(["session", "workflow", "dispatch"]).default("session"),
78
87
  /** 必须绑定 project(与 session.create 一致)。 */
79
88
  project: ProjectId,
80
89
  /** runKind=session:用哪个 agent。 */
@@ -85,8 +94,11 @@ export const ScheduleTarget = z.object({
85
94
  /** runKind=workflow:L3 plan。 */
86
95
  plan: WorkflowPlan.optional(),
87
96
  agentConfig: z.record(z.unknown()).optional(),
88
- skills: z.array(z.string()).optional(),
89
- });
97
+ skills: z.array(SkillSelection).max(16).optional(),
98
+ /** A durable handoff to an authorizing controller; never launches a model. */
99
+ dispatch: ScheduleDispatch.optional(),
100
+ }).refine(value => value.runKind === "dispatch" ? !!value.dispatch && !value.agent && !value.plan && !value.agentConfig : !value.dispatch,
101
+ { message: "dispatch targets require a dispatch identity and cannot contain executable agent configuration" });
90
102
  export type ScheduleTarget = z.infer<typeof ScheduleTarget>;
91
103
 
92
104
  // ---------------------------------------------------------------------------
@@ -161,12 +173,26 @@ export type RunStatus = z.infer<typeof RunStatus>;
161
173
  export const RunTriggerSource = z.enum(["cron", "webhook", "manual"]);
162
174
  export type RunTriggerSource = z.infer<typeof RunTriggerSource>;
163
175
 
176
+ export const RunRetryAttempt = z.object({
177
+ /** 失败的是第几次尝试(从 1 开始)。 */
178
+ attempt: z.number().int().positive(),
179
+ at: z.string(),
180
+ phase: z.enum(["launch", "runtime"]),
181
+ error: z.string(),
182
+ });
183
+ export type RunRetryAttempt = z.infer<typeof RunRetryAttempt>;
184
+
164
185
  export const Run = z.object({
165
186
  id: RunId,
166
187
  scheduleId: ScheduleId,
167
188
  tenantId: TenantId,
168
189
  triggerSource: RunTriggerSource,
169
190
  status: RunStatus,
191
+ /** Non-sensitive execution-kind marker, retained even in status-only pushes. */
192
+ controllerDispatch: z.literal(true).optional(),
193
+ dispatch: ScheduleDispatch.optional(),
194
+ /** Frozen trigger data for controller dispatch; never an instruction/approval. */
195
+ input: z.union([z.string(), z.record(z.unknown())]).optional(),
170
196
  /** runKind=session:对应的 L1 session。 */
171
197
  sessionId: SessionId.optional(),
172
198
  /** runKind=workflow:对应的 L3 workflow。 */
@@ -180,6 +206,11 @@ export const Run = z.object({
180
206
  /** 终态产物文本(summary 推送用)。 */
181
207
  resultText: z.string().optional(),
182
208
  usage: z.record(z.unknown()).optional(),
209
+ /** 当前/最终尝试序号;总尝试次数上限恒为 1 + policy.maxRetries。 */
210
+ attempt: z.number().int().nonnegative().optional(),
211
+ maxAttempts: z.number().int().positive().optional(),
212
+ /** 每次触发重试的失败审计。 */
213
+ retryHistory: z.array(RunRetryAttempt).optional(),
183
214
  });
184
215
  export type Run = z.infer<typeof Run>;
185
216
 
@@ -275,8 +306,12 @@ export const ScheduleTriggerParams = z.object({
275
306
  scheduleId: ScheduleId,
276
307
  /** 触发来源标记(manual / 测试 cron / 重放 webhook)。默认 manual。 */
277
308
  source: RunTriggerSource.optional(),
278
- /** 可选:注入到 target.prompt 的输入变量(webhook body 等)。 */
279
- input: z.record(z.unknown()).optional(),
309
+ /**
310
+ * 可选触发输入。字符串直接注入;对象 JSON 序列化后注入。
311
+ * session 追加到 target.prompt,workflow 传给 workflow.run.input。
312
+ * record 形态保留,兼容既有 webhook/manual API。
313
+ */
314
+ input: z.union([z.string(), z.record(z.unknown())]).optional(),
280
315
  clientRequestId: z.string().optional(),
281
316
  });
282
317
  export type ScheduleTriggerParams = z.infer<typeof ScheduleTriggerParams>;
@@ -293,6 +328,8 @@ export const ScheduleRunsListParams = z.object({
293
328
  scheduleId: ScheduleId,
294
329
  status: RunStatus.optional(),
295
330
  limit: z.number().int().positive().optional(),
331
+ /** Drain oldest unacknowledged occurrences without losing an offline backlog. */
332
+ unackedOnly: z.boolean().optional(),
296
333
  });
297
334
  export type ScheduleRunsListParams = z.infer<typeof ScheduleRunsListParams>;
298
335
 
@@ -310,6 +347,18 @@ export type RunGetParams = z.infer<typeof RunGetParams>;
310
347
  export const RunGetResult = z.object({ run: Run });
311
348
  export type RunGetResult = z.infer<typeof RunGetResult>;
312
349
 
350
+ export const RunResolveParams = z.object({
351
+ runId: RunId,
352
+ dispatch: ScheduleDispatch,
353
+ status: z.enum(["success", "failed", "cancelled", "skipped", "timeout"]),
354
+ resultText: z.string().max(65536).optional(),
355
+ error: z.string().max(4000).optional(),
356
+ clientRequestId: z.string().optional(),
357
+ });
358
+ export type RunResolveParams = z.infer<typeof RunResolveParams>;
359
+ export const RunResolveResult = z.object({ run: Run });
360
+ export type RunResolveResult = z.infer<typeof RunResolveResult>;
361
+
313
362
  // ---- run.events.subscribe / unsubscribe ----
314
363
  export const RunEventsSubscribeParams = z.object({
315
364
  runId: RunId,
@@ -1,5 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import { AgentId, ProjectId, SessionId, Timestamp, Verbosity } from "./common.js";
3
+ import { SessionCompressionControls, CompressionReceipt } from "./compression.js";
4
+ import { TurnReasoning } from "./reasoning.js";
5
+ import { NativeStopTarget } from "./native-stop.js";
6
+ import { SkillSelection } from "./skill.js";
3
7
 
4
8
  /**
5
9
  * L1 Session 协议原语(design §4)。
@@ -82,6 +86,7 @@ export type WhenBusy = z.infer<typeof WhenBusy>;
82
86
 
83
87
  export const SessionSendParams = z.object({
84
88
  sessionId: SessionId,
89
+ reasoning: TurnReasoning.optional(),
85
90
  /** 用户输入 / 任务内容。 */
86
91
  input: z.string(),
87
92
  /**
@@ -95,19 +100,7 @@ export const SessionSendParams = z.object({
95
100
  * phonon 保证:(1) skill 在 agent 能访问到的位置;(2) 上下文注入强制加载指令。
96
101
  * 优先级:send 指定 > project skill > global skill。
97
102
  */
98
- skills: z
99
- .array(
100
- z.union([
101
- z.string(),
102
- z.object({
103
- name: z.string().min(1),
104
- version: z.string().optional(),
105
- scope: z.enum(["global", "project"]).optional(),
106
- force: z.boolean().optional(),
107
- }),
108
- ]),
109
- )
110
- .optional(),
103
+ skills: z.array(SkillSelection).max(16).optional(),
111
104
  /** 可选:覆盖本轮详细度。 */
112
105
  verbosity: Verbosity.optional(),
113
106
  /**
@@ -123,6 +116,7 @@ export const SessionSendParams = z.object({
123
116
  /**
124
117
  * 可选:本轮关联 id。phonon 会把该轮所有 stream.event 标上同一 turnId,
125
118
  * 调用方据此聚合流式输出。缺省由 phonon 生成并在 ack 中返回。
119
+ * whenBusy=inject 不创建新轮;如显式提供 turnId,必须等于当前 turn。
126
120
  */
127
121
  turnId: z.string().optional(),
128
122
  });
@@ -138,7 +132,8 @@ export const SessionSendAck = z.object({
138
132
  * - started :立即开始执行(session 空闲)
139
133
  * - queued :已排队(whenBusy=queue 且正忙)
140
134
  * - interrupted:已中断上一轮并开始本轮(whenBusy=interrupt)
141
- * - injected :将在下一 tool call 边界插入(whenBusy=inject)
135
+ * - injected :已在当前 turn 的工具边界应用输入(whenBusy=inject),turnId 是当前 turn,不创建新轮。
136
+ * 未应用前不回 injected;窗口关闭必须拒绝,不能自动排队。
142
137
  */
143
138
  disposition: z.enum(["started", "queued", "interrupted", "injected"]),
144
139
  /** queued 时的队列位置(从 1 起)。 */
@@ -160,6 +155,7 @@ export const SessionInterruptParams = z.object({
160
155
  export type SessionInterruptParams = z.infer<typeof SessionInterruptParams>;
161
156
 
162
157
  export const SessionInterruptResult = z.object({
158
+ nativeStop:NativeStopTarget.optional(),
163
159
  sessionId: SessionId,
164
160
  /** 被中断的 turn(若当时有在跑的)。 */
165
161
  interruptedTurnId: z.string().optional(),
@@ -191,6 +187,8 @@ export type CompressMode = z.infer<typeof CompressMode>;
191
187
 
192
188
  export const SessionCompressParams = z.object({
193
189
  sessionId: SessionId,
190
+ clientRequestId: z.string().min(1).max(512).optional(),
191
+ background: z.boolean().optional(),
194
192
  /** native = 透传 agent 原生压缩;custom = phonon 自有压缩引擎。 */
195
193
  mode: CompressMode,
196
194
  /**
@@ -203,12 +201,11 @@ export const SessionCompressParams = z.object({
203
201
  });
204
202
  export type SessionCompressParams = z.infer<typeof SessionCompressParams>;
205
203
 
206
- export const SessionCompressResult = z.object({
204
+ // Older devices return only sessionId/mode; receipt-capable devices retain the
205
+ // complete proof through schema parsing, including identity and change counts.
206
+ export const SessionCompressResult = CompressionReceipt.partial().extend({
207
207
  sessionId: SessionId,
208
208
  mode: CompressMode,
209
- /** 压缩前后的 token 估算(若可得)。 */
210
- tokensBefore: z.number().int().nonnegative().optional(),
211
- tokensAfter: z.number().int().nonnegative().optional(),
212
209
  /** 简短摘要/说明。 */
213
210
  summary: z.string().optional(),
214
211
  });
@@ -273,9 +270,18 @@ export type SessionSwitchModelResult = z.infer<typeof SessionSwitchModelResult>;
273
270
  // session.status / session.list —— 始终携带 agent 身份
274
271
  // ---------------------------------------------------------------------------
275
272
  export const SessionMeta = z.object({
273
+ nativeStop:NativeStopTarget.optional(),
274
+ recovery:z.object({detached:z.boolean(),canAttempt:z.boolean(),reason:z.string().optional()}).strict().optional(),
275
+ streamNextSeq:z.number().int().nonnegative().safe().optional(),
276
+ proactive:z.object({supported:z.boolean(),ready:z.boolean(),errorCode:z.string().optional()}).strict().optional(),
277
+ compression: SessionCompressionControls.optional(),
278
+ employeeId:z.string().uuid().optional(),
279
+ employeeRevision:z.number().int().positive().optional(),
276
280
  sessionId: SessionId,
277
281
  /** 绑定的项目(一等身份,D23)。 */
278
282
  project: ProjectId,
283
+ /** Original worktree binding, retained through status/list/recover parsing. */
284
+ worktreeId: z.string().optional(),
279
285
  /** 绑定的 agent 身份,全程携带。 */
280
286
  agent: AgentId,
281
287
  model: z.string(),
@@ -316,6 +322,12 @@ export type SessionStatusParams = z.infer<typeof SessionStatusParams>;
316
322
  export const SessionStatusResult = SessionMeta;
317
323
  export type SessionStatusResult = z.infer<typeof SessionStatusResult>;
318
324
 
325
+ /** Reopen a verified, settled native Session. Never sends input or resumes a workflow. */
326
+ export const SessionRecoverParams = z.object({sessionId:SessionId,project:ProjectId,agent:AgentId,model:z.string().min(1)}).strict();
327
+ export type SessionRecoverParams = z.infer<typeof SessionRecoverParams>;
328
+ export const SessionRecoverResult = SessionMeta;
329
+ export type SessionRecoverResult = z.infer<typeof SessionRecoverResult>;
330
+
319
331
  export const SessionListParams = z.object({
320
332
  /** 可选:按项目过滤。 */
321
333
  project: ProjectId.optional(),
@@ -14,6 +14,14 @@ import { AgentId, ProjectId, Timestamp } from "./common.js";
14
14
  export const SkillScope = z.enum(["global", "project"]);
15
15
  export type SkillScope = z.infer<typeof SkillScope>;
16
16
 
17
+ const skillName = z.string().min(1).max(128).regex(/^[A-Za-z0-9._-]+$/).refine(value => value !== "." && value !== "..");
18
+ export const SkillSelection = z.union([
19
+ skillName,
20
+ z.object({name:skillName,version:z.string().min(1).max(128).refine(value=>!/[\p{Cc}]/u.test(value)).optional(),scope:SkillScope.optional(),force:z.boolean().optional(),
21
+ revision:z.string().regex(/^[a-f0-9]{64}$/).optional(),installationId:z.string().uuid().optional()}).strict(),
22
+ ]);
23
+ export type SkillSelection = z.infer<typeof SkillSelection>;
24
+
17
25
  /** skill 来源:内联内容、本地路径、或远端引用。 */
18
26
  export const SkillSource = z.union([
19
27
  z.object({ kind: z.literal("inline"), files: z.record(z.string()) }), // path → content
@@ -57,12 +65,16 @@ export const SkillDescriptor = z.object({
57
65
  /** 安装落地路径(设备本地)。 */
58
66
  installedPath: z.string().optional(),
59
67
  installedAt: Timestamp.optional(),
68
+ revision:z.string().regex(/^[a-f0-9]{64}$/).optional(),
69
+ publication:z.object({kind:z.literal("immutable"),versionId:z.string().uuid(),treeHash:z.string().regex(/^[a-f0-9]{64}$/)}).strict().optional(),
60
70
  });
61
71
  export type SkillDescriptor = z.infer<typeof SkillDescriptor>;
62
72
 
63
73
  // --- skill.install ---
64
74
  export const SkillInstallParams = z
65
75
  .object({
76
+ /** Exact parsed request identity; changed payloads cannot reuse a confirmed receipt. */
77
+ clientRequestId: z.string().min(1).max(512).optional(),
66
78
  /** 目标 agent。 */
67
79
  agent: AgentId,
68
80
  name: z.string().min(1),
@@ -82,9 +94,47 @@ export const SkillInstallResult = z.object({
82
94
  });
83
95
  export type SkillInstallResult = z.infer<typeof SkillInstallResult>;
84
96
 
97
+ export const SkillPublishParams=z.object({clientRequestId:z.string().min(1).max(512),agent:AgentId,name:skillName,scope:z.literal("project").default("project"),projectId:ProjectId,
98
+ baseRevision:z.string().regex(/^[a-f0-9]{64}$/).nullable(),expectedReceiverID:z.string().uuid().optional(),source:z.union([SkillSource.options[0],SkillSource.options[1]])}).strict();
99
+ export type SkillPublishParams=z.infer<typeof SkillPublishParams>;
100
+ export const SkillUnpublishParams=z.object({clientRequestId:z.string().min(1).max(512),agent:AgentId,name:skillName,scope:z.literal("project").default("project"),projectId:ProjectId,
101
+ baseRevision:z.string().regex(/^[a-f0-9]{64}$/)}).strict();
102
+ export type SkillUnpublishParams=z.infer<typeof SkillUnpublishParams>;
103
+ export const SkillUnpublishResult=z.object({projectId:ProjectId,name:skillName,deactivated:z.literal(true),previousRevision:z.string().regex(/^[a-f0-9]{64}$/)}).strict();
104
+ export type SkillUnpublishResult=z.infer<typeof SkillUnpublishResult>;
105
+
106
+ export const SkillInstallStatusParams = z.object({
107
+ clientRequestId:z.string().min(1).max(512),agent:AgentId,name:z.string().min(1).max(255),scope:SkillScope,projectId:ProjectId.optional(),
108
+ includeReceiverIdentity:z.literal(true).optional(),
109
+ includeRecoveryContext:z.literal(true).optional(),
110
+ }).strict().refine(value=>value.scope==="project"?!!value.projectId:value.projectId===undefined,{message:"Project scope requires projectId; global scope excludes it"});
111
+ export type SkillInstallStatusParams = z.infer<typeof SkillInstallStatusParams>;
112
+ export const SkillInstallRecoveryContext=z.object({revision:z.string().regex(/^[a-f0-9]{64}$/),receiverID:z.string().uuid(),originalReceiverID:z.string().uuid().nullable(),
113
+ fenced:z.boolean(),fenceID:z.string().uuid().optional()}).strict().refine(value=>value.fenced===!!value.fenceID);
114
+ export type SkillInstallRecoveryContext=z.infer<typeof SkillInstallRecoveryContext>;
115
+ const installStatusIdentity={clientRequestId:z.string().min(1).max(512),createdAt:Timestamp,updatedAt:Timestamp,receiverID:z.string().uuid().optional(),recovery:SkillInstallRecoveryContext.optional()};
116
+ export const SkillInstallStatusResult = z.discriminatedUnion("state",[
117
+ z.object({clientRequestId:z.string().min(1).max(512),state:z.literal("not_found"),found:z.literal(false),outcomeKnown:z.literal(false)}).strict(),
118
+ z.object({...installStatusIdentity,state:z.literal("prepared"),found:z.literal(true),outcomeKnown:z.literal(false),dispatchClaimed:z.literal(false)}).strict(),
119
+ z.object({...installStatusIdentity,state:z.literal("dispatched"),found:z.literal(true),outcomeKnown:z.literal(false),dispatchClaimed:z.literal(true)}).strict(),
120
+ z.object({...installStatusIdentity,state:z.literal("unknown"),found:z.literal(true),outcomeKnown:z.literal(false),dispatchClaimed:z.literal(true),reasonCode:z.enum(["write_outcome_unconfirmed","controller_not_observed"])}).strict(),
121
+ z.object({...installStatusIdentity,state:z.literal("failed"),found:z.literal(true),outcomeKnown:z.literal(true),dispatchClaimed:z.literal(false),reasonCode:z.literal("preparation_failed")}).strict(),
122
+ z.object({...installStatusIdentity,state:z.literal("confirmed"),found:z.literal(true),outcomeKnown:z.literal(true),dispatchClaimed:z.literal(true),result:SkillInstallResult}).strict(),
123
+ ]);
124
+ export type SkillInstallStatusResult = z.infer<typeof SkillInstallStatusResult>;
125
+
126
+ export const SkillInstallFenceParams=z.object({clientRequestId:z.string().min(1).max(512),originalRequestId:z.string().min(1).max(512),agent:AgentId,
127
+ name:z.string().min(1).max(255),scope:z.literal("project").default("project"),projectId:ProjectId,expectedReceiverID:z.string().uuid(),baseRecoveryRevision:z.string().regex(/^[a-f0-9]{64}$/)}).strict();
128
+ export type SkillInstallFenceParams=z.infer<typeof SkillInstallFenceParams>;
129
+ export const SkillInstallFenceResult=z.object({clientRequestId:z.string().min(1).max(512),originalRequestId:z.string().min(1).max(512),agent:AgentId,
130
+ name:z.string().min(1).max(255),scope:z.literal("project"),projectId:ProjectId,receiverID:z.string().uuid(),originalReceiverID:z.string().uuid().nullable(),fenceID:z.string().uuid(),
131
+ disposition:z.literal("unconfirmed_metadata_fenced"),outcomeKnown:z.literal(false),targetLocked:z.literal(true),filesDeleted:z.literal(false),originalWritesMayContinue:z.literal(true),recordedAt:Timestamp}).strict();
132
+ export type SkillInstallFenceResult=z.infer<typeof SkillInstallFenceResult>;
133
+
85
134
  // --- skill.uninstall ---
86
135
  export const SkillUninstallParams = z
87
136
  .object({
137
+ clientRequestId: z.string().optional(),
88
138
  agent: AgentId,
89
139
  name: z.string().min(1),
90
140
  scope: SkillScope,
@@ -142,6 +192,8 @@ export const SkillDirectoryDescriptor = z.object({
142
192
  /** skill 目录真实本机路径。 */
143
193
  path: z.string().min(1),
144
194
  exists: z.boolean(),
195
+ active:z.boolean().optional(),
196
+ publication:SkillDescriptor.shape.publication,
145
197
  });
146
198
  export type SkillDirectoryDescriptor = z.infer<typeof SkillDirectoryDescriptor>;
147
199
 
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { SessionId, Timestamp } from "./common.js";
3
+ import { ReasoningConfirmation } from "./reasoning.js";
3
4
 
4
5
  /**
5
6
  * 流式事件(design §4 / §6 / 订阅模型)——phonon → server 异步推送。
@@ -27,6 +28,7 @@ export type StreamOrigin = z.infer<typeof StreamOrigin>;
27
28
 
28
29
  /** 事件种类。 */
29
30
  export const StreamEventType = z.enum([
31
+ "runtime_settings",
30
32
  "message", // 一条完整/增量消息文本
31
33
  "thinking", // 思考过程(trace 档)
32
34
  "tool_call", // agent 发起工具调用
@@ -48,6 +50,10 @@ const StreamEventBase = z.object({
48
50
  origin: StreamOrigin.default("solicited"),
49
51
  /** unsolicited 时的冲泡来源标签,如 "cron" / "scheduled" / "heartbeat"。 */
50
52
  source: z.string().optional(),
53
+ /** Native harness output identity; not a caller-selected conversation or sender. */
54
+ sourceEventId:z.string().min(1).max(255).optional(),
55
+ nativeProactive:z.object({anchorRunId:z.string().uuid(),employeeId:z.string().uuid(),employeeRevision:z.number().int().positive(),
56
+ upstreamId:z.string().min(1).max(255),project:z.string().min(1).max(512),agent:z.string().min(1).max(255),model:z.string().min(1).max(255)}).strict().optional(),
51
57
  /** 单调递增序号(按 session),保证调用方可排序/去重。 */
52
58
  seq: z.number().int().nonnegative(),
53
59
  at: Timestamp,
@@ -60,6 +66,8 @@ const StreamEventBase = z.object({
60
66
  workflowId: z.string().optional(),
61
67
  nodeId: z.string().optional(),
62
68
  role: z.string().optional(),
69
+ /** Server-generated native conversation run correlation, stamped by core. */
70
+ nativeRunId: z.string().uuid().optional(),
63
71
  });
64
72
 
65
73
  export const StreamMessageEvent = StreamEventBase.extend({
@@ -99,6 +107,11 @@ export const StreamTokenEvent = StreamEventBase.extend({
99
107
  text: z.string(),
100
108
  });
101
109
 
110
+ export const StreamRuntimeSettingsEvent = StreamEventBase.extend({
111
+ type: z.literal("runtime_settings"),
112
+ agent: z.string(), model: z.string(), reasoning: ReasoningConfirmation,
113
+ });
114
+
102
115
  export const StreamResultEvent = StreamEventBase.extend({
103
116
  type: z.literal("result"),
104
117
  /** 本轮最终文本结果。 */
@@ -135,18 +148,24 @@ export const StreamErrorEvent = StreamEventBase.extend({
135
148
 
136
149
  // ---------------------------------------------------------------------------
137
150
  // stream.ack —— server → phonon,确认已收到 seq <= lastSeq(P0-4)
138
- // 让 phonon 能清理 outbox / 控制背压;可按 session 粒度或全局。
151
+ // 让 phonon 能清理 outbox / 控制背压。seq 是 per-session,ACK 必须带 sessionId。
139
152
  // ---------------------------------------------------------------------------
140
153
  export const StreamAckParams = z.object({
141
- /** 按 session 确认;缺省表示该连接全局。 */
142
- sessionId: SessionId.optional(),
154
+ /** 必须按 session 确认;单一标量无法安全表达连接全局水位。 */
155
+ sessionId: SessionId,
143
156
  /** 已收到的最大连续 seq(含);phonon 可清理 <= 此值的 outbox。 */
144
157
  lastSeq: z.number().int().nonnegative(),
145
158
  });
146
159
  export type StreamAckParams = z.infer<typeof StreamAckParams>;
147
160
 
161
+ export const StreamReplayParams = z.object({ sessionId: SessionId, fromSeq: z.number().int().nonnegative().default(0), limit: z.number().int().min(1).max(1000).default(200) });
162
+ export type StreamReplayParams = z.infer<typeof StreamReplayParams>;
163
+ export const StreamReplayResult = z.object({ sessionId: SessionId, replayed: z.number().int().nonnegative(), nextSeq: z.number().int().nonnegative().optional() });
164
+ export type StreamReplayResult = z.infer<typeof StreamReplayResult>;
165
+
148
166
  /** 流式事件联合体(phonon → server,方法名 stream.event)。 */
149
167
  export const StreamEvent = z.discriminatedUnion("type", [
168
+ StreamRuntimeSettingsEvent,
150
169
  StreamMessageEvent,
151
170
  StreamThinkingEvent,
152
171
  StreamToolCallEvent,
@@ -1,5 +1,8 @@
1
1
  import { z } from "zod";
2
+ import { NativeStopProof } from "./native-stop.js";
2
3
  import { AgentId, ProjectId, SessionId, Timestamp } from "./common.js";
4
+ import { TurnReasoning } from "./reasoning.js";
5
+ import { SkillSelection } from "./skill.js";
3
6
 
4
7
  /**
5
8
  * L3 Orchestration Protocol (workflow.*)
@@ -37,6 +40,8 @@ export const WorkflowNode = z.object({
37
40
  nodeId: WorkflowNodeId,
38
41
  agent: AgentId,
39
42
  model: ModelId,
43
+ reasoning: TurnReasoning.optional(),
44
+ skills: z.array(SkillSelection).max(16).optional(),
40
45
  /** 该节点在 workflow 中扮演的角色(由调用方定义,phonon 仅回显)。 */
41
46
  role: WorkflowRoleId.optional(),
42
47
  input: z.string().optional(),
@@ -154,6 +159,7 @@ export type WorkflowPlan = z.infer<typeof WorkflowPlan>;
154
159
  export const WorkflowStatus = z.enum([
155
160
  "queued",
156
161
  "running",
162
+ "paused",
157
163
  "completed",
158
164
  "failed",
159
165
  "cancelled",
@@ -165,6 +171,7 @@ export const WorkflowNodeStatus = z.enum([
165
171
  "pending",
166
172
  "ready",
167
173
  "running",
174
+ "paused",
168
175
  "completed",
169
176
  "failed",
170
177
  "skipped",
@@ -211,6 +218,8 @@ export type WorkflowSharedContext = z.infer<typeof WorkflowSharedContext>;
211
218
  export const WorkflowResumeFrom = z.object({
212
219
  /** 要恢复的 workflowId(必须先前 run 过,并有 checkpoint)。 */
213
220
  workflowId: WorkflowId,
221
+ /** Reject a fresh resume if the observed native event cursor has changed. */
222
+ expectedSeq:z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER).optional(),
214
223
  /**
215
224
  * 起点策略:
216
225
  * - "last_success_dependents" : 从最后成功节点的下游开始(DAG 默认)
@@ -218,6 +227,7 @@ export const WorkflowResumeFrom = z.object({
218
227
  * - "node:<nodeId>" : 显式指定从某 node 开始
219
228
  */
220
229
  strategy: z.union([
230
+ z.literal("continue"),
221
231
  z.literal("last_success_dependents"),
222
232
  z.literal("failed_node"),
223
233
  z.string().regex(/^node:/),
@@ -234,6 +244,7 @@ export type WorkflowResumeFrom = z.infer<typeof WorkflowResumeFrom>;
234
244
  export const WorkflowResumeParams = z.object({
235
245
  workflowId: WorkflowId,
236
246
  strategy: z.union([
247
+ z.literal("continue"),
237
248
  z.literal("last_success_dependents"),
238
249
  z.literal("failed_node"),
239
250
  z.string().regex(/^node:/),
@@ -317,6 +328,17 @@ export const WorkflowNodeRuntime = z.object({
317
328
  result: WorkflowNodeResult.optional(),
318
329
  /** 该节点完成的轮次计数(discussion 用;DAG/Graph 一次执行 = 1)。 */
319
330
  iterations: z.number().int().nonnegative().optional(),
331
+ /** 每次执行的 session/turn 映射;用于崩溃恢复、审计和 late-event fencing。 */
332
+ attempts: z.array(z.object({
333
+ attempt: z.number().int().positive(),
334
+ iteration: z.number().int().positive().optional(),
335
+ sessionId: SessionId.optional(),
336
+ turnId: TurnId.optional(),
337
+ status: z.enum(["running", "completed", "failed", "interrupted", "timeout", "cancelled"]),
338
+ startedAt: Timestamp,
339
+ completedAt: Timestamp.optional(),
340
+ error: z.string().optional(),
341
+ })).optional(),
320
342
  });
321
343
  export type WorkflowNodeRuntime = z.infer<typeof WorkflowNodeRuntime>;
322
344
 
@@ -327,7 +349,24 @@ export type WorkflowNodeRuntime = z.infer<typeof WorkflowNodeRuntime>;
327
349
  export const WorkflowStatusParams = z.object({ workflowId: WorkflowId });
328
350
  export type WorkflowStatusParams = z.infer<typeof WorkflowStatusParams>;
329
351
 
352
+ export const WorkflowInputParams=z.object({workflowId:WorkflowId.max(512),nodeId:WorkflowNodeId.max(512),
353
+ sessionId:SessionId,turnId:TurnId.max(512),inputId:ClientRequestId.max(255),input:z.string().min(1).max(16000).refine(value=>!!value.trim())}).strict();
354
+ export type WorkflowInputParams=z.infer<typeof WorkflowInputParams>;
355
+ export const WorkflowInputStatusParams=z.object({workflowId:WorkflowId.max(512),inputId:ClientRequestId.max(255)}).strict();
356
+ export type WorkflowInputStatusParams=z.infer<typeof WorkflowInputStatusParams>;
357
+ export const WorkflowInputReceipt=z.object({workflowId:WorkflowId,nodeId:WorkflowNodeId,sessionId:SessionId,turnId:TurnId,
358
+ inputId:ClientRequestId,contentHash:z.string().regex(/^[a-f0-9]{64}$/),state:z.enum(['inserting','inserted','unknown']),
359
+ createdAt:Timestamp,updatedAt:Timestamp,errorCode:z.string().max(120).optional()}).strict();
360
+ export type WorkflowInputReceipt=z.infer<typeof WorkflowInputReceipt>;
361
+ export const WorkflowInputStatusResult=z.discriminatedUnion('found',[
362
+ z.object({found:z.literal(false),workflowId:WorkflowId,inputId:ClientRequestId}).strict(),
363
+ z.object({found:z.literal(true),receipt:WorkflowInputReceipt}).strict(),
364
+ ]);
365
+ export type WorkflowInputStatusResult=z.infer<typeof WorkflowInputStatusResult>;
366
+
330
367
  export const WorkflowStatusResult = z.object({
368
+ nativeStop:NativeStopProof.optional(),
369
+ dispatchKey: z.string().optional(),
331
370
  workflowId: WorkflowId,
332
371
  status: WorkflowStatus,
333
372
  /** workflow 默认 project;v0.6 起可选。 */
@@ -344,12 +383,51 @@ export const WorkflowStatusResult = z.object({
344
383
  });
345
384
  export type WorkflowStatusResult = z.infer<typeof WorkflowStatusResult>;
346
385
 
386
+ const ResultVersion = z.string().regex(/^[a-f0-9]{64}$/);
387
+ export const WorkflowResultParams = z.object({
388
+ workflowId: WorkflowId,
389
+ nodeId: WorkflowNodeId.optional(),
390
+ offset: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0),
391
+ version: ResultVersion.optional(),
392
+ knownVersion: ResultVersion.optional(),
393
+ }).strict();
394
+ export type WorkflowResultParams = z.infer<typeof WorkflowResultParams>;
395
+ export const WorkflowResultPage = z.object({
396
+ workflowId: WorkflowId,
397
+ project: ProjectId.optional(),
398
+ nodeId: WorkflowNodeId.optional(),
399
+ status: WorkflowStatus,
400
+ version: ResultVersion,
401
+ offset: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
402
+ end: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
403
+ totalLength: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),
404
+ text: z.string().max(16000).optional(),
405
+ omitted: z.literal(true).optional(),
406
+ }).strict().superRefine((value, ctx) => {
407
+ if (value.end < value.offset || value.end > value.totalLength || value.end - value.offset > 16000
408
+ || value.end < value.totalLength && value.end === value.offset
409
+ || (value.omitted === true ? value.text !== undefined : value.text === undefined || value.text.length !== value.end - value.offset)) {
410
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid workflow result page' });
411
+ }
412
+ });
413
+ export type WorkflowResultPage = z.infer<typeof WorkflowResultPage>;
414
+
347
415
  export const WorkflowCancelParams = z.object({ workflowId: WorkflowId, reason: z.string().optional() });
348
416
  export type WorkflowCancelParams = z.infer<typeof WorkflowCancelParams>;
349
- export const WorkflowCancelResult = z.object({ workflowId: WorkflowId, status: z.literal("cancelled") });
417
+ export const WorkflowDispatchCancelParams=z.object({ dispatchKey:z.string().min(1).max(255),project:ProjectId,reason:z.string().max(1000).optional() });
418
+ export type WorkflowDispatchCancelParams=z.infer<typeof WorkflowDispatchCancelParams>;
419
+ export const WorkflowDispatchCancelResult=z.object({ dispatchKey:z.string(),workflowId:WorkflowId.optional(),status:WorkflowStatus,cancelledBeforeStart:z.boolean(),nativeStop:NativeStopProof.optional() });
420
+ export type WorkflowDispatchCancelResult=z.infer<typeof WorkflowDispatchCancelResult>;
421
+ export const WorkflowCancelResult = z.object({ workflowId: WorkflowId, status: WorkflowStatus,nativeStop:NativeStopProof.optional() });
350
422
  export type WorkflowCancelResult = z.infer<typeof WorkflowCancelResult>;
351
423
 
424
+ export const WorkflowPauseParams = z.object({ workflowId: WorkflowId, reason: z.string().optional() });
425
+ export type WorkflowPauseParams = z.infer<typeof WorkflowPauseParams>;
426
+ export const WorkflowPauseResult = z.object({ workflowId: WorkflowId, status: z.literal("paused") });
427
+ export type WorkflowPauseResult = z.infer<typeof WorkflowPauseResult>;
428
+
352
429
  export const WorkflowListParams = z.object({
430
+ dispatchKey: z.string().optional(),
353
431
  status: WorkflowStatus.optional(),
354
432
  projectId: ProjectId.optional(),
355
433
  since: Timestamp.optional(),
@@ -371,6 +449,7 @@ export type WorkflowListResult = z.infer<typeof WorkflowListResult>;
371
449
  // ---------------------------------------------------------------------------
372
450
 
373
451
  export const WorkflowEvent = z.object({
452
+ nativeStop:NativeStopProof.optional(),
374
453
  workflowId: WorkflowId,
375
454
  seq: z.number().int().nonnegative(),
376
455
  type: z.enum([
@@ -392,6 +471,8 @@ export const WorkflowEvent = z.object({
392
471
  agent: AgentId.optional(),
393
472
  model: ModelId.optional(),
394
473
  role: WorkflowRoleId.optional(),
474
+ /** Scheduling/orchestration correlation metadata. */
475
+ metadata: z.record(z.unknown()).optional(),
395
476
  status: z.union([WorkflowStatus, WorkflowNodeStatus]).optional(),
396
477
  result: WorkflowNodeResult.optional(),
397
478
  /** 自由载荷。常见字段:iteration, from, to, reason, terminationReason 等。 */