paseo-plugin-zcode-provider 0.0.0-stage → 0.2.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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +29 -0
  3. package/README.md +112 -2
  4. package/client/account.tsx +827 -0
  5. package/client/diagnostics.tsx +379 -0
  6. package/client/runtime.tsx +296 -0
  7. package/client/settings.tsx +84 -0
  8. package/client/value.tsx +20 -0
  9. package/icon.svg +1 -0
  10. package/index.client.tsx +22 -0
  11. package/index.server.ts +39 -0
  12. package/package.json +77 -4
  13. package/paseo-plugin.json +6 -0
  14. package/server/account.ts +781 -0
  15. package/server/attachments.ts +150 -0
  16. package/server/build-info.ts +2 -0
  17. package/server/conversation.ts +319 -0
  18. package/server/diagnostics.ts +252 -0
  19. package/server/discovery/discover.ts +225 -0
  20. package/server/discovery/manifest.ts +36 -0
  21. package/server/discovery/types.ts +30 -0
  22. package/server/errors.ts +36 -0
  23. package/server/host/bridge.ts +490 -0
  24. package/server/host/schemas.ts +119 -0
  25. package/server/logger.ts +19 -0
  26. package/server/mapping.ts +270 -0
  27. package/server/models.ts +68 -0
  28. package/server/persistence.ts +146 -0
  29. package/server/presentation.ts +470 -0
  30. package/server/provider-status.ts +81 -0
  31. package/server/provider.ts +838 -0
  32. package/server/runtime/managed.ts +501 -0
  33. package/server/runtime/pins.ts +72 -0
  34. package/server/runtime-setup.ts +77 -0
  35. package/server/session-types.ts +49 -0
  36. package/server/session.ts +866 -0
  37. package/server/status.ts +89 -0
  38. package/server/timeline.ts +18 -0
  39. package/server/usage.ts +362 -0
  40. package/server/vendor/zcode/LICENSE +202 -0
  41. package/server/vendor/zcode/NOTICE.md +70 -0
  42. package/server/vendor/zcode/THIRD-PARTY-NOTICES.md +37 -0
  43. package/server/vendor/zcode/packages/model-option-map/src/compiler.ts +92 -0
  44. package/server/vendor/zcode/packages/model-option-map/src/evaluator.ts +214 -0
  45. package/server/vendor/zcode/packages/model-option-map/src/index.ts +5 -0
  46. package/server/vendor/zcode/packages/model-option-map/src/merge-patch.ts +97 -0
  47. package/server/vendor/zcode/packages/model-option-map/src/option-maps.ts +42 -0
  48. package/server/vendor/zcode/packages/model-option-map/src/parser.ts +240 -0
  49. package/server/vendor/zcode/packages/model-option-map/src/tokenizer.ts +141 -0
  50. package/server/vendor/zcode/packages/model-option-map/src/types.ts +36 -0
  51. package/server/vendor/zcode/packages/rpc/src/buffer.ts +88 -0
  52. package/server/vendor/zcode/packages/rpc/src/channelClient.ts +275 -0
  53. package/server/vendor/zcode/packages/rpc/src/channelServer.ts +283 -0
  54. package/server/vendor/zcode/packages/rpc/src/channels.shared.ts +66 -0
  55. package/server/vendor/zcode/packages/rpc/src/channels.ts +4 -0
  56. package/server/vendor/zcode/packages/rpc/src/delayedChannel.ts +17 -0
  57. package/server/vendor/zcode/packages/rpc/src/foundation.ts +260 -0
  58. package/server/vendor/zcode/packages/rpc/src/protocol.ts +397 -0
  59. package/server/vendor/zcode/packages/rpc/src/proxy-channel.ts +213 -0
  60. package/server/vendor/zcode/packages/rpc/src/serialization.ts +291 -0
  61. package/server/vendor/zcode/packages/shared/src/account-provider-state.ts +13 -0
  62. package/server/vendor/zcode/packages/shared/src/background-bash-output.ts +24 -0
  63. package/server/vendor/zcode/packages/shared/src/background-task-controls.ts +404 -0
  64. package/server/vendor/zcode/packages/shared/src/bash-output-display.ts +11 -0
  65. package/server/vendor/zcode/packages/shared/src/bots.ts +558 -0
  66. package/server/vendor/zcode/packages/shared/src/browser-use/backend.ts +80 -0
  67. package/server/vendor/zcode/packages/shared/src/browser-use/command-metadata.ts +170 -0
  68. package/server/vendor/zcode/packages/shared/src/browser-use/commands.ts +588 -0
  69. package/server/vendor/zcode/packages/shared/src/browser-use/result.ts +130 -0
  70. package/server/vendor/zcode/packages/shared/src/browser-use/snapshot.ts +77 -0
  71. package/server/vendor/zcode/packages/shared/src/command-types.ts +96 -0
  72. package/server/vendor/zcode/packages/shared/src/config-schema.ts +8 -0
  73. package/server/vendor/zcode/packages/shared/src/cuaAccessibilitySettings.ts +41 -0
  74. package/server/vendor/zcode/packages/shared/src/database-startup.ts +178 -0
  75. package/server/vendor/zcode/packages/shared/src/env.ts +63 -0
  76. package/server/vendor/zcode/packages/shared/src/execution-output-preview.ts +14 -0
  77. package/server/vendor/zcode/packages/shared/src/localTtft.ts +192 -0
  78. package/server/vendor/zcode/packages/shared/src/model-config.ts +123 -0
  79. package/server/vendor/zcode/packages/shared/src/model-execution.ts +23 -0
  80. package/server/vendor/zcode/packages/shared/src/model-provider-family.ts +171 -0
  81. package/server/vendor/zcode/packages/shared/src/model-provider-types.ts +81 -0
  82. package/server/vendor/zcode/packages/shared/src/model-selection.ts +60 -0
  83. package/server/vendor/zcode/packages/shared/src/oauth.ts +203 -0
  84. package/server/vendor/zcode/packages/shared/src/official-mcp-auth.ts +272 -0
  85. package/server/vendor/zcode/packages/shared/src/official-mcp-tool-error.ts +68 -0
  86. package/server/vendor/zcode/packages/shared/src/process-diagnostic.ts +42 -0
  87. package/server/vendor/zcode/packages/shared/src/protocol.ts +369 -0
  88. package/server/vendor/zcode/packages/shared/src/provider-family-connection-selection.ts +32 -0
  89. package/server/vendor/zcode/packages/shared/src/remoteAssetInstallMode.ts +11 -0
  90. package/server/vendor/zcode/packages/shared/src/remoteResourcePackages.ts +91 -0
  91. package/server/vendor/zcode/packages/shared/src/runtimeEnv.ts +315 -0
  92. package/server/vendor/zcode/packages/shared/src/settings-source.ts +10 -0
  93. package/server/vendor/zcode/packages/shared/src/usage-quota.ts +74 -0
  94. package/server/vendor/zcode/packages/shared/src/usage-stats.ts +462 -0
  95. package/server/vendor/zcode/packages/shared/src/validationAppSettings.ts +562 -0
  96. package/server/vendor/zcode/packages/shared/src/workspacePurpose.ts +2 -0
  97. package/server/vendor/zcode/packages/shared/src/wslUserValidation.ts +33 -0
  98. package/server/vendor/zcode/packages/shared/src/zcode-agent-policy.ts +25 -0
  99. package/server/vendor/zcode/packages/shared/src/zcode-media-policy.ts +10 -0
  100. package/server/vendor/zcode/packages/shared/src/zcode-protocol/index.ts +3720 -0
  101. package/server/vendor/zcode/packages/shared/src/zcode-protocol-legacy-types.ts +529 -0
  102. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.ts +218 -0
  103. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/attachment-ref.ts +14 -0
  104. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/command.ts +482 -0
  105. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/core.ts +100 -0
  106. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-workflow-display.ts +156 -0
  107. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/cuaPermission.ts +41 -0
  108. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/delta.ts +147 -0
  109. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/input-intent.ts +69 -0
  110. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.ts +432 -0
  111. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/session-config.ts +43 -0
  112. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index-workflow-activity.ts +195 -0
  113. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index.ts +85 -0
  114. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-import.ts +38 -0
  115. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-ref.ts +10 -0
  116. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.ts +509 -0
  117. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/submission.ts +5 -0
  118. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/toolDisplay.ts +264 -0
  119. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.ts +1152 -0
  120. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.ts +574 -0
  121. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-binary.ts +65 -0
  122. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-codec.ts +240 -0
  123. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-fault.ts +39 -0
  124. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire.ts +159 -0
  125. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-artifacts.ts +291 -0
  126. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-observation-display.ts +281 -0
  127. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-row-meta.ts +163 -0
  128. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-run-settings-command.ts +62 -0
  129. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs-delta.ts +517 -0
  130. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs.ts +512 -0
  131. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-config.ts +81 -0
  132. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-hook-review.ts +210 -0
  133. package/server/vendor/zcode/packages/shared/src/zcode-task-mode-schema.ts +6 -0
  134. package/server/vendor/zcode/packages/shared/src/zcode-task-types-core.ts +1187 -0
  135. package/server/vendor/zcode/packages/shared/src/zcodeEndpoint.ts +296 -0
  136. package/server/vendor/zcode/provenance.json +405 -0
  137. package/shared/account.ts +201 -0
  138. package/shared/diagnostics.ts +52 -0
  139. package/shared/runtime-setup.ts +73 -0
  140. package/vendor/acp-registry/LICENSE +176 -0
  141. package/vendor/paseo/LICENSE +211 -0
@@ -0,0 +1,482 @@
1
+ import { localTtftContextSchema, localTtftClockSchema } from "../localTtft.js";
2
+ // Command 层:信封 / ACK / 命令全集 payload。
3
+ // conversation rewind 无独立命令(裁决:= editUserQuery 的 UI 入口);
4
+ // workspace-only 文件撤销走 applyFileRewind,不截断聊天历史。
5
+ import { z } from "zod";
6
+ import { conversationRowTargetSchema, timestampSchema } from "./core.js";
7
+ import { attachmentRefSchema } from "./attachment-ref.js";
8
+ import { v4ConversationFileRewindPreviewResultSchema } from "./transport.js";
9
+ import { modelSelectionSchema } from "../model-selection.js";
10
+ import { modelExecutionSchema } from "../model-execution.js";
11
+ import { submissionModeSchema } from "./submission.js";
12
+ import { zcodeAutomationBotDeliveryTargetSchema } from "../bots.js";
13
+ import {
14
+ amendWorkflowRunSettingsPayloadSchema,
15
+ amendWorkflowRunSettingsResultSchema,
16
+ } from "./workflow-run-settings-command.js";
17
+ import {
18
+ workspaceHookReviewCommandTargetSchema,
19
+ workspaceHookReviewDecisionSchema,
20
+ workspaceHookTrustRevokeTargetSchema,
21
+ requestWorkspaceHookReviewTargetSchema,
22
+ } from "./workspace-hook-review.js";
23
+ import {
24
+ zcodeBrowserAmbientContextSchema,
25
+ zcodeProtocolMcpServerSchema,
26
+ } from "../zcode-protocol/index.js";
27
+ import { sharedContextRefSchema } from "./shared-context-ref.js";
28
+ export type { SharedContextRef } from "./shared-context-ref.js";
29
+
30
+ const createSessionRequestedConfigSchema = z.object({
31
+ modelSelection: modelSelectionSchema.optional(),
32
+ provider: z.string().optional(),
33
+ model: z.string().optional(),
34
+ thought: z.string().optional(),
35
+ followupMode: z.enum(["queue", "guide"]).optional(),
36
+ // createSession.config 表达“请求覆盖字段”,不能复用 snapshot 的
37
+ // sessionConfigStateSchema.partial();snapshot 为兼容旧快照给 mode 设了 default("build"),
38
+ // 会把“没传 mode”误变成“请求切回 build”,覆盖 workspace 默认 yolo。
39
+ mode: z.string().optional(),
40
+ planEnabled: z.boolean().optional(),
41
+ });
42
+
43
+ // ── 命令 payload 全集 ──
44
+ export const commandPayloadSchemas = {
45
+ // firstInput 缺省 → phase=draft 空会话;携带 → 直接 turnHeader+userInput rows。
46
+ createSession: z.object({
47
+ workspaceId: z.string(),
48
+ firstInput: z
49
+ .object({
50
+ text: z.string(),
51
+ attachments: z.array(attachmentRefSchema).optional(),
52
+ modelSelection: modelSelectionSchema.optional(),
53
+ mode: submissionModeSchema.optional(),
54
+ planEnabled: z.boolean().optional(),
55
+ })
56
+ .optional(),
57
+ config: createSessionRequestedConfigSchema.optional(),
58
+ // MCP 是 runtime 启动期配置,必须随 create 一次性进入 record,不能在首发后补写。
59
+ mcpServers: z.array(zcodeProtocolMcpServerSchema).optional(),
60
+ // Off-Peak 工具面 flag,与 legacy session/create 等价——V4 createSession 是桌面
61
+ // 新会话的实际创建路径,不透传则 OffPeakCreate/OffPeakList 永不注册。additive,
62
+ // 旧 CLI 的 z.object 会静默丢弃该键(fail-closed)。
63
+ offPeakToolEnabled: z.boolean().optional(),
64
+ // 动态工作流灰度 flag,与 offPeakToolEnabled 同一模式。
65
+ dynamicWorkflowEnabled: z.boolean().optional(),
66
+ }),
67
+ // 父会话由 envelope.sessionId 指定;服务端从父 record 派生完整运行配置。
68
+ // firstInput 存在时,child 创建完成后立即启动首条普通输入;缺省则保持空副屏。
69
+ createSelectionSideSession: z.object({
70
+ firstInput: z
71
+ .object({
72
+ text: z.string().trim().min(1),
73
+ // 提交推荐只覆盖新 child 的完整选择,缺省保留父 runtime 继承。
74
+ modelSelection: modelSelectionSchema.optional(),
75
+ })
76
+ .optional(),
77
+ }),
78
+ // 按 inputRouting 裁决:startNow / enqueue / guide / choice。
79
+ // heldQueueDisposition:held 状态(inputRouting.mode=choice)下必带;
80
+ // clear→清空 queue 后 startNow,keep→保留 queue 立即 startNow。
81
+ sendText: z
82
+ .object({
83
+ text: z.string(),
84
+ attachments: z.array(attachmentRefSchema).optional(),
85
+ // Desktop Cmd/Ctrl+Enter 只覆盖本次 busy input,不改 session followupMode。
86
+ // startNow 由 CLI 原子抢占当前 turn,不经过 queue admission。
87
+ requestedDelivery: z.enum(["startNow", "queue", "guide"]).optional(),
88
+ browserAmbientContext: zcodeBrowserAmbientContextSchema.optional(),
89
+ // Share handover 只允许当前 session 的一个已导入上下文;完整正文由 runtime 从
90
+ // 持久化 provenance 解析,不能随 command 从 renderer 传入。
91
+ context_refs: z.array(sharedContextRefSchema).max(1).optional(),
92
+ heldQueueDisposition: z.enum(["clearQueueAndSend", "keepQueueAndSend"]).optional(),
93
+ // 暂停队列确认框打开时看到的 queueItemId 集合。CLI 在执行 clear/keep 前校验,
94
+ // 防止桌面/手机并发增删后把用户没确认过的新队列一并处置。
95
+ expectedHeldQueueItemIds: z.array(z.string().min(1)).optional(),
96
+ // 迁移期允许旧发送端缺省;CLI admission 会把当前 Session Selection 固定进
97
+ // canonical intent。Renderer 切换完成后,第一方用户提交始终显式携带这两项。
98
+ modelSelection: modelSelectionSchema.optional(),
99
+ mode: submissionModeSchema.optional(),
100
+ planEnabled: z.boolean().optional(),
101
+ // 本次执行仍使用上面的标准 Selection;这里只携带不持久化语义、动态鉴权和 child 策略。
102
+ // 仅 idle startNow 接受,防止 Secret/Ticket 进入普通 CommandInbox。
103
+ modelExecution: modelExecutionSchema.optional(),
104
+ automationId: z.string().min(1).optional(),
105
+ offPeakTaskId: z.string().min(1).optional(),
106
+ offPeakRunType: z.enum(["init", "resume"]).optional(),
107
+ // Bot 来源只由 Host 注入,用于 CronCreate 在当前 turn 内读取并持久化回推地址。
108
+ botDeliveryTarget: zcodeAutomationBotDeliveryTargetSchema.optional(),
109
+ // 定时任务会话的后续用户输入也必须保持 turn-scoped 工具面隔离;不能借用
110
+ // automationId,否则会把普通用户输入误标成一次 automation 派发。
111
+ toolDisallowlist: z.array(z.string().min(1)).optional(),
112
+ })
113
+ .superRefine((payload, context) => {
114
+ if (payload.automationId && payload.offPeakTaskId) {
115
+ context.addIssue({
116
+ code: z.ZodIssueCode.custom,
117
+ message: "automationId and offPeakTaskId are mutually exclusive",
118
+ });
119
+ }
120
+ if (payload.offPeakRunType && !payload.offPeakTaskId) {
121
+ context.addIssue({
122
+ code: z.ZodIssueCode.custom,
123
+ message: "offPeakRunType requires offPeakTaskId",
124
+ path: ["offPeakRunType"],
125
+ });
126
+ }
127
+ if (payload.modelExecution && !payload.modelSelection) {
128
+ context.addIssue({
129
+ code: z.ZodIssueCode.custom,
130
+ message: "modelExecution requires modelSelection",
131
+ path: ["modelExecution"],
132
+ });
133
+ }
134
+ }),
135
+ sendGoalCommand: z.object({
136
+ text: z.string(),
137
+ displayText: z.string().optional(),
138
+ modelSelection: modelSelectionSchema.optional(),
139
+ mode: submissionModeSchema.optional(),
140
+ planEnabled: z.boolean().optional(),
141
+ heldQueueDisposition: z.enum(["clearQueueAndSend", "keepQueueAndSend"]).optional(),
142
+ expectedHeldQueueItemIds: z.array(z.string().min(1)).optional(),
143
+ }),
144
+ stop: z.object({
145
+ // 来自 activeWorks;CLI 用它拒绝会误杀后续无关执行的迟到 Stop。
146
+ expectedForegroundExecutionId: z.string().min(1).optional(),
147
+ }),
148
+ // compact 是输入型维护命令:idle 时立即执行,busy/held 时进入 FIFO。
149
+ // 因为 admission 与当前 revision 无关,不走 CAS;sourceCommandId 提供幂等边界。
150
+ compact: z.object({}),
151
+ // running 时对稳定 assistant row 可用。
152
+ forkAssistant: z.object({ target: conversationRowTargetSchema }),
153
+ applyFileRewind: z.object({ target: conversationRowTargetSchema }),
154
+ editUserQuery: z.object({
155
+ target: conversationRowTargetSchema,
156
+ newText: z.string(),
157
+ attachments: z.array(attachmentRefSchema).optional(),
158
+ // 缺省 preserve:仅切 conversation branch;rewind 会先安全恢复该轮文件。
159
+ workspaceMode: z.enum(["preserve", "rewind"]).optional(),
160
+ }),
161
+ retryTurn: z.object({ target: conversationRowTargetSchema }),
162
+ setAssistantFeedback: z.object({
163
+ target: conversationRowTargetSchema,
164
+ feedback: z.enum(["like", "dislike"]).nullable(),
165
+ }),
166
+ sendQueuedNow: z.object({ queueItemId: z.string() }),
167
+ editQueueItem: z.object({ queueItemId: z.string(), newText: z.string() }),
168
+ // beforeQueueItemId = null → 移到队尾。
169
+ reorderQueueItem: z.object({
170
+ queueItemId: z.string(),
171
+ beforeQueueItemId: z.string().nullable(),
172
+ }),
173
+ deleteQueueItem: z.object({ queueItemId: z.string() }),
174
+ setAutoDrain: z.object({ autoDrain: z.boolean() }),
175
+ // 先到先得,晚到 noop(reasonCode=proto.alreadyResolved)。
176
+ resolveInteraction: z.object({
177
+ interactionId: z.string(),
178
+ answer: z.object({
179
+ optionId: z.string().optional(),
180
+ freeText: z.string().optional(),
181
+ // (elicitation 回执收敛):AskUserQuestion/plan-approval 的
182
+ // 多题答案与注解无损承载。action 存在时 CLI broker 按 accept/decline/cancel
183
+ // 精确映射(content 直传旧 userInput response 语义);缺省沿用
184
+ // optionId/freeText 兼容路径,旧客户端行为不变。
185
+ action: z.enum(["accept", "decline", "cancel"]).optional(),
186
+ content: z.record(z.string(), z.unknown()).optional(),
187
+ }),
188
+ }),
189
+ respondWorkspaceHookReview: workspaceHookReviewCommandTargetSchema.extend({
190
+ decision: workspaceHookReviewDecisionSchema,
191
+ }),
192
+ toggleWorkspaceHookReviewItem: workspaceHookReviewCommandTargetSchema.extend({
193
+ reviewItemId: z.string().trim().min(1),
194
+ enabled: z.boolean(),
195
+ }),
196
+ revokeWorkspaceHookTrust: z.union([
197
+ workspaceHookReviewCommandTargetSchema.extend({
198
+ reviewItemIds: z.array(z.string().trim().min(1)).min(1),
199
+ }),
200
+ workspaceHookTrustRevokeTargetSchema,
201
+ ]),
202
+ // 软门禁:按需开审核 flow,克隆 revoke non-flow target 但不带 hookDeclarationDigests。
203
+ requestWorkspaceHookReview: requestWorkspaceHookReviewTargetSchema,
204
+ // AskUserQuestion 首次有效操作永久暂停本次自动结束;重复/迟到调用为幂等 noop。
205
+ snoozeInteractionAutoResolution: z.object({
206
+ interactionId: z.string(),
207
+ }),
208
+ switchModelConfig: z.object({
209
+ provider: z.string(),
210
+ model: z.string(),
211
+ thought: z.string(),
212
+ }),
213
+ // additive(冻结面按黄金测试背书演进):agent 协作模式切换。
214
+ // 值域 = core CollaborationMode 的可切换子集(auto 非用户可切,不进 UI 命令面)。
215
+ switchCollaborationMode: z.object({
216
+ mode: z.enum(["build", "edit", "plan", "yolo"]),
217
+ }),
218
+ setFollowupMode: z.object({ mode: z.enum(["queue", "guide"]) }),
219
+ pauseGoal: z.object({}),
220
+ resumeGoal: z.object({}),
221
+ cancelBackgroundWork: z.object({ workId: z.string() }),
222
+ // cancel & resume:恢复一个已取消 / 被进程死亡
223
+ // 打断的 dwf run。workId ≡ runId(与 cancelBackgroundWork 同一个身份等式);`name` 可选,
224
+ // 喂恢复后完成通知的主题(重启后原 CreateWorkflow 工具 input 不可得)。刻意不携
225
+ // baseRevision:与 cancelBackgroundWork 同类(workflowRuns 面免 revision,假 CAS 失败
226
+ // 只会误伤)。门在 CLI 侧(可恢复集 = cancelled ∪ failed+Interrupted),拒绝以
227
+ // fault.command.workflowRunResumeRejected.<reason> 回 ACK。
228
+ resumeWorkflowRun: z.object({ workId: z.string(), name: z.string().optional() }),
229
+ // startSavedWorkflow:中枢「运行」不再合成
230
+ // 对话文案,直接请 agent 在新会话里启动已保存工作流。与 cancelBackgroundWork / resumeWorkflowRun
231
+ // 同类:不携 baseRevision(workflowRuns 面免 revision,假 CAS 失败只会误伤)。name 由 agent 从
232
+ // 解析结果填(不变式 6),命令不收 name 覆盖。
233
+ // 拒绝以 fault.command.savedWorkflowStartRejected.<reason> 回 ACK(词表见下方
234
+ // savedWorkflowStartRejectionReasonSchema);能力缺席(无 dwf 端口)→ V4CapabilityUnsupportedError
235
+ // (与 resumeWorkflowRun 同一条错误)。
236
+ startSavedWorkflow: z.object({
237
+ name: z.string().min(1),
238
+ scope: z.enum(["project", "global"]).optional(),
239
+ args: z.record(z.string(), z.unknown()).optional(),
240
+ }),
241
+ // amendWorkflowRunSettings:run 卡 / 详情页的「配置」直接请 agent 以新设置修订 run,不经模型轮。载荷、结果与拒绝
242
+ // 词表见 workflow-run-settings-command.ts;能力缺席 → V4CapabilityUnsupportedError。
243
+ amendWorkflowRunSettings: amendWorkflowRunSettingsPayloadSchema,
244
+ renameSession: z.object({ title: z.string() }),
245
+ deleteSession: z.object({}),
246
+ discardSharedContext: z.object({ contextId: z.string().trim().min(1) }).strict(),
247
+ } as const;
248
+
249
+ export type CommandType = keyof typeof commandPayloadSchemas;
250
+ export type CommandPayloadMap = {
251
+ [T in CommandType]: T extends "sendText"
252
+ ? z.infer<(typeof commandPayloadSchemas)[T]> &
253
+ import("../zcode-task-types-core.js").ZCodeBackgroundTurnAttribution
254
+ : z.infer<(typeof commandPayloadSchemas)[T]>;
255
+ };
256
+
257
+ export const commandTypeSchema = z.enum(
258
+ Object.keys(commandPayloadSchemas) as [CommandType, ...CommandType[]],
259
+ );
260
+
261
+ // startSavedWorkflow 拒绝词表:
262
+ // bootstrap handler 铸造 fault code,ui launcher 反查 i18n 文案,两侧共享此枚举避免漂移。
263
+ // invalid_name / not_found:解析阶段;invalid_args:实参校验;compile_failed:analyzeScript 诊断;
264
+ // session_busy:会话有活动 turn;start_failed:port.submit 之前的其它启动失败。
265
+ export const savedWorkflowStartRejectionReasonSchema = z.enum([
266
+ "invalid_name",
267
+ "not_found",
268
+ "invalid_args",
269
+ "compile_failed",
270
+ "session_busy",
271
+ "start_failed",
272
+ ]);
273
+ export type SavedWorkflowStartRejectionReason = z.infer<
274
+ typeof savedWorkflowStartRejectionReasonSchema
275
+ >;
276
+
277
+ // 完整 fault code = 前缀 + reason(如 fault.command.savedWorkflowStartRejected.not_found)。
278
+ // 与 workflowRunResumeRejected 命名空间同族;导出常量供 bootstrap 拼接、ui 前缀匹配。
279
+ export const SAVED_WORKFLOW_START_REJECTED_FAULT_PREFIX =
280
+ "fault.command.savedWorkflowStartRejected." as const;
281
+
282
+ // resumeWorkflowRun 的拒绝:前缀 + 端口 reason(not_found / not_resumable / superseded /
283
+ // already_running / script_missing / script_mismatch / compile_failed);`ack.message` 携带
284
+ // compile_failed 的有界诊断。
285
+ export const WORKFLOW_RUN_RESUME_REJECTED_FAULT_PREFIX =
286
+ "fault.command.workflowRunResumeRejected." as const;
287
+
288
+ // cancelBackgroundWork 的拒绝:core 明确回「没有取消任何东西」时(任务不存在 / 已终结 / 类型不支持)
289
+ // 以前缀 + reason 上行,而不是一个假装成功的 accepted——详情页据此告诉用户这个 run 并不在跑。
290
+ // reason 即 core 的 stopBackgroundTask reason 去掉 `background_task_` 前缀:not_found /
291
+ // not_running / cancel_not_supported。
292
+ export const BACKGROUND_WORK_CANCEL_REJECTED_FAULT_PREFIX =
293
+ "fault.command.backgroundWorkCancelRejected." as const;
294
+
295
+ // CAS ✓ 的命令:信封必带 baseRevision。
296
+ export const COMMANDS_REQUIRING_BASE_REVISION: ReadonlySet<CommandType> = new Set([
297
+ "applyFileRewind",
298
+ "forkAssistant",
299
+ "editUserQuery",
300
+ "retryTurn",
301
+ "setAssistantFeedback",
302
+ "sendQueuedNow",
303
+ "editQueueItem",
304
+ "reorderQueueItem",
305
+ "deleteQueueItem",
306
+ "setAutoDrain",
307
+ "switchModelConfig",
308
+ "switchCollaborationMode",
309
+ "setFollowupMode",
310
+ "pauseGoal",
311
+ "resumeGoal",
312
+ ]);
313
+
314
+ export const ROW_TARGETING_COMMANDS: ReadonlySet<CommandType> = new Set([
315
+ "applyFileRewind",
316
+ "forkAssistant",
317
+ "editUserQuery",
318
+ "retryTurn",
319
+ "setAssistantFeedback",
320
+ ]);
321
+
322
+ // ── 信封 ──
323
+ export const commandEnvelopeSchema = z.object({
324
+ ttft: localTtftContextSchema.optional(),
325
+ // uuid v7,客户端生成,重试不变。
326
+ commandId: z.string(),
327
+ clientId: z.string(),
328
+ // createSession 时为 null。
329
+ sessionId: z.string().nullable(),
330
+ baseRevision: z.number().optional(),
331
+ baseLogEpoch: z.string().trim().min(1).optional(),
332
+ type: commandTypeSchema,
333
+ payload: z.unknown(),
334
+ // 客户端时钟,仅遥测;服务端不用于任何裁决。
335
+ issuedAt: timestampSchema,
336
+ });
337
+ export type CommandEnvelope = z.infer<typeof commandEnvelopeSchema>;
338
+
339
+ /** 校验信封并按 type 校验 payload(信封 schema 无法静态关联 payload,收口在这里)。 */
340
+ export function parseCommandEnvelope(
341
+ value: unknown,
342
+ ): { ok: true; envelope: CommandEnvelope } | { ok: false; error: z.ZodError } {
343
+ const envelope = commandEnvelopeSchema.safeParse(value);
344
+ if (!envelope.success) return { ok: false, error: envelope.error };
345
+ const payload = commandPayloadSchemas[envelope.data.type].safeParse(envelope.data.payload);
346
+ if (!payload.success) return { ok: false, error: payload.error };
347
+ if (
348
+ (COMMANDS_REQUIRING_BASE_REVISION.has(envelope.data.type) &&
349
+ envelope.data.baseRevision === undefined) ||
350
+ (ROW_TARGETING_COMMANDS.has(envelope.data.type) && envelope.data.baseLogEpoch === undefined)
351
+ ) {
352
+ return {
353
+ ok: false,
354
+ error: new z.ZodError([
355
+ {
356
+ code: "custom",
357
+ path: [envelope.data.baseRevision === undefined ? "baseRevision" : "baseLogEpoch"],
358
+ message: "CAS commands require baseRevision and baseLogEpoch",
359
+ },
360
+ ]),
361
+ };
362
+ }
363
+ return {
364
+ ok: true,
365
+ envelope: { ...envelope.data, payload: payload.data },
366
+ };
367
+ }
368
+
369
+ // ── ACK ──
370
+ export const commandResultSchema = z.discriminatedUnion("type", [
371
+ z.object({
372
+ type: z.enum(["createSession", "createSelectionSideSession", "forkAssistant"]),
373
+ sessionId: z.string(),
374
+ input: z
375
+ .object({
376
+ delivery: z.enum(["startNow", "queue", "guide"]),
377
+ inputId: z.string(),
378
+ // Core admission ACK 不等待 TurnStarted;messageId 可能由后续事件补齐。
379
+ messageId: z.string().optional(),
380
+ })
381
+ .optional(),
382
+ }),
383
+ z.object({
384
+ type: z.literal("resolveInteraction"),
385
+ resolvedBy: z.object({
386
+ clientId: z.string(),
387
+ optionId: z.string().optional(),
388
+ }),
389
+ }),
390
+ z.object({
391
+ type: z.literal("applyFileRewind"),
392
+ applied: z.boolean(),
393
+ preview: v4ConversationFileRewindPreviewResultSchema,
394
+ response: z.string(),
395
+ }),
396
+ z.object({
397
+ type: z.literal("editUserQuery"),
398
+ // fork 仅保留旧 ACK 解码兼容;新 editUserQuery 不再生成 child session。
399
+ disposition: z.enum(["rewind", "fork", "blocked"]),
400
+ sessionId: z.string().min(1),
401
+ reasonCode: z.string().min(1).optional(),
402
+ preview: v4ConversationFileRewindPreviewResultSchema.optional(),
403
+ }),
404
+ z.object({
405
+ // startSavedWorkflow accepted ACK:
406
+ // runId 联接启动轮 run 卡状态 / 通知 / 侧板;toolCallId = launch-<uuid>,联接合成 CreateWorkflow 轮。
407
+ type: z.literal("startSavedWorkflow"),
408
+ runId: z.string().min(1),
409
+ toolCallId: z.string().min(1),
410
+ }),
411
+ amendWorkflowRunSettingsResultSchema,
412
+ z.object({
413
+ // messageId 只在 TurnStarted 后作为旁路归因补齐;Core admission ACK 不等待
414
+ // projection commit,不能把 messageId 作为输入 accepted 的必要条件。
415
+ type: z.literal("inputAccepted"),
416
+ delivery: z.enum(["startNow", "queue", "guide"]),
417
+ inputId: z.string(),
418
+ messageId: z.string().optional(),
419
+ }),
420
+ z.object({
421
+ // restart discarded 过去只返回一个无差别 fault,renderer 无法区分
422
+ // runtime-local queue 与仍需人工确认的 startNow。delivery 来自 session_input
423
+ // 持久事实,不能由客户端按当前 UI phase 猜测。
424
+ type: z.literal("inputDisposition"),
425
+ delivery: z.enum(["startNow", "queue", "guide"]),
426
+ }),
427
+ ]);
428
+ export type CommandResult = z.infer<typeof commandResultSchema>;
429
+
430
+ export const commandAckSchema = z.object({
431
+ /** 会话创建期采用的 App Memory 开关;旧发送端缺省表示未知。 */
432
+ memoryEnabled: z.boolean().optional(),
433
+ ttftExcluded: z.literal("capacity").optional(),
434
+ commandId: z.string(),
435
+ // accepted 不承诺跨 CLI 进程存活;最终收口以权威数据(sourceCommandId)为准。
436
+ status: z.enum(["accepted", "rejected", "stale", "duplicate", "noop", "failed"]),
437
+ // rejected/stale/noop/failed 必带;= guard id 或 fault code(命名空间)。
438
+ reasonCode: z.string().optional(),
439
+ message: z.string().optional(),
440
+ revisionAtDecision: z.number(),
441
+ // duplicate 回放缓存结果;accepted 亦可即时带(fork)。
442
+ result: commandResultSchema.optional(),
443
+ });
444
+ export type CommandAck = z.infer<typeof commandAckSchema>;
445
+
446
+ // ── commands/query ──
447
+ export const commandKeySchema = z
448
+ .object({
449
+ // null 只属于全局/createSession 幂等桶;session 命令必须携带 sessionId。
450
+ sessionId: z.string().nullable(),
451
+ commandId: z.string().min(1),
452
+ })
453
+ .strict();
454
+ export type CommandKey = z.infer<typeof commandKeySchema>;
455
+
456
+ export const commandsQueryParamsSchema = z
457
+ .object({
458
+ commands: z.array(commandKeySchema).min(1).max(64),
459
+ clock: z.literal(true).optional(),
460
+ })
461
+ .strict()
462
+ .refine(
463
+ (params) => !params.clock || params.commands.every((key) => key.sessionId === null),
464
+ "clock probes cannot query session commands",
465
+ );
466
+ export type CommandsQueryParams = z.infer<typeof commandsQueryParamsSchema>;
467
+
468
+ export const commandQueryItemSchema = z
469
+ .object({
470
+ key: commandKeySchema,
471
+ result: z.union([commandAckSchema, z.literal("unknown")]),
472
+ })
473
+ .strict();
474
+ export type CommandQueryItem = z.infer<typeof commandQueryItemSchema>;
475
+
476
+ export const commandsQueryResultSchema = z
477
+ .object({
478
+ results: z.array(commandQueryItemSchema).min(1).max(64),
479
+ clock: localTtftClockSchema.optional(),
480
+ })
481
+ .strict();
482
+ export type CommandsQueryResult = z.infer<typeof commandsQueryResultSchema>;
@@ -0,0 +1,100 @@
1
+ // ZCode Protocol v4 —— 数据模型草稿(未冻结,schema 定型以黄金测试为准)。
2
+ // 本包纪律:只放 schema 类型 + 纯函数,禁止任何运行时/IO/传输逻辑。
3
+ import { z } from "zod";
4
+ import { VIDEO_INPUT_MAX_BYTES } from "../zcode-media-policy.js";
5
+
6
+ /** V4 物理 wire 协议版本;projection snapshot 继续独立使用 protocolVersion=1。 */
7
+ export const V4_WIRE_PROTOCOL_VERSION = 3 as const;
8
+
9
+ /** V3 row target:display row 与稳定实体必须成对提交并由同一权威投影校验。 */
10
+ export const conversationRowTargetSchema = z
11
+ .object({
12
+ rowId: z.number().int().nonnegative(),
13
+ entityId: z.string().trim().min(1),
14
+ })
15
+ .strict();
16
+ export type ConversationRowTarget = z.infer<typeof conversationRowTargetSchema>;
17
+
18
+ // 时钟规则:Unix ms,一律 CLI 时钟;客户端禁止拿本地时钟与协议 Timestamp 相减。
19
+ export const timestampSchema = z.number();
20
+ export type Timestamp = z.infer<typeof timestampSchema>;
21
+
22
+ // delivery profile:只存在于 CLI flush 管线的参数表,客户端代码禁止出现 profile 变量。
23
+ export const streamablePathSchema = z.enum(["text", "inputText", "output.text", "summaryText"]);
24
+ export type StreamablePath = z.infer<typeof streamablePathSchema>;
25
+
26
+ export interface DeliveryProfile {
27
+ desktopOnlyRows: boolean;
28
+ flushWindowMs: number;
29
+ streamPaths: Record<StreamablePath, boolean>;
30
+ streamOutputCapBytes: number;
31
+ toolProgress: boolean;
32
+ }
33
+
34
+ export const DELIVERY_PROFILES = {
35
+ continuous: {
36
+ desktopOnlyRows: true,
37
+ flushWindowMs: 30,
38
+ streamPaths: {
39
+ text: true,
40
+ inputText: true,
41
+ "output.text": true,
42
+ summaryText: true,
43
+ },
44
+ streamOutputCapBytes: 262144,
45
+ toolProgress: false,
46
+ },
47
+ replayable: {
48
+ desktopOnlyRows: false,
49
+ flushWindowMs: 150,
50
+ streamPaths: {
51
+ text: true,
52
+ inputText: false,
53
+ "output.text": false,
54
+ summaryText: false,
55
+ },
56
+ streamOutputCapBytes: 0,
57
+ toolProgress: true,
58
+ },
59
+ } as const satisfies Record<string, DeliveryProfile>;
60
+
61
+ export type DeliveryProfileName = keyof typeof DELIVERY_PROFILES;
62
+
63
+ // 常量与限额(初始值,实测调参)。
64
+ export const PROTOCOL_V4_LIMITS = {
65
+ maxFrameBytes: 1024 * 1024,
66
+ logicalFrameAssemblyMaxBytes: 16 * 1024 * 1024,
67
+ logicalFrameAssemblyMaxFragments: 1024,
68
+ logicalFrameAssemblyMaxConcurrent: 32,
69
+ logicalFrameAssemblyMaxStagedBytes: 32 * 1024 * 1024,
70
+ logicalFrameAssemblyTimeoutMs: 30_000,
71
+ transportEnvelopeIdMaxChars: 256,
72
+ subscriberBufferMaxOps: 500,
73
+ subscriberBufferMaxBytes: 1024 * 1024,
74
+ eventRetentionPerSession: 2000,
75
+ snapshotTailWindowRows: 60,
76
+ rowsRangeMaxLimit: 200,
77
+ toolOutputFinalHeadBytes: 32 * 1024,
78
+ toolOutputFinalTailBytes: 32 * 1024,
79
+ goalVerificationsRetained: 20,
80
+ pendingCommandsDisplayMax: 32,
81
+ commandPendingTtlMs: 24 * 60 * 60 * 1000,
82
+ idempotencyTablePerSession: 512,
83
+ conversationQueryTimeoutMs: 10_000,
84
+ attachmentMaxBytes: 20 * 1024 * 1024,
85
+ attachmentChunkMaxBytes: 512 * 1024,
86
+ attachmentPreviewMaxBytes: VIDEO_INPUT_MAX_BYTES,
87
+ // share 选择阶段的 metadata-only stat 曾复用 attachmentPreviewMaxBytes
88
+ // (30MiB)作为 totalBytes 上限,于是超过该值的附件在 schema 校验就抛错,
89
+ // 「容量超限」这个本应确定阻断的分类反而被降级成 deferred 并静默丢内容。
90
+ // stat 不搬运字节,只需要一个足够表达真实文件大小的上界。
91
+ attachmentStatMaxBytes: 2 * 1024 * 1024 * 1024,
92
+ attachmentPreviewMaxChunks: VIDEO_INPUT_MAX_BYTES / (512 * 1024),
93
+ attachmentReadCacheMaxBytes: VIDEO_INPUT_MAX_BYTES,
94
+ attachmentReadCacheTtlMs: 30_000,
95
+ attachmentUploadMaxChunks: 64,
96
+ attachmentUploadMaxConcurrent: 16,
97
+ attachmentUploadMaxStagedBytes: 64 * 1024 * 1024,
98
+ attachmentUploadTtlMs: 5 * 60_000,
99
+ attachmentUnreferencedTtlMs: 24 * 60 * 60 * 1000,
100
+ } as const;