@yielded/agent 0.1.0-beta.175 → 0.1.0-beta.177
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/dist/{Admin-Qa3I1oA5.d.mts → Admin-Bpg24yCK.d.mts} +19 -13
- package/dist/{Agent-BiRbr73L.mjs → Agent-B3J0B4l6.mjs} +6 -3
- package/dist/Agent-B3J0B4l6.mjs.map +1 -0
- package/dist/{AgentRuntime-DaDKMasp.mjs → AgentRuntime-DrQfy4cL.mjs} +7 -6
- package/dist/AgentRuntime-DrQfy4cL.mjs.map +1 -0
- package/dist/{AgentRuntime-CHDyRbSf.d.mts → AgentRuntime-Dx5u_FJD.d.mts} +6 -6
- package/dist/{Digest-C3EODOee.mjs → Digest-ft4ku9pj.mjs} +2 -2
- package/dist/{Digest-C3EODOee.mjs.map → Digest-ft4ku9pj.mjs.map} +1 -1
- package/dist/{DurableAgentRuntime-CPlw5_7e.mjs → DurableAgentRuntime-CGW93k81.mjs} +176 -63
- package/dist/DurableAgentRuntime-CGW93k81.mjs.map +1 -0
- package/dist/{DurableStep-DXGn7KQ4.d.mts → DurableStep-CAJnlgfL.d.mts} +5 -4
- package/dist/{EventSource-BTu68yDW.d.mts → EventSource-A6TB7t-f.d.mts} +2 -2
- package/dist/{MessageDelivery-DjAZJ4Fd.d.mts → MessageDelivery-BkWrcQUd.d.mts} +4 -4
- package/dist/{Messaging-SVu6rWV8.d.mts → Messaging-DpEZMTVE.d.mts} +2 -2
- package/dist/{MessagingHost-CZCyrnvJ.mjs → MessagingHost-BILcuj0V.mjs} +2 -2
- package/dist/{MessagingHost-CZCyrnvJ.mjs.map → MessagingHost-BILcuj0V.mjs.map} +1 -1
- package/dist/{MessagingHost-C6SOAcoG.d.mts → MessagingHost-BKxDskYj.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-wgY4JMZY.d.mts → PreparedInputAdmission-DKIfqRZT.d.mts} +3 -3
- package/dist/{Records-DzL4Kbtw.mjs → Records-CZRedCE7.mjs} +3 -3
- package/dist/{Records-DzL4Kbtw.mjs.map → Records-CZRedCE7.mjs.map} +1 -1
- package/dist/{RunContinuation-3jB5pULC.d.mts → RunContinuation-Ce2pR8VD.d.mts} +4 -4
- package/dist/{RunContinuation-BiyKJK32.mjs → RunContinuation-D42RFqjS.mjs} +5 -5
- package/dist/RunContinuation-D42RFqjS.mjs.map +1 -0
- package/dist/{RunJournal-CPMKcfd0.mjs → RunJournal-oJLo-pjS.mjs} +7 -7
- package/dist/{RunJournal-CPMKcfd0.mjs.map → RunJournal-oJLo-pjS.mjs.map} +1 -1
- package/dist/{RunOptions-Be77lKVZ.d.mts → RunOptions-BANtohGk.d.mts} +3 -3
- package/dist/{RunStorage-CzutHJBE.mjs → RunStorage-BRGP3Tcu.mjs} +43 -33
- package/dist/RunStorage-BRGP3Tcu.mjs.map +1 -0
- package/dist/{Scheduling-07_dsGED.mjs → Scheduling-BebkRVc2.mjs} +3 -3
- package/dist/{Scheduling-07_dsGED.mjs.map → Scheduling-BebkRVc2.mjs.map} +1 -1
- package/dist/{Subagent-xhN_aD1r.d.mts → Subagent-5ulnV6An.d.mts} +9 -9
- package/dist/{Subagent-CexndZSp.mjs → Subagent-C7F7c8Op.mjs} +3 -3
- package/dist/{Subagent-CexndZSp.mjs.map → Subagent-C7F7c8Op.mjs.map} +1 -1
- package/dist/{SubagentHost-D1xBgn9g.d.mts → SubagentHost-CikdGpmk.d.mts} +2 -2
- package/dist/{Subscription-DmIHlOJK.d.mts → Subscription-D5sOrmlI.d.mts} +2 -2
- package/dist/{SubscriptionInput-DgcQhvbe.d.mts → SubscriptionInput-CxSXZUiC.d.mts} +2 -2
- package/dist/{ThreadImport-DP-vOk2F.d.mts → ThreadImport-C6IiPJMW.d.mts} +42 -42
- package/dist/{ThreadImport-CjlG57vH.mjs → ThreadImport-DUcPj5jC.mjs} +9 -9
- package/dist/{ThreadImport-CjlG57vH.mjs.map → ThreadImport-DUcPj5jC.mjs.map} +1 -1
- package/dist/{ThreadStore-EuUilthA.mjs → ThreadStore-Cn6FDWX9.mjs} +42 -21
- package/dist/ThreadStore-Cn6FDWX9.mjs.map +1 -0
- package/dist/{ThreadTransfer-DB_zsrtJ.mjs → ThreadTransfer-BWnAHIge.mjs} +4 -4
- package/dist/{ThreadTransfer-DB_zsrtJ.mjs.map → ThreadTransfer-BWnAHIge.mjs.map} +1 -1
- package/dist/{Worker-CHRaIsWu.d.mts → Worker-CLYgfqhF.d.mts} +7 -5
- package/dist/{Worker-DZjdMjZn.mjs → Worker-CtuUwYOK.mjs} +4 -2
- package/dist/Worker-CtuUwYOK.mjs.map +1 -0
- package/dist/{WorkerAdmission-eBeXt_mu.mjs → WorkerAdmission-cfiK9aRi.mjs} +6 -6
- package/dist/{WorkerAdmission-eBeXt_mu.mjs.map → WorkerAdmission-cfiK9aRi.mjs.map} +1 -1
- package/dist/{agent-registration-a6QYaG3h.mjs → agent-registration-Dt57NAP6.mjs} +5 -5
- package/dist/{agent-registration-a6QYaG3h.mjs.map → agent-registration-Dt57NAP6.mjs.map} +1 -1
- package/dist/capabilities/CodeMode.mjs +1 -1
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/ContextTools.mjs +1 -1
- package/dist/capabilities/McpClient.mjs +1 -1
- package/dist/capabilities/MemoryNotes.d.mts +1 -1
- package/dist/capabilities/MemoryNotes.mjs +2 -1
- package/dist/capabilities/MemoryNotes.mjs.map +1 -1
- package/dist/capabilities/Messaging.d.mts +1 -1
- package/dist/capabilities/Messaging.mjs +2 -2
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/Subagent.d.mts +2 -2
- package/dist/capabilities/Subagent.mjs +2 -2
- package/dist/capabilities/ToolDiscovery.mjs +1 -1
- package/dist/capabilities/WebCapture.mjs +1 -1
- package/dist/capabilities/WebSearch.mjs +1 -1
- package/dist/core/Agent.mjs +1 -1
- package/dist/core/Worker.d.mts +1 -1
- package/dist/core/Worker.mjs +1 -1
- package/dist/durable/ActivityStore.mjs +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/Admin.mjs +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/AgentRegistration.mjs +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/CommittedActivity.mjs +3 -3
- package/dist/durable/Digest.mjs +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +2 -2
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/EventSource.mjs +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/LifecyclePublication.mjs +3 -3
- package/dist/durable/MessageDelivery.d.mts +1 -1
- package/dist/durable/MessageDelivery.mjs +3 -3
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +2 -2
- package/dist/durable/MessageDeliveryStoreConformance.mjs +3 -3
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PersistentHistory.mjs +4 -4
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/RecordFormat.mjs +1 -1
- package/dist/durable/Records.mjs +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/Recovery.mjs +1 -1
- package/dist/durable/RunContinuation.d.mts +2 -2
- package/dist/durable/RunContinuation.mjs +3 -3
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/RunJournal.mjs +1 -1
- package/dist/durable/RunStorage.d.mts +1 -1
- package/dist/durable/RunStorage.mjs +1 -1
- package/dist/durable/Schedule.mjs +1 -1
- package/dist/durable/ScheduleStoreConformance.mjs +1 -1
- package/dist/durable/ScheduleTransition.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +1 -1
- package/dist/durable/Scheduling.mjs +1 -1
- package/dist/durable/SettlementPublisher.d.mts +1 -1
- package/dist/durable/SettlementPublisher.mjs +3 -3
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +4 -4
- package/dist/durable/SubmissionLedger.mjs.map +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +7 -7
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/Subscription.mjs +2 -2
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +2 -2
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +1 -1
- package/dist/durable/SubscriptionTools.d.mts +3 -3
- package/dist/durable/SubscriptionTools.mjs +2 -1
- package/dist/durable/SubscriptionTools.mjs.map +1 -1
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/SubscriptionTransition.mjs +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/Subscriptions.mjs +2 -2
- package/dist/durable/ThreadArchiveRange.d.mts +1 -1
- package/dist/durable/ThreadArchiveRange.mjs +1 -1
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.mjs +2 -2
- package/dist/durable/ThreadContextHistoryProjection.mjs +1 -1
- package/dist/durable/ThreadImport.d.mts +1 -1
- package/dist/durable/ThreadImport.mjs +1 -1
- package/dist/durable/ThreadInvariants.d.mts +3 -3
- package/dist/durable/ThreadInvariants.mjs +4 -4
- package/dist/durable/ThreadProjection.mjs +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadReader.d.mts +1 -1
- package/dist/durable/ThreadReader.mjs +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +2 -2
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +4 -4
- package/dist/durable/ThreadTransfer.d.mts +1 -1
- package/dist/durable/ThreadTransfer.mjs +1 -1
- package/dist/durable/ThreadWork.d.mts +1 -1
- package/dist/durable/ThreadWork.mjs +5 -5
- package/dist/durable/ToolReconciler.mjs +1 -1
- package/dist/durable/WorkerAdmission.d.mts +68 -68
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +2 -2
- package/dist/durable/WorkerHost.mjs +1 -1
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/DurableStep.d.mts +2 -2
- package/dist/engine/DurableStep.mjs +1 -11
- package/dist/engine/DurableStep.mjs.map +1 -1
- package/dist/engine/MessagingHost.d.mts +1 -1
- package/dist/engine/MessagingHost.mjs +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/engine/SubagentHost.mjs +1 -1
- package/dist/index.d.mts +16 -16
- package/dist/index.mjs +15 -15
- package/dist/{run-context-reader-DVhJZ1Qe.d.mts → run-context-reader-BtBPX_nC.d.mts} +2 -2
- package/dist/tool-execution-Ba7tO7Pt.mjs +17 -0
- package/dist/tool-execution-Ba7tO7Pt.mjs.map +1 -0
- package/package.json +1 -1
- package/src/core/Worker.ts +3 -1
- package/src/core/internal/agent-updates.ts +9 -1
- package/src/core/internal/tool-execution.ts +33 -0
- package/src/durable/DurableAgentRuntime.ts +243 -63
- package/src/durable/RunContinuation.ts +2 -2
- package/src/durable/RunJournal.ts +9 -5
- package/src/durable/RunStorage.ts +83 -61
- package/src/durable/SubmissionLedger.ts +8 -0
- package/src/durable/ThreadStore.ts +39 -19
- package/src/durable/internal/agent-updates.ts +59 -3
- package/src/durable/internal/initial-context.ts +17 -2
- package/src/durable/internal/prompt-history-cache.ts +13 -8
- package/src/durable/internal/worker-host.ts +3 -1
- package/src/engine/DurableStep.ts +5 -31
- package/src/engine/internal/agent-runtime.ts +2 -1
- package/dist/Agent-BiRbr73L.mjs.map +0 -1
- package/dist/AgentRuntime-DaDKMasp.mjs.map +0 -1
- package/dist/DurableAgentRuntime-CPlw5_7e.mjs.map +0 -1
- package/dist/RunContinuation-BiyKJK32.mjs.map +0 -1
- package/dist/RunStorage-CzutHJBE.mjs.map +0 -1
- package/dist/ThreadStore-EuUilthA.mjs.map +0 -1
- package/dist/Worker-DZjdMjZn.mjs.map +0 -1
|
@@ -113,6 +113,8 @@ export interface RunWriter {
|
|
|
113
113
|
|
|
114
114
|
export interface RunStorageSession extends RunWriter, RunOwnership {
|
|
115
115
|
readonly claim: Claim;
|
|
116
|
+
/** Atomic original input/context plus the ledger marker, when the adapter supports it. */
|
|
117
|
+
readonly appendInput?: RunWriter["append"];
|
|
116
118
|
/** Library-only initialization, before application/model IO. Hold progress before mutation
|
|
117
119
|
* so the captured controls and this owner's acknowledged input remain one read view. */
|
|
118
120
|
readonly withInitialization?: <A, E, R>(
|
|
@@ -176,69 +178,75 @@ const makeWriter = Effect.fnUntraced(function* (threadId: ThreadId) {
|
|
|
176
178
|
}),
|
|
177
179
|
);
|
|
178
180
|
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
ThreadStoreError.make({
|
|
190
|
-
operation: "capture append",
|
|
191
|
-
message: cause.message,
|
|
192
|
-
cause,
|
|
181
|
+
const makeAppend = Effect.gen(function* () {
|
|
182
|
+
const publisher = yield* ThreadStore;
|
|
183
|
+
|
|
184
|
+
const append: RunWriter["append"] = Effect.fnUntraced(function* (batch, executions) {
|
|
185
|
+
const captured = yield* PreparedAppend.capture(
|
|
186
|
+
AppendRequest.make({
|
|
187
|
+
threadId,
|
|
188
|
+
expectedTailSequence: tail.sequence,
|
|
189
|
+
batch,
|
|
190
|
+
...(executions === undefined ? {} : { executions }),
|
|
193
191
|
}),
|
|
194
|
-
)
|
|
195
|
-
|
|
192
|
+
).pipe(
|
|
193
|
+
Effect.mapError((cause) =>
|
|
194
|
+
ThreadStoreError.make({
|
|
195
|
+
operation: "capture append",
|
|
196
|
+
message: cause.message,
|
|
197
|
+
cause,
|
|
198
|
+
}),
|
|
199
|
+
),
|
|
200
|
+
);
|
|
196
201
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
202
|
+
return yield* owner.withProgress(
|
|
203
|
+
threadId,
|
|
204
|
+
owner.withMutation(
|
|
205
|
+
Effect.gen(function* () {
|
|
206
|
+
yield* checkActive;
|
|
207
|
+
for (let retries = 0; ; retries++) {
|
|
208
|
+
const result = yield* publisher
|
|
209
|
+
.append(
|
|
210
|
+
captured.expectedTailSequence === tail.sequence
|
|
211
|
+
? captured
|
|
212
|
+
: AppendRequest.make({
|
|
213
|
+
...captured,
|
|
214
|
+
expectedTailSequence: tail.sequence,
|
|
215
|
+
}),
|
|
216
|
+
)
|
|
217
|
+
.pipe(
|
|
218
|
+
Effect.catchTag("AppendConflict", (conflict) => {
|
|
219
|
+
if (
|
|
220
|
+
conflict.reason !== "tail" ||
|
|
221
|
+
conflict.actualTailSequence === undefined ||
|
|
222
|
+
retries >= 8
|
|
223
|
+
)
|
|
224
|
+
return Effect.fail(conflict);
|
|
225
|
+
tail = { sequence: conflict.actualTailSequence };
|
|
226
|
+
if (captured.executions !== undefined) return Effect.fail(conflict);
|
|
227
|
+
|
|
228
|
+
return Effect.succeed(undefined);
|
|
229
|
+
}),
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
if (result === undefined) continue;
|
|
233
|
+
// A historical replay returns its original coordinates, not today's canonical tail.
|
|
234
|
+
if (result.replayed) yield* refresh;
|
|
235
|
+
else tail = { sequence: result.lastSequence };
|
|
236
|
+
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
}).pipe(
|
|
240
|
+
// Revoke uncertain writes before releasing the writer's mutation gate.
|
|
241
|
+
Effect.onError((cause) =>
|
|
242
|
+
isDefiniteWriteFailure(cause) ? Effect.void : ownership.release,
|
|
243
|
+
),
|
|
238
244
|
),
|
|
239
245
|
),
|
|
240
|
-
)
|
|
241
|
-
);
|
|
246
|
+
);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return append;
|
|
242
250
|
});
|
|
243
251
|
|
|
244
252
|
const writer = {
|
|
@@ -247,13 +255,14 @@ const makeWriter = Effect.fnUntraced(function* (threadId: ThreadId) {
|
|
|
247
255
|
withProgress: <A, E, R>(effect: Effect.Effect<A, E, R>) =>
|
|
248
256
|
owner.withProgress(threadId, Effect.andThen(checkActive, effect)),
|
|
249
257
|
tail: Effect.sync(() => tail),
|
|
250
|
-
append,
|
|
258
|
+
append: yield* makeAppend,
|
|
251
259
|
checkActive: owner.withMutation(checkActive),
|
|
252
260
|
refresh,
|
|
253
261
|
};
|
|
254
262
|
|
|
255
263
|
return {
|
|
256
264
|
writer,
|
|
265
|
+
makeAppend,
|
|
257
266
|
adoptTail: (sequence: CanonicalSequence) => {
|
|
258
267
|
tail = { sequence };
|
|
259
268
|
},
|
|
@@ -310,7 +319,7 @@ export const make = Effect.gen(function* () {
|
|
|
310
319
|
});
|
|
311
320
|
yield* store.materialize(ThreadMaterialization.make({ threadId: request.threadId }));
|
|
312
321
|
|
|
313
|
-
const { writer, adoptTail } = yield* makeWriter(request.threadId).pipe(
|
|
322
|
+
const { writer, makeAppend, adoptTail } = yield* makeWriter(request.threadId).pipe(
|
|
314
323
|
Effect.provideService(WriterOwnership, generation),
|
|
315
324
|
Effect.provideService(ThreadStore, store),
|
|
316
325
|
Effect.provideService(StorageOwner, owner),
|
|
@@ -318,9 +327,22 @@ export const make = Effect.gen(function* () {
|
|
|
318
327
|
|
|
319
328
|
const owned = <A, E>(effect: Effect.Effect<A, E>) => generation.use(effect);
|
|
320
329
|
|
|
330
|
+
const inputPublisher = ledger.appendInput;
|
|
331
|
+
|
|
332
|
+
const appendInput =
|
|
333
|
+
inputPublisher === undefined
|
|
334
|
+
? undefined
|
|
335
|
+
: yield* makeAppend.pipe(
|
|
336
|
+
Effect.provideService(ThreadStore, {
|
|
337
|
+
...store,
|
|
338
|
+
append: (request) => inputPublisher(claimed.submissionId, request),
|
|
339
|
+
}),
|
|
340
|
+
);
|
|
341
|
+
|
|
321
342
|
const session: RunStorageSession = {
|
|
322
343
|
...writer,
|
|
323
344
|
claim: claimed,
|
|
345
|
+
...(appendInput === undefined ? {} : { appendInput }),
|
|
324
346
|
withInitialization: (effect) =>
|
|
325
347
|
owner.withProgress(request.threadId, generation.use(effect)),
|
|
326
348
|
release: generation.release,
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
ToolCallUnknown,
|
|
37
37
|
WorkerAdmission,
|
|
38
38
|
} from "./Records.ts";
|
|
39
|
+
import type { AppendRequest, AppendResult, ThreadStoreFailure } from "./ThreadStore.ts";
|
|
39
40
|
|
|
40
41
|
export { IdempotencyKey, JoinedToHost, QueueSequence, Principal } from "../core/Receipt.ts";
|
|
41
42
|
|
|
@@ -1113,6 +1114,13 @@ export class SubmissionLedger extends Context.Service<
|
|
|
1113
1114
|
readonly selectHead: (
|
|
1114
1115
|
request: ClaimRequest,
|
|
1115
1116
|
) => Effect.Effect<Option.Option<Claim>, LedgerError>;
|
|
1117
|
+
/** Atomically publish a captured original input, active context and applied marker.
|
|
1118
|
+
* Optional adapters retain the ordinary append-then-repair protocol. The captured input
|
|
1119
|
+
* must be this owner's deterministic admission; a moved context boundary is refused. */
|
|
1120
|
+
readonly appendInput?: (
|
|
1121
|
+
submissionId: SubmissionId,
|
|
1122
|
+
request: AppendRequest,
|
|
1123
|
+
) => Effect.Effect<AppendResult, ThreadStoreFailure>;
|
|
1116
1124
|
readonly markInputApplied: (
|
|
1117
1125
|
request: MarkInputAppliedRequest,
|
|
1118
1126
|
) => Effect.Effect<void, OwnershipLost | LedgerError>;
|
|
@@ -343,19 +343,20 @@ export class AppendRequest extends Schema.Class<AppendRequest>(
|
|
|
343
343
|
expectedTailSequence: CanonicalSequence,
|
|
344
344
|
}) {}
|
|
345
345
|
|
|
346
|
+
const RecordCount = Schema.Array(Schema.Unknown).check(Schema.isMaxLength(256));
|
|
347
|
+
const ExecutionRecordCount = Schema.Array(Schema.Unknown).check(Schema.isMaxLength(8));
|
|
348
|
+
|
|
346
349
|
const AppendHeader = Schema.Struct({
|
|
347
350
|
threadId: ThreadId,
|
|
348
351
|
expectedTailSequence: CanonicalSequence,
|
|
349
352
|
batchId: BatchId,
|
|
350
353
|
producerId: ProducerId,
|
|
354
|
+
records: RecordCount,
|
|
355
|
+
executions: RecordCount,
|
|
351
356
|
});
|
|
352
357
|
|
|
353
358
|
const validateHeader = Schema.decodeUnknownSync(AppendHeader);
|
|
354
359
|
|
|
355
|
-
const validateRecordCount = Schema.decodeUnknownSync(
|
|
356
|
-
Schema.Array(Schema.Unknown).check(Schema.isMaxLength(256)),
|
|
357
|
-
);
|
|
358
|
-
|
|
359
360
|
const validateExecutionHeader = Schema.decodeUnknownSync(
|
|
360
361
|
Schema.Struct({
|
|
361
362
|
previousRevision: ExecutionUpdate.fields.previousRevision,
|
|
@@ -366,24 +367,36 @@ const validateExecutionHeader = Schema.decodeUnknownSync(
|
|
|
366
367
|
originalSequence: ExecutionCheckpoint.fields.originalSequence,
|
|
367
368
|
throughSequence: ExecutionCheckpoint.fields.throughSequence,
|
|
368
369
|
batchId: ExecutionCheckpoint.fields.batchId,
|
|
370
|
+
operational: ExecutionRecordCount,
|
|
369
371
|
}),
|
|
372
|
+
facts: ExecutionRecordCount,
|
|
370
373
|
}),
|
|
371
374
|
);
|
|
372
375
|
|
|
373
|
-
const validateExecutionRecordCount = Schema.decodeUnknownSync(
|
|
374
|
-
Schema.Array(Schema.Unknown).check(Schema.isMaxLength(8)),
|
|
375
|
-
);
|
|
376
|
-
|
|
377
376
|
/** Capture records once; wrapper fields retain their owning Schema's constraints. */
|
|
378
377
|
const captureExecution = (input: ExecutionUpdate) => {
|
|
379
|
-
const
|
|
380
|
-
const operationalInput =
|
|
378
|
+
const checkpointInput = input.checkpoint;
|
|
379
|
+
const operationalInput = checkpointInput.operational;
|
|
381
380
|
const factsInput = input.facts;
|
|
382
381
|
|
|
383
|
-
const
|
|
384
|
-
|
|
382
|
+
const header = validateExecutionHeader({
|
|
383
|
+
previousRevision: input.previousRevision,
|
|
384
|
+
retire: input.retire,
|
|
385
|
+
checkpoint: {
|
|
386
|
+
version: checkpointInput.version,
|
|
387
|
+
canonicalRecords: checkpointInput.canonicalRecords,
|
|
388
|
+
originalSequence: checkpointInput.originalSequence,
|
|
389
|
+
throughSequence: checkpointInput.throughSequence,
|
|
390
|
+
batchId: checkpointInput.batchId,
|
|
391
|
+
operational: operationalInput,
|
|
392
|
+
},
|
|
393
|
+
facts: factsInput,
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const operationalLength = header.checkpoint.operational.length;
|
|
397
|
+
const factsLength = header.facts.length;
|
|
385
398
|
|
|
386
|
-
const progress = captureRecord(
|
|
399
|
+
const progress = captureRecord(checkpointInput.progressRecord);
|
|
387
400
|
|
|
388
401
|
if (Result.isFailure(progress)) return Result.fail(progress.failure);
|
|
389
402
|
const progressRecord = progress.success.canonical;
|
|
@@ -530,15 +543,19 @@ export const PreparedAppend = {
|
|
|
530
543
|
return Effect.try({
|
|
531
544
|
try: () =>
|
|
532
545
|
Result.gen(function* () {
|
|
546
|
+
const executions = input.executions ?? [];
|
|
547
|
+
const recordInputs = input.batch.records;
|
|
548
|
+
|
|
533
549
|
const header = validateHeader({
|
|
534
550
|
...input,
|
|
535
551
|
batchId: input.batch.batchId,
|
|
536
552
|
producerId: input.batch.producerId,
|
|
553
|
+
records: recordInputs,
|
|
554
|
+
executions,
|
|
537
555
|
});
|
|
538
556
|
|
|
539
|
-
|
|
540
|
-
const
|
|
541
|
-
const executionLength = validateRecordCount(executions).length;
|
|
557
|
+
const recordLength = header.records.length;
|
|
558
|
+
const executionLength = header.executions.length;
|
|
542
559
|
|
|
543
560
|
const executionWrites: Array<PreparedAppend["executionWrites"][number]> = [];
|
|
544
561
|
|
|
@@ -546,7 +563,7 @@ export const PreparedAppend = {
|
|
|
546
563
|
executionWrites.push(yield* captureExecution(executions[index]!));
|
|
547
564
|
Object.freeze(executionWrites);
|
|
548
565
|
|
|
549
|
-
if (
|
|
566
|
+
if (recordLength === 0 && executionWrites.length === 0)
|
|
550
567
|
return yield* Result.fail(
|
|
551
568
|
ThreadStoreError.make({
|
|
552
569
|
operation: "prepare durable commit",
|
|
@@ -560,8 +577,11 @@ export const PreparedAppend = {
|
|
|
560
577
|
message: "Active state exceeds its bounded transfer representation",
|
|
561
578
|
}),
|
|
562
579
|
);
|
|
563
|
-
// Visit
|
|
564
|
-
const encodings =
|
|
580
|
+
// Visit Schema-validated indexed slots, including sparse ones, never a caller's iterator.
|
|
581
|
+
const encodings = [];
|
|
582
|
+
|
|
583
|
+
for (let index = 0; index < recordLength; index++)
|
|
584
|
+
encodings.push(yield* captureRecord(recordInputs[index]!));
|
|
565
585
|
const prefix = `{"batchId":${JSON.stringify(header.batchId)},"producerId":${JSON.stringify(header.producerId)},"records":[`;
|
|
566
586
|
const batchJson = `${prefix}${encodings.map(({ json }) => json).join(",")}]}`;
|
|
567
587
|
|
|
@@ -2,6 +2,7 @@ import { Clock, Crypto, DateTime, Effect, Option, Schema, Stream } from "effect"
|
|
|
2
2
|
|
|
3
3
|
import { Update, UpdateError } from "../../core/AgentUpdates.ts";
|
|
4
4
|
import type { RunId, SubmissionId, ThreadId } from "../../core/Identifiers.ts";
|
|
5
|
+
import { nativeUpdateId } from "../../core/internal/agent-updates.ts";
|
|
5
6
|
import { utf8ByteLength } from "../../core/internal/utf8.ts";
|
|
6
7
|
import { IdempotencyKey } from "../../core/Receipt.ts";
|
|
7
8
|
import { digestJson } from "../Digest.ts";
|
|
@@ -16,6 +17,8 @@ import {
|
|
|
16
17
|
BatchId,
|
|
17
18
|
CanonicalBatch,
|
|
18
19
|
DefinitionDigests,
|
|
20
|
+
type CanonicalRecordEnvelope,
|
|
21
|
+
type DeclaredToolCall,
|
|
19
22
|
type DeploymentId,
|
|
20
23
|
PersistedJson,
|
|
21
24
|
type ProducerId,
|
|
@@ -26,7 +29,7 @@ import { CurrentRunWriter, readRunEvidenceSnapshot } from "../RunContinuation.ts
|
|
|
26
29
|
import { runIdForSubmission } from "../RunJournal.ts";
|
|
27
30
|
import { LedgerError, type SubmissionSnapshot } from "../SubmissionLedger.ts";
|
|
28
31
|
import { PreparedInput } from "../Subscription.ts";
|
|
29
|
-
import { ThreadReader, ThreadStore, ThreadTailRequest } from "../ThreadStore.ts";
|
|
32
|
+
import { getRecord, ThreadReader, ThreadStore, ThreadTailRequest } from "../ThreadStore.ts";
|
|
30
33
|
import {
|
|
31
34
|
deliveryPredecessor,
|
|
32
35
|
decodeWorkCursor,
|
|
@@ -44,6 +47,37 @@ const storage = () =>
|
|
|
44
47
|
|
|
45
48
|
const rejected = (reason: UpdateError["reason"]) => UpdateError.make({ reason });
|
|
46
49
|
|
|
50
|
+
const updateDigest = (threadId: ThreadId, runId: RunId, updateId: string) =>
|
|
51
|
+
digestJson([threadId, runId, updateId]);
|
|
52
|
+
|
|
53
|
+
const nativeParameters = Schema.Struct({ value: Schema.Json });
|
|
54
|
+
const isNativeParameters = Schema.is(nativeParameters);
|
|
55
|
+
const definitionDigestsEqual = Schema.toEquivalence(DefinitionDigests);
|
|
56
|
+
const updateValuesEqual = Schema.toEquivalence(Schema.Json);
|
|
57
|
+
|
|
58
|
+
/** Canonical native acceptance proves only this exact update call, never an external effect.
|
|
59
|
+
* Its frozen delivery remains independently recoverable even when its Tool acknowledgement is lost.
|
|
60
|
+
*/
|
|
61
|
+
export const nativeUpdateAccepted = (
|
|
62
|
+
submission: SubmissionSnapshot,
|
|
63
|
+
call: DeclaredToolCall,
|
|
64
|
+
records: ReadonlyArray<CanonicalRecordEnvelope>,
|
|
65
|
+
): boolean => {
|
|
66
|
+
if (call.toolName !== "emit_update" || !isNativeParameters(call.parameters)) return false;
|
|
67
|
+
const value = call.parameters.value;
|
|
68
|
+
|
|
69
|
+
return records.some(
|
|
70
|
+
({ record: { payload } }) =>
|
|
71
|
+
payload._tag === "AgentUpdateEmitted" &&
|
|
72
|
+
payload.update.threadId === submission.threadId &&
|
|
73
|
+
payload.update.agentId === submission.agentId &&
|
|
74
|
+
payload.update.runId === call.runId &&
|
|
75
|
+
payload.update.updateId === nativeUpdateId(call.runId, call.toolCallId) &&
|
|
76
|
+
definitionDigestsEqual(payload.definitions, submission.agentDigests) &&
|
|
77
|
+
updateValuesEqual(payload.update.value, value),
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
47
81
|
/** Acceptance is fenced by the actual emitting Attempt; recovery only recreates frozen outbox rows. */
|
|
48
82
|
export const makeAgentUpdateRuntime = Effect.fnUntraced(function* (options: {
|
|
49
83
|
readonly deploymentId: DeploymentId;
|
|
@@ -58,6 +92,28 @@ export const makeAgentUpdateRuntime = Effect.fnUntraced(function* (options: {
|
|
|
58
92
|
|
|
59
93
|
const reader = ThreadReader.fromStore(store);
|
|
60
94
|
|
|
95
|
+
// Terminal operation evidence excludes updates; fetch the original acceptance by its
|
|
96
|
+
// stable identity instead of expanding every operation's recovery history.
|
|
97
|
+
const accepted = Effect.fnUntraced(function* (
|
|
98
|
+
submission: SubmissionSnapshot,
|
|
99
|
+
call: DeclaredToolCall,
|
|
100
|
+
) {
|
|
101
|
+
if (call.toolName !== "emit_update") return false;
|
|
102
|
+
|
|
103
|
+
const digest = yield* updateDigest(
|
|
104
|
+
submission.threadId,
|
|
105
|
+
call.runId,
|
|
106
|
+
nativeUpdateId(call.runId, call.toolCallId),
|
|
107
|
+
).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.mapError(storage));
|
|
108
|
+
|
|
109
|
+
const record = yield* getRecord({
|
|
110
|
+
threadId: submission.threadId,
|
|
111
|
+
recordId: RecordId.make(`agent-update:${digest}`),
|
|
112
|
+
}).pipe(Effect.provideService(ThreadReader, reader), Effect.mapError(storage));
|
|
113
|
+
|
|
114
|
+
return Option.isSome(record) && nativeUpdateAccepted(submission, call, [record.value]);
|
|
115
|
+
});
|
|
116
|
+
|
|
61
117
|
const readRun = Effect.fnUntraced(function* (threadId: ThreadId, submissionId: SubmissionId) {
|
|
62
118
|
const tail = yield* store
|
|
63
119
|
.inspectTail(ThreadTailRequest.make({ threadId }))
|
|
@@ -194,7 +250,7 @@ export const makeAgentUpdateRuntime = Effect.fnUntraced(function* (options: {
|
|
|
194
250
|
Effect.mapError(() => rejected("validation")),
|
|
195
251
|
);
|
|
196
252
|
|
|
197
|
-
const digest = yield*
|
|
253
|
+
const digest = yield* updateDigest(request.submission.threadId, request.runId, updateId).pipe(
|
|
198
254
|
Effect.provideService(Crypto.Crypto, crypto),
|
|
199
255
|
Effect.mapError(storage),
|
|
200
256
|
);
|
|
@@ -367,5 +423,5 @@ export const makeAgentUpdateRuntime = Effect.fnUntraced(function* (options: {
|
|
|
367
423
|
),
|
|
368
424
|
);
|
|
369
425
|
|
|
370
|
-
return { emit, repair: insert, repairRun };
|
|
426
|
+
return { emit, accepted, repair: insert, repairRun };
|
|
371
427
|
});
|
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import { Effect, Option, Schema, Stream } from "effect";
|
|
2
2
|
import { Prompt } from "effect/ai";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CanonicalSequence,
|
|
6
|
+
type CanonicalRecordEnvelope,
|
|
7
|
+
type RecordEnvelope,
|
|
8
|
+
type UserInputRecorded,
|
|
9
|
+
} from "../Records.ts";
|
|
5
10
|
import { RunJournalError, toolCallSettledRecordId } from "../RunJournal.ts";
|
|
6
11
|
import { submissionSettlementRecordId } from "../SubmissionLedger.ts";
|
|
7
12
|
import { getRecord, getRunInput, PROMPT_EVIDENCE_TAGS, ThreadReader } from "../ThreadStore.ts";
|
|
8
13
|
import type { JournalRecordEnvelope } from "./journal-metadata.ts";
|
|
9
14
|
|
|
15
|
+
/** A captured original input can prepare context before its atomic publication. It carries
|
|
16
|
+
* an expected position, never a committed observation cursor or dispatch authority. */
|
|
17
|
+
export type InitialContextInput =
|
|
18
|
+
| CanonicalRecordEnvelope
|
|
19
|
+
| {
|
|
20
|
+
readonly threadId: CanonicalRecordEnvelope["threadId"];
|
|
21
|
+
readonly sequence: CanonicalRecordEnvelope["sequence"];
|
|
22
|
+
readonly record: RecordEnvelope & { readonly payload: UserInputRecorded };
|
|
23
|
+
};
|
|
24
|
+
|
|
10
25
|
const invalid = (message: string) => RunJournalError.make({ message });
|
|
11
26
|
const promptTag = new Set<string>(PROMPT_EVIDENCE_TAGS);
|
|
12
27
|
|
|
13
28
|
/** Fresh admission trusts validated immutable history; recovery verifies its saved Prompt digest. */
|
|
14
|
-
export const initialContext = Effect.fnUntraced(function* (original:
|
|
29
|
+
export const initialContext = Effect.fnUntraced(function* (original: InitialContextInput) {
|
|
15
30
|
const reader = yield* ThreadReader;
|
|
16
31
|
const threadId = original.threadId;
|
|
17
32
|
const through = CanonicalSequence.make(original.sequence - 1);
|
|
@@ -6,9 +6,9 @@ import { boundedValueFootprint } from "../../engine/internal/bounded-value.ts";
|
|
|
6
6
|
import { canonicalJson, digestCanonicalJson, utf8ByteLength } from "../Digest.ts";
|
|
7
7
|
import {
|
|
8
8
|
CanonicalSequence,
|
|
9
|
+
type CanonicalRecordEnvelope,
|
|
9
10
|
CURRENT_RECORD_FORMAT,
|
|
10
11
|
PromptRecord,
|
|
11
|
-
type CanonicalRecordEnvelope,
|
|
12
12
|
type Digest,
|
|
13
13
|
type PromptRecordEnvelope,
|
|
14
14
|
type RecordEnvelope,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
ThreadStore,
|
|
24
24
|
ThreadTailRequest,
|
|
25
25
|
} from "../ThreadStore.ts";
|
|
26
|
+
import type { InitialContextInput } from "./initial-context.ts";
|
|
26
27
|
import type { JournalRecordEnvelope } from "./journal-metadata.ts";
|
|
27
28
|
import { promptJsonFootprint } from "./prompt-footprint.ts";
|
|
28
29
|
import { captureRecord } from "./record-encoding.ts";
|
|
@@ -149,12 +150,14 @@ const retainedBytes = (value: unknown, json: string, allowance: number) => {
|
|
|
149
150
|
return footprint === undefined ? undefined : encodedBytes + 2 * footprint;
|
|
150
151
|
};
|
|
151
152
|
|
|
152
|
-
const encodeHistory =
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
const encodeHistory = (prompt: Prompt.Prompt, allowance: number) =>
|
|
154
|
+
Effect.suspend(() =>
|
|
155
|
+
Effect.mapEager(encodePrompt(prompt), (value) => {
|
|
156
|
+
const encoded = canonicalJson(value);
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
})
|
|
158
|
+
return { encoded, bytes: retainedBytes(value, encoded, allowance) };
|
|
159
|
+
}),
|
|
160
|
+
);
|
|
158
161
|
|
|
159
162
|
// Finish parsing/decoding before suspending for suffix reads. Only the native prefix and its
|
|
160
163
|
// canonical string leave this Effect; it does not keep a second parsed root in the outer Run.
|
|
@@ -252,7 +255,9 @@ const suffixRecordFootprint = (entry: PromptRecordEnvelope, allowance: number) =
|
|
|
252
255
|
* acknowledged, consecutive appends. Never authority for writes or recovery; any uncertainty
|
|
253
256
|
* discards this derivative and completion rereads canonical history.
|
|
254
257
|
*/
|
|
255
|
-
export const makeCommittedPromptSuffix = (
|
|
258
|
+
export const makeCommittedPromptSuffix = (
|
|
259
|
+
original: Pick<CanonicalRecordEnvelope, "threadId" | "sequence" | "record">,
|
|
260
|
+
) => {
|
|
256
261
|
const records: Array<PromptRecordEnvelope> = [];
|
|
257
262
|
|
|
258
263
|
const runId =
|
|
@@ -558,7 +563,7 @@ export const makePromptHistoryCache = Effect.fnUntraced(function* () {
|
|
|
558
563
|
const complete = Effect.fnUntraced(
|
|
559
564
|
function* (
|
|
560
565
|
writer: WriterIdentity,
|
|
561
|
-
original:
|
|
566
|
+
original: InitialContextInput,
|
|
562
567
|
history: PromptHistory,
|
|
563
568
|
committed?: CommittedPromptSuffix,
|
|
564
569
|
) {
|
|
@@ -3083,7 +3083,9 @@ export const makeWorkerRuntime = Effect.fnUntraced(function* (options: WorkerRun
|
|
|
3083
3083
|
? "stopped"
|
|
3084
3084
|
: "stopping"
|
|
3085
3085
|
: control.active !== null
|
|
3086
|
-
?
|
|
3086
|
+
? control.active.state === "unknown"
|
|
3087
|
+
? "unknown"
|
|
3088
|
+
: "active"
|
|
3087
3089
|
: delivery !== undefined
|
|
3088
3090
|
? "starting"
|
|
3089
3091
|
: "idle"),
|
|
@@ -1,40 +1,14 @@
|
|
|
1
1
|
import type { Effect, Option } from "effect";
|
|
2
|
-
import type { Tool } from "effect/ai";
|
|
3
2
|
import * as Context from "effect/Context";
|
|
4
3
|
import * as Schema from "effect/Schema";
|
|
5
4
|
|
|
6
5
|
import { ToolCallId } from "../core/Identifiers.ts";
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* start and settlement is a free re-run; no prepared record is written.
|
|
14
|
-
* - `"idempotent"`: the handler declares an external idempotency contract
|
|
15
|
-
* (it owns key derivation). Prepared/settled records are written and
|
|
16
|
-
* recovery may re-execute without reconciliation proof.
|
|
17
|
-
* - `"uncertain"`: no external contract is declared. Prepared/settled records
|
|
18
|
-
* are written and recovery must reconcile or record an Unknown Outcome.
|
|
19
|
-
*/
|
|
20
|
-
export type ToolExecutionClassValue = "readonly" | "idempotent" | "uncertain";
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Effect AI Tool annotation key declaring a Tool's execution class, applied
|
|
24
|
-
* with `Tool.annotate(ToolExecutionClass, "...")`.
|
|
25
|
-
*
|
|
26
|
-
* Unannotated Tools default to `"uncertain"`: security and durability
|
|
27
|
-
* decisions are fail-closed, so the framework never infers a safer class
|
|
28
|
-
* from a Tool's shape.
|
|
29
|
-
*/
|
|
30
|
-
export const ToolExecutionClass = Context.Reference<ToolExecutionClassValue>(
|
|
31
|
-
"@effect-agent/engine/ToolExecutionClass",
|
|
32
|
-
{ defaultValue: () => "uncertain" },
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
/** Read a Tool's declared execution class, falling back to the fail-closed `"uncertain"` default. */
|
|
36
|
-
export const getToolExecutionClass = (tool: Tool.Any): ToolExecutionClassValue =>
|
|
37
|
-
Context.get(tool.annotations, ToolExecutionClass);
|
|
7
|
+
export {
|
|
8
|
+
ToolExecutionClass,
|
|
9
|
+
getToolExecutionClass,
|
|
10
|
+
type ToolExecutionClassValue,
|
|
11
|
+
} from "../core/internal/tool-execution.ts";
|
|
38
12
|
|
|
39
13
|
/** Stable identity of one Step within one Tool Call: `(toolCallId, stepName)`. */
|
|
40
14
|
export interface RunStepKey {
|
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
type TurnId,
|
|
72
72
|
} from "../../core/Identifiers.ts";
|
|
73
73
|
import { IdGenerator } from "../../core/IdGenerator.ts";
|
|
74
|
+
import { nativeUpdateId } from "../../core/internal/agent-updates.ts";
|
|
74
75
|
import { copyJson } from "../../core/internal/json.ts";
|
|
75
76
|
import { utf8ByteLength } from "../../core/internal/utf8.ts";
|
|
76
77
|
import { IdempotencyKey } from "../../core/Receipt.ts";
|
|
@@ -9126,7 +9127,7 @@ function executeWithCompletion<
|
|
|
9126
9127
|
);
|
|
9127
9128
|
|
|
9128
9129
|
const updateId = yield* Schema.decodeEffect(IdempotencyKey)(
|
|
9129
|
-
|
|
9130
|
+
nativeUpdateId(context.runId, call.toolCallId),
|
|
9130
9131
|
).pipe(Effect.mapError(() => UpdateError.make({ reason: "validation" })));
|
|
9131
9132
|
|
|
9132
9133
|
const emitter = yield* Emitter;
|