@whaletalk/dsh-codex-collab 0.1.9 → 0.1.10

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.
@@ -121,14 +121,25 @@ const foldRecords = (events) => {
121
121
  error: undefined,
122
122
  reason: undefined,
123
123
  stopReason: undefined,
124
+ // 投递控制(第四轮):父关系/投递模式是**不可变关系**,在 bind 时就落盘(不能等执行后补)。
125
+ deliver: event.deliver,
126
+ parentTaskId: event.parentTaskId,
127
+ resultScope: event.resultScope,
128
+ requestSeq: event.requestSeq,
129
+ receiptState: event.receiptState,
130
+ route: event.route,
131
+ routePolicy: event.routePolicy,
124
132
  })
125
133
  continue
126
134
  }
127
135
  if (event.type === 'update') {
128
136
  const record = records.get(event.taskId)
129
137
  if (record === undefined) continue
130
- for (const key of ['status', 'delivered', 'result', 'error', 'reason', 'stopReason', 'requestId', 'dshTurn']) {
131
- if (event[key] !== undefined) record[key] = event[key]
138
+ for (const key of ['status', 'delivered', 'result', 'error', 'reason', 'stopReason', 'requestId', 'dshTurn', 'deliver', 'parentTaskId', 'receiptState', 'observedTurn', 'resultScope', 'requestSeq', 'route', 'routePolicy', 'routeStopReason']) {
139
+ if (event[key] === undefined) continue
140
+ // 显式 null = **清除**(回执绝不允许残留父任务的 result/reason 等旧值)
141
+ if (event[key] === null) { delete record[key]; continue }
142
+ record[key] = event[key]
132
143
  }
133
144
  record.updatedAt = event.at
134
145
  }
@@ -182,7 +193,7 @@ export const openAssociations = (options = {}) => {
182
193
  * 登记一条关联。**必须在执行前调用**:写盘失败就抛错,让调用方放弃启动 DSH 执行
183
194
  * (绝不出现"执行了却没绑定")。
184
195
  */
185
- bind({ originThreadId, taskId, kind, target, delivered }) {
196
+ bind({ originThreadId, taskId, kind, target, delivered, deliver, parentTaskId, resultScope, requestSeq, receiptState, route, routePolicy }) {
186
197
  if (!isValidOrigin(originThreadId)) {
187
198
  throw fail(ASSOC_REASONS.INVALID_ORIGIN, 'originThreadId must be a non-empty string of at most ' + MAX_ORIGIN_LENGTH + ' characters without control characters')
188
199
  }
@@ -204,6 +215,15 @@ export const openAssociations = (options = {}) => {
204
215
  profile,
205
216
  status: 'accepted',
206
217
  delivered: delivered === true ? true : undefined,
218
+ // 不可变父关系 / 投递模式(第四轮 A):执行前就落盘,重启后仍在
219
+ deliver: deliver === 'steer' || deliver === 'queue' ? deliver : undefined,
220
+ parentTaskId: typeof parentTaskId === 'string' && parentTaskId !== '' ? parentTaskId : undefined,
221
+ resultScope: typeof resultScope === 'string' ? resultScope : undefined,
222
+ requestSeq: typeof requestSeq === 'number' ? requestSeq : undefined,
223
+ receiptState: typeof receiptState === 'string' ? receiptState : undefined,
224
+ // 模型路由(第一版验收修正):派活前就落盘的选择/策略(重启后可按 origin+task 取回)
225
+ route: route !== null && typeof route === 'object' ? route : undefined,
226
+ routePolicy: routePolicy !== null && typeof routePolicy === 'object' ? routePolicy : undefined,
207
227
  at,
208
228
  })
209
229
  return load().get(taskId)
@@ -222,12 +242,24 @@ export const openAssociations = (options = {}) => {
222
242
  taskId,
223
243
  status: typeof patch.status === 'string' ? patch.status : undefined,
224
244
  delivered: patch.delivered === undefined ? undefined : patch.delivered === true,
225
- result: typeof patch.result === 'string' ? patch.result : undefined,
226
- error: typeof patch.error === 'string' ? patch.error : undefined,
227
- reason: typeof patch.reason === 'string' ? patch.reason : undefined,
228
- stopReason: typeof patch.stopReason === 'string' ? patch.stopReason : undefined,
245
+ result: patch.result === null ? null : (typeof patch.result === 'string' ? patch.result : undefined),
246
+ error: patch.error === null ? null : (typeof patch.error === 'string' ? patch.error : undefined),
247
+ reason: patch.reason === null ? null : (typeof patch.reason === 'string' ? patch.reason : undefined),
248
+ stopReason: patch.stopReason === null ? null : (typeof patch.stopReason === 'string' ? patch.stopReason : undefined),
229
249
  requestId: typeof patch.requestId === 'string' ? patch.requestId : undefined,
230
250
  dshTurn: typeof patch.dshTurn === 'number' ? patch.dshTurn : undefined,
251
+ // 投递控制(第四轮 A):投递模式与父/回执关系(持久化,重启后仍能查);
252
+ // `null` = 显式清除(回执绝不允许残留父任务的旧 result/reason)。
253
+ deliver: patch.deliver === 'steer' || patch.deliver === 'queue' ? patch.deliver : undefined,
254
+ parentTaskId: patch.parentTaskId === null ? null : (typeof patch.parentTaskId === 'string' ? patch.parentTaskId : undefined),
255
+ receiptState: patch.receiptState === null ? null : (typeof patch.receiptState === 'string' ? patch.receiptState : undefined),
256
+ observedTurn: patch.observedTurn === null ? null : (typeof patch.observedTurn === 'number' ? patch.observedTurn : undefined),
257
+ resultScope: patch.resultScope === null ? null : (typeof patch.resultScope === 'string' ? patch.resultScope : undefined),
258
+ requestSeq: patch.requestSeq === null ? null : (typeof patch.requestSeq === 'number' ? patch.requestSeq : undefined),
259
+ // 模型路由(第一版验收修正):选择/策略/终止原因随任务落盘(重启后按 origin+task 可取回)
260
+ route: patch.route === null ? null : (patch.route !== null && typeof patch.route === 'object' ? patch.route : undefined),
261
+ routePolicy: patch.routePolicy === null ? null : (patch.routePolicy !== null && typeof patch.routePolicy === 'object' ? patch.routePolicy : undefined),
262
+ routeStopReason: patch.routeStopReason === null ? null : (typeof patch.routeStopReason === 'string' ? patch.routeStopReason : undefined),
231
263
  at: Date.now(),
232
264
  })
233
265
  return load().get(taskId)