effect-agent 0.1.0-beta.124 → 0.1.0-beta.126
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/{Records-D88mgvyS.d.mts → Admin-C34cVKlT.d.mts} +2908 -3941
- package/dist/{AgentRuntime-BUxDdLpw.d.mts → AgentRuntime-DEDvMkAR.d.mts} +2 -2
- package/dist/Digest-U69rDHuO.d.mts +22 -0
- package/dist/{DurableAgentRuntime-B-9w7jDt.mjs → DurableAgentRuntime-BydyN_n-.mjs} +89 -15
- package/dist/DurableAgentRuntime-BydyN_n-.mjs.map +1 -0
- package/dist/{EventSource-CnlZ3Kma.d.mts → EventSource-Bac0SxKL.d.mts} +3 -3
- package/dist/{PreparedInputAdmission-BQLGldl-.d.mts → PreparedInputAdmission-DcQGQ0Yp.d.mts} +4 -4
- package/dist/Records-B5GFWCpn.d.mts +1104 -0
- package/dist/{Schedule-BIOHA6RR.d.mts → Schedule-CtYREFnz.d.mts} +2 -2
- package/dist/{Subagent-DCrB7an7.mjs → Subagent-DJeZDrbD.mjs} +6 -2
- package/dist/Subagent-DJeZDrbD.mjs.map +1 -0
- package/dist/{Subagent-CNik9RiA.d.mts → Subagent-DRFyQxdb.d.mts} +21 -4
- package/dist/{SubagentHost-4WB8Hj0C.d.mts → SubagentHost-DQjHFGqH.d.mts} +10 -2
- package/dist/{Subscription-CRteOKRf.d.mts → Subscription-Bk2Smmqc.d.mts} +34 -3
- package/dist/{SubscriptionInput-oNcwTPti.d.mts → SubscriptionInput-ekbJz3pF.d.mts} +3 -3
- package/dist/capabilities/Subagent.d.mts +1 -1
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/durable/ActivityStore.d.mts +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +3 -1
- package/dist/durable/Digest.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +1 -1
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/MessageDelivery.d.mts +82 -41
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +23 -1
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/Records.d.mts +2 -2
- package/dist/durable/Records.mjs +12 -2
- package/dist/durable/Records.mjs.map +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/Schedule.d.mts +1 -1
- package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
- package/dist/durable/ScheduleTransition.d.mts +1 -1
- package/dist/durable/Scheduling.d.mts +3 -2
- package/dist/durable/SqlStorageV2Upgrade.d.mts +2 -2
- package/dist/durable/SqlSubscriptionStore.d.mts +2 -2
- package/dist/durable/SqlThreadNativeReads.d.mts +2 -1
- package/dist/durable/SqlThreadNativeReads.mjs +1 -1
- package/dist/durable/SqlThreadNativeReads.mjs.map +1 -1
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +2 -1
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionTools.d.mts +4 -3
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/Subscriptions.d.mts +6 -5
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
- package/dist/durable/ThreadInvariants.d.mts +2 -1
- package/dist/durable/ThreadProjection.d.mts +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +10 -1
- package/dist/durable/ThreadStoreConformance.mjs.map +1 -1
- package/dist/durable/WorkerHost.d.mts +9 -2
- package/dist/durable/WorkerHost.mjs.map +1 -1
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/engine/SubagentHost.mjs.map +1 -1
- package/dist/index.d.mts +12 -10
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
- package/src/capabilities/internal/subagent-background.ts +37 -3
- package/src/durable/Records.ts +13 -1
- package/src/durable/SqlThreadNativeReads.ts +1 -1
- package/src/durable/ThreadStoreConformance.ts +28 -0
- package/src/durable/WorkerHost.ts +14 -2
- package/src/durable/internal/worker-host.ts +284 -9
- package/src/engine/SubagentHost.ts +9 -0
- package/dist/DurableAgentRuntime-B-9w7jDt.mjs.map +0 -1
- package/dist/Subagent-DCrB7an7.mjs.map +0 -1
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
WorkerInputRequested,
|
|
72
72
|
WorkerStopRequested,
|
|
73
73
|
WorkerOrigin,
|
|
74
|
+
WorkerContinuation,
|
|
74
75
|
WorkerOriginRecorded,
|
|
75
76
|
WorkerInputCompleted,
|
|
76
77
|
WorkerReportPrepared,
|
|
@@ -292,6 +293,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
292
293
|
origin: WorkerOrigin,
|
|
293
294
|
principal: Principal,
|
|
294
295
|
) {
|
|
296
|
+
yield* verifyContinuation(origin);
|
|
295
297
|
if (origin.budgetScope !== "worker-run") return;
|
|
296
298
|
// Independence changes accounting ownership, never delegation generations.
|
|
297
299
|
if (origin.depth !== 1) return yield* failure("start", "denied");
|
|
@@ -300,6 +302,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
300
302
|
source: origin.source,
|
|
301
303
|
principal,
|
|
302
304
|
worker: origin.worker,
|
|
305
|
+
...(origin.continuationOf === undefined ? {} : { continuationOf: origin.continuationOf }),
|
|
303
306
|
policy: origin.policy,
|
|
304
307
|
budget: origin.budget,
|
|
305
308
|
});
|
|
@@ -321,6 +324,170 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
321
324
|
);
|
|
322
325
|
});
|
|
323
326
|
|
|
327
|
+
const completedContinuation = Effect.fn("WorkerHost.completedContinuation")(function* (
|
|
328
|
+
source: WorkerContext["source"],
|
|
329
|
+
worker: WorkerRef,
|
|
330
|
+
targetAgentId: AgentId,
|
|
331
|
+
delegationId: WorkerRef["delegationId"],
|
|
332
|
+
expected?: WorkerContinuation,
|
|
333
|
+
) {
|
|
334
|
+
const selected = yield* decode(WorkerRef, worker, "start");
|
|
335
|
+
|
|
336
|
+
if (
|
|
337
|
+
selected.targetAgentId !== targetAgentId ||
|
|
338
|
+
selected.delegationId !== delegationId ||
|
|
339
|
+
selected.threadId === source.threadId ||
|
|
340
|
+
deps.ledger.inspectWorker === undefined
|
|
341
|
+
)
|
|
342
|
+
return yield* failure("start", "worker-mismatch");
|
|
343
|
+
const sourceState = yield* readWorkerState(source.threadId, "start");
|
|
344
|
+
|
|
345
|
+
if (
|
|
346
|
+
sourceState.records.some(
|
|
347
|
+
({ record }) =>
|
|
348
|
+
record.payload._tag === "WorkerStopRequested" &&
|
|
349
|
+
record.payload.command.worker.threadId === selected.threadId,
|
|
350
|
+
)
|
|
351
|
+
)
|
|
352
|
+
return yield* failure("start", "denied");
|
|
353
|
+
|
|
354
|
+
const first = sourceState.records.find(
|
|
355
|
+
({ record }) => record.recordId === firstWorkerInputRecordId(selected),
|
|
356
|
+
)?.record.payload;
|
|
357
|
+
|
|
358
|
+
const origin = first?._tag === "WorkerInputRequested" ? first.admission.origin : undefined;
|
|
359
|
+
|
|
360
|
+
if (
|
|
361
|
+
origin === undefined ||
|
|
362
|
+
origin.lifecycle !== "assignment" ||
|
|
363
|
+
!Schema.toEquivalence(WorkerRef)(origin.worker, selected) ||
|
|
364
|
+
origin.source.threadId !== source.threadId ||
|
|
365
|
+
origin.source.agentId !== source.agentId ||
|
|
366
|
+
first?._tag !== "WorkerInputRequested" ||
|
|
367
|
+
first.admission.messageId !== origin.firstMessageId
|
|
368
|
+
)
|
|
369
|
+
return yield* failure("start", "worker-mismatch");
|
|
370
|
+
|
|
371
|
+
const recorded = Option.getOrUndefined(
|
|
372
|
+
yield* exactRecord(selected.threadId, workerOriginRecordId(selected.threadId), "start"),
|
|
373
|
+
)?.record.payload;
|
|
374
|
+
|
|
375
|
+
if (recorded?._tag !== "WorkerOriginRecorded" || !sameOrigin(recorded.origin, origin))
|
|
376
|
+
return yield* failure("start", "worker-mismatch");
|
|
377
|
+
|
|
378
|
+
const control = yield* deps.ledger
|
|
379
|
+
.inspectWorker(selected.threadId)
|
|
380
|
+
.pipe(Effect.mapError(storageFailure("start")));
|
|
381
|
+
|
|
382
|
+
if (control.terminal !== "completed" || !control.stopped || control.active !== null)
|
|
383
|
+
return yield* failure("start", "denied");
|
|
384
|
+
|
|
385
|
+
const tail = yield* deps.store
|
|
386
|
+
.inspectTail(ThreadTailRequest.make({ threadId: selected.threadId }))
|
|
387
|
+
.pipe(Effect.mapError(storageFailure("start")));
|
|
388
|
+
|
|
389
|
+
const execution = yield* deps.store
|
|
390
|
+
.read({
|
|
391
|
+
threadId: selected.threadId,
|
|
392
|
+
selection: {
|
|
393
|
+
_tag: "WorkerExecution",
|
|
394
|
+
expectedTailSequence: tail.tailSequence,
|
|
395
|
+
expectedTailDigest: tail.tailDigest,
|
|
396
|
+
},
|
|
397
|
+
page: { limit: 2 },
|
|
398
|
+
})
|
|
399
|
+
.pipe(Stream.runCollect, Effect.mapError(storageFailure("start")));
|
|
400
|
+
|
|
401
|
+
const run = execution.find(({ record }) => record.payload._tag === "RunStarted")?.record
|
|
402
|
+
.payload;
|
|
403
|
+
|
|
404
|
+
if (run?._tag !== "RunStarted") return yield* failure("start", "corrupt");
|
|
405
|
+
|
|
406
|
+
const input = Option.getOrUndefined(
|
|
407
|
+
yield* getRunInput({ threadId: selected.threadId, runId: run.runId }).pipe(
|
|
408
|
+
Effect.provideService(ThreadStore, deps.store),
|
|
409
|
+
Effect.mapError(storageFailure("start")),
|
|
410
|
+
),
|
|
411
|
+
)?.record.payload;
|
|
412
|
+
|
|
413
|
+
if (input?._tag !== "UserInputRecorded" || input.submissionId === undefined)
|
|
414
|
+
return yield* failure("start", "corrupt");
|
|
415
|
+
|
|
416
|
+
const found = yield* deps.ledger
|
|
417
|
+
.lookup(SubmissionLookupById.make({ submissionId: input.submissionId }))
|
|
418
|
+
.pipe(Effect.mapError(storageFailure("start")));
|
|
419
|
+
|
|
420
|
+
const row = Option.getOrUndefined(found);
|
|
421
|
+
|
|
422
|
+
const settlement = Option.getOrUndefined(
|
|
423
|
+
yield* exactRecord(
|
|
424
|
+
selected.threadId,
|
|
425
|
+
submissionSettlementRecordId(input.submissionId),
|
|
426
|
+
"start",
|
|
427
|
+
),
|
|
428
|
+
)?.record.payload;
|
|
429
|
+
|
|
430
|
+
if (
|
|
431
|
+
row === undefined ||
|
|
432
|
+
row.threadId !== selected.threadId ||
|
|
433
|
+
row.state !== "settled" ||
|
|
434
|
+
row.settledOutcome !== "completed" ||
|
|
435
|
+
row.workerAdmission === undefined ||
|
|
436
|
+
!sameOrigin(row.workerAdmission.origin, origin) ||
|
|
437
|
+
settlement?._tag !== "SubmissionSettled" ||
|
|
438
|
+
settlement.outcome !== "completed" ||
|
|
439
|
+
settlement.runDisposition !== "completed" ||
|
|
440
|
+
settlement.finishReason !== undefined ||
|
|
441
|
+
settlement.runId !== run.runId ||
|
|
442
|
+
settlement.submissionId !== row.submissionId ||
|
|
443
|
+
settlement.receiptId !== row.receiptId
|
|
444
|
+
)
|
|
445
|
+
return yield* failure("start", "denied");
|
|
446
|
+
|
|
447
|
+
const evidence = WorkerContinuation.make({
|
|
448
|
+
worker: selected,
|
|
449
|
+
receipt: Receipt.make({
|
|
450
|
+
threadId: row.threadId,
|
|
451
|
+
submissionId: row.submissionId,
|
|
452
|
+
receiptId: row.receiptId,
|
|
453
|
+
queueSequence: row.queueSequence,
|
|
454
|
+
}),
|
|
455
|
+
settlementId: settlement.settlementId,
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
if (expected !== undefined && !Schema.toEquivalence(WorkerContinuation)(expected, evidence))
|
|
459
|
+
return yield* failure("start", "worker-mismatch");
|
|
460
|
+
|
|
461
|
+
return { evidence, origin };
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
const verifyContinuation = Effect.fn("WorkerHost.verifyContinuation")(function* (
|
|
465
|
+
origin: WorkerOrigin,
|
|
466
|
+
) {
|
|
467
|
+
if (origin.continuationOf === undefined) return;
|
|
468
|
+
|
|
469
|
+
const previous = yield* completedContinuation(
|
|
470
|
+
origin.source,
|
|
471
|
+
origin.continuationOf.worker,
|
|
472
|
+
origin.worker.targetAgentId,
|
|
473
|
+
origin.worker.delegationId,
|
|
474
|
+
origin.continuationOf,
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
if (
|
|
478
|
+
origin.worker.threadId === previous.origin.worker.threadId ||
|
|
479
|
+
origin.lifecycle !== "assignment" ||
|
|
480
|
+
!samePolicy(origin.policy, previous.origin.policy) ||
|
|
481
|
+
!Schema.toEquivalence(WorkerOrigin.fields.budget)(origin.budget, previous.origin.budget) ||
|
|
482
|
+
!Schema.toEquivalence(SubagentGrant)(origin.grant, previous.origin.grant) ||
|
|
483
|
+
origin.budgetScope !== previous.origin.budgetScope ||
|
|
484
|
+
origin.depth !== previous.origin.depth ||
|
|
485
|
+
origin.toolCallAllowance !== previous.origin.toolCallAllowance ||
|
|
486
|
+
origin.expiresAtMillis > previous.origin.expiresAtMillis
|
|
487
|
+
)
|
|
488
|
+
return yield* failure("start", "denied");
|
|
489
|
+
});
|
|
490
|
+
|
|
324
491
|
const readIdentity = Effect.fn("WorkerHost.readIdentity")(function* (
|
|
325
492
|
threadId: ThreadId,
|
|
326
493
|
operation: WorkerError["operation"],
|
|
@@ -885,6 +1052,8 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
885
1052
|
retainedFrameworkInput: boolean,
|
|
886
1053
|
): Effect.fn.Return<void, WorkerError> {
|
|
887
1054
|
const origin = admission.origin;
|
|
1055
|
+
|
|
1056
|
+
yield* verifyContinuation(origin);
|
|
888
1057
|
const id = workerInputRecordId(admission.messageId);
|
|
889
1058
|
|
|
890
1059
|
for (let attempt = 0; attempt < 16; attempt++) {
|
|
@@ -895,6 +1064,16 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
895
1064
|
);
|
|
896
1065
|
|
|
897
1066
|
const current = source.current;
|
|
1067
|
+
|
|
1068
|
+
if (
|
|
1069
|
+
origin.continuationOf !== undefined &&
|
|
1070
|
+
current.records.some(
|
|
1071
|
+
({ record }) =>
|
|
1072
|
+
record.payload._tag === "WorkerStopRequested" &&
|
|
1073
|
+
record.payload.command.worker.threadId === origin.continuationOf?.worker.threadId,
|
|
1074
|
+
)
|
|
1075
|
+
)
|
|
1076
|
+
return yield* failure("start", "denied");
|
|
898
1077
|
const rows = requests(current.records);
|
|
899
1078
|
const existing = current.records.find(({ record }) => record.recordId === id)?.record.payload;
|
|
900
1079
|
|
|
@@ -955,6 +1134,9 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
955
1134
|
? {
|
|
956
1135
|
...targetRequest,
|
|
957
1136
|
_tag: "InitialInput",
|
|
1137
|
+
...(origin.continuationOf === undefined
|
|
1138
|
+
? {}
|
|
1139
|
+
: { continuationOf: origin.continuationOf }),
|
|
958
1140
|
input,
|
|
959
1141
|
inputDigest,
|
|
960
1142
|
...(source.submission === undefined ? {} : { sourceSubmission: source.submission }),
|
|
@@ -1057,6 +1239,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1057
1239
|
const selectedConcurrency = yield* deps.concurrencyResolver.resolve({
|
|
1058
1240
|
source: origin.source,
|
|
1059
1241
|
worker: origin.worker,
|
|
1242
|
+
...(origin.continuationOf === undefined ? {} : { continuationOf: origin.continuationOf }),
|
|
1060
1243
|
principal,
|
|
1061
1244
|
...(source.submission === undefined ? {} : { sourceSubmission: source.submission }),
|
|
1062
1245
|
});
|
|
@@ -1168,6 +1351,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1168
1351
|
yield* validateCompletion(options.messageAdmission, options, agentId, inputDigest);
|
|
1169
1352
|
}
|
|
1170
1353
|
|
|
1354
|
+
yield* verifyContinuation(admission.origin);
|
|
1171
1355
|
yield* deps.authorizer.authorize({
|
|
1172
1356
|
sourceThreadId: admission.origin.source.threadId,
|
|
1173
1357
|
...(admission.sourceSubmissionId === undefined
|
|
@@ -1177,6 +1361,9 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1177
1361
|
operation: "start",
|
|
1178
1362
|
access: "send",
|
|
1179
1363
|
worker: admission.origin.worker,
|
|
1364
|
+
...(admission.origin.continuationOf === undefined
|
|
1365
|
+
? {}
|
|
1366
|
+
: { continuationOf: admission.origin.continuationOf }),
|
|
1180
1367
|
});
|
|
1181
1368
|
yield* authorizeBudget(admission.origin, options.principal);
|
|
1182
1369
|
if (
|
|
@@ -1247,6 +1434,8 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1247
1434
|
);
|
|
1248
1435
|
|
|
1249
1436
|
if (now >= deadlineAtMillis) return yield* failure("followUp", "denied");
|
|
1437
|
+
if (reports[0].reportUpdate !== undefined && !reports[0].reportUpdate(update))
|
|
1438
|
+
return undefined;
|
|
1250
1439
|
const input = destination.input;
|
|
1251
1440
|
|
|
1252
1441
|
let workerAdmission: WorkerAdmission | undefined;
|
|
@@ -1438,7 +1627,11 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1438
1627
|
},
|
|
1439
1628
|
};
|
|
1440
1629
|
|
|
1441
|
-
const projection = yield* Effect.suspend(() =>
|
|
1630
|
+
const projection = yield* Effect.suspend(() =>
|
|
1631
|
+
descriptor.reportCompletion?.(report) === false
|
|
1632
|
+
? Effect.succeed(undefined)
|
|
1633
|
+
: descriptor.prepare(report),
|
|
1634
|
+
).pipe(
|
|
1442
1635
|
Effect.timeout(
|
|
1443
1636
|
Math.min(deps.limits.reportPreparationTimeoutMillis ?? 5_000, deadlineAtMillis - now),
|
|
1444
1637
|
),
|
|
@@ -1455,6 +1648,8 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1455
1648
|
|
|
1456
1649
|
if (projection._tag === "WorkerReportRefused") return projection;
|
|
1457
1650
|
|
|
1651
|
+
if (projection.value === undefined) return refused("filtered");
|
|
1652
|
+
|
|
1458
1653
|
const message = projection.value.message;
|
|
1459
1654
|
|
|
1460
1655
|
if (!Schema.is(WorkerCompletion)(message)) return refused("input");
|
|
@@ -1676,6 +1871,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1676
1871
|
operation: WorkerError["operation"],
|
|
1677
1872
|
access: "context" | "read" | "send" | "control",
|
|
1678
1873
|
worker?: WorkerRef,
|
|
1874
|
+
continuationOf?: WorkerContinuation,
|
|
1679
1875
|
) =>
|
|
1680
1876
|
deps.authorizer.authorize({
|
|
1681
1877
|
sourceThreadId: context.source.threadId,
|
|
@@ -1684,6 +1880,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1684
1880
|
operation,
|
|
1685
1881
|
access,
|
|
1686
1882
|
...(worker === undefined ? {} : { worker }),
|
|
1883
|
+
...(continuationOf === undefined ? {} : { continuationOf }),
|
|
1687
1884
|
});
|
|
1688
1885
|
|
|
1689
1886
|
const binding = (target: Agent.AnyDefinition, operation: WorkerError["operation"]) =>
|
|
@@ -1697,6 +1894,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1697
1894
|
const preparedTarget = Effect.fn("WorkerHost.preparedTarget")(function* (
|
|
1698
1895
|
target: Agent.AnyDefinition,
|
|
1699
1896
|
encodedInput: unknown,
|
|
1897
|
+
continuationOf?: WorkerContinuation,
|
|
1700
1898
|
) {
|
|
1701
1899
|
const resolved = yield* binding(target, "start");
|
|
1702
1900
|
|
|
@@ -1713,6 +1911,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
1713
1911
|
|
|
1714
1912
|
const policy = yield* resolveTargetPolicy({
|
|
1715
1913
|
_tag: "InitialInput",
|
|
1914
|
+
...(continuationOf === undefined ? {} : { continuationOf }),
|
|
1716
1915
|
definition: resolved.definition,
|
|
1717
1916
|
definitions: resolved.digests,
|
|
1718
1917
|
source: context.source,
|
|
@@ -2185,14 +2384,35 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2185
2384
|
};
|
|
2186
2385
|
}),
|
|
2187
2386
|
resolveTargetPolicy: Effect.fn("WorkerHost.resolvePreparedTargetPolicy")(function* (request) {
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2387
|
+
const previous =
|
|
2388
|
+
request.continuationOf === undefined
|
|
2389
|
+
? undefined
|
|
2390
|
+
: yield* completedContinuation(
|
|
2391
|
+
context.source,
|
|
2392
|
+
request.continuationOf,
|
|
2393
|
+
request.target.id,
|
|
2394
|
+
request.continuationOf.delegationId,
|
|
2395
|
+
);
|
|
2396
|
+
|
|
2397
|
+
yield* authorize("start", "send", undefined, previous?.evidence);
|
|
2398
|
+
|
|
2399
|
+
return (yield* preparedTarget(request.target, request.encodedInput, previous?.evidence))
|
|
2400
|
+
.policy;
|
|
2191
2401
|
}),
|
|
2192
2402
|
start: Effect.fn("WorkerHost.start")(function* <E = never, R = never>(
|
|
2193
2403
|
command: StartWorkerRequest | DeferredStartWorkerRequest<E, R>,
|
|
2194
2404
|
): Effect.fn.Return<WorkerStarted, WorkerError | E, R> {
|
|
2195
|
-
const
|
|
2405
|
+
const previous =
|
|
2406
|
+
command.continuationOf === undefined
|
|
2407
|
+
? undefined
|
|
2408
|
+
: yield* completedContinuation(
|
|
2409
|
+
context.source,
|
|
2410
|
+
command.continuationOf,
|
|
2411
|
+
command.target.id,
|
|
2412
|
+
command.delegationId,
|
|
2413
|
+
);
|
|
2414
|
+
|
|
2415
|
+
const principal = yield* authorize("start", "send", undefined, previous?.evidence);
|
|
2196
2416
|
|
|
2197
2417
|
if (context.depth !== 0 && sourceSubmissionId === undefined)
|
|
2198
2418
|
return yield* failure("start", "denied");
|
|
@@ -2219,7 +2439,23 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2219
2439
|
|
|
2220
2440
|
const replay = (saved: MessageDeliveryRecord) =>
|
|
2221
2441
|
Effect.gen(function* () {
|
|
2222
|
-
const
|
|
2442
|
+
const currentPrevious =
|
|
2443
|
+
command.continuationOf === undefined
|
|
2444
|
+
? undefined
|
|
2445
|
+
: yield* completedContinuation(
|
|
2446
|
+
context.source,
|
|
2447
|
+
command.continuationOf,
|
|
2448
|
+
command.target.id,
|
|
2449
|
+
command.delegationId,
|
|
2450
|
+
previous?.evidence,
|
|
2451
|
+
);
|
|
2452
|
+
|
|
2453
|
+
const replayPrincipal = yield* authorize(
|
|
2454
|
+
"start",
|
|
2455
|
+
"send",
|
|
2456
|
+
undefined,
|
|
2457
|
+
currentPrevious?.evidence,
|
|
2458
|
+
);
|
|
2223
2459
|
|
|
2224
2460
|
yield* binding(command.target, "start");
|
|
2225
2461
|
const metadata = saved.envelope.workerAdmission;
|
|
@@ -2228,6 +2464,10 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2228
2464
|
const origin = metadata.origin;
|
|
2229
2465
|
|
|
2230
2466
|
if (
|
|
2467
|
+
!Schema.toEquivalence(Schema.UndefinedOr(WorkerContinuation))(
|
|
2468
|
+
origin.continuationOf,
|
|
2469
|
+
currentPrevious?.evidence,
|
|
2470
|
+
) ||
|
|
2231
2471
|
origin.firstMessageId !== messageId ||
|
|
2232
2472
|
metadata.messageId !== messageId ||
|
|
2233
2473
|
origin.source.threadId !== context.source.threadId ||
|
|
@@ -2247,6 +2487,8 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2247
2487
|
)
|
|
2248
2488
|
return yield* failure("start", "idempotency-conflict");
|
|
2249
2489
|
|
|
2490
|
+
yield* verifyContinuation(origin);
|
|
2491
|
+
|
|
2250
2492
|
return {
|
|
2251
2493
|
worker: origin.worker,
|
|
2252
2494
|
delivery: yield* send(
|
|
@@ -2268,7 +2510,34 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2268
2510
|
const request =
|
|
2269
2511
|
"prepare" in command ? { ...(yield* command.prepare), ...command } : command;
|
|
2270
2512
|
|
|
2271
|
-
const
|
|
2513
|
+
const currentPrevious =
|
|
2514
|
+
command.continuationOf === undefined
|
|
2515
|
+
? undefined
|
|
2516
|
+
: yield* completedContinuation(
|
|
2517
|
+
context.source,
|
|
2518
|
+
command.continuationOf,
|
|
2519
|
+
command.target.id,
|
|
2520
|
+
command.delegationId,
|
|
2521
|
+
previous?.evidence,
|
|
2522
|
+
);
|
|
2523
|
+
|
|
2524
|
+
if (currentPrevious !== undefined) {
|
|
2525
|
+
const preparedPrincipal = yield* authorize(
|
|
2526
|
+
"start",
|
|
2527
|
+
"send",
|
|
2528
|
+
undefined,
|
|
2529
|
+
currentPrevious.evidence,
|
|
2530
|
+
);
|
|
2531
|
+
|
|
2532
|
+
if (preparedPrincipal !== principal) return yield* failure("start", "denied");
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
const prepared = yield* preparedTarget(
|
|
2536
|
+
request.target,
|
|
2537
|
+
request.encodedInput,
|
|
2538
|
+
currentPrevious?.evidence,
|
|
2539
|
+
);
|
|
2540
|
+
|
|
2272
2541
|
const resolved = prepared.resolved;
|
|
2273
2542
|
|
|
2274
2543
|
const sourcePolicy = Option.getOrElse(
|
|
@@ -2302,6 +2571,9 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2302
2571
|
threadId: Schema.decodeSync(ThreadId)(messageId),
|
|
2303
2572
|
},
|
|
2304
2573
|
source: context.source,
|
|
2574
|
+
...(currentPrevious === undefined
|
|
2575
|
+
? {}
|
|
2576
|
+
: { continuationOf: currentPrevious.evidence }),
|
|
2305
2577
|
...(resolved.definition.runDisposition?.workerLifecycle === "assignment"
|
|
2306
2578
|
? { lifecycle: "assignment" }
|
|
2307
2579
|
: {}),
|
|
@@ -2313,7 +2585,10 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2313
2585
|
depth: context.depth + 1,
|
|
2314
2586
|
firstMessageId: messageId,
|
|
2315
2587
|
createdAtMillis: now,
|
|
2316
|
-
expiresAtMillis:
|
|
2588
|
+
expiresAtMillis: Math.min(
|
|
2589
|
+
now + deps.limits.lifetimeMillis,
|
|
2590
|
+
currentPrevious?.origin.expiresAtMillis ?? Infinity,
|
|
2591
|
+
),
|
|
2317
2592
|
...(reporting === undefined ? {} : { reporting }),
|
|
2318
2593
|
...(request.toolCallAllowance === undefined
|
|
2319
2594
|
? {}
|
|
@@ -2796,7 +3071,7 @@ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
|
|
|
2796
3071
|
...(sourceSubmissionId === undefined ? {} : { sourceSubmissionId }),
|
|
2797
3072
|
principal: options.principal,
|
|
2798
3073
|
operation: "followUp",
|
|
2799
|
-
access: "
|
|
3074
|
+
access: "report",
|
|
2800
3075
|
worker: receiving?.origin.worker ?? origin.worker,
|
|
2801
3076
|
});
|
|
2802
3077
|
|
|
@@ -3,6 +3,7 @@ import { Context, Schema, Stream } from "effect";
|
|
|
3
3
|
|
|
4
4
|
import type * as Agent from "../core/Agent.ts";
|
|
5
5
|
import type { AgentPolicy } from "../core/AgentPolicy.ts";
|
|
6
|
+
import type { Update } from "../core/AgentUpdates.ts";
|
|
6
7
|
import type * as FailureDiagnostic from "../core/FailureDiagnostic.ts";
|
|
7
8
|
import type { DelegationId, RunId, SettlementId, ThreadId } from "../core/Identifiers.ts";
|
|
8
9
|
import type { MessageRef, MessageStatus } from "../core/Messaging.ts";
|
|
@@ -26,6 +27,8 @@ import {
|
|
|
26
27
|
/** Prepared values cross this port only to be Schema-decoded before durable storage. */
|
|
27
28
|
export interface StartWorkerRequest {
|
|
28
29
|
readonly delegationId: DelegationId;
|
|
30
|
+
/** Start a distinct assignment using verified completed predecessor authority. */
|
|
31
|
+
readonly continuationOf?: WorkerRef;
|
|
29
32
|
readonly target: Agent.AnyDefinition;
|
|
30
33
|
readonly idempotencyKey: IdempotencyKey;
|
|
31
34
|
readonly encodedInput: unknown;
|
|
@@ -49,6 +52,7 @@ export interface StartWorkerRequest {
|
|
|
49
52
|
export interface DeferredStartWorkerRequest<E = never, R = never> extends Pick<
|
|
50
53
|
StartWorkerRequest,
|
|
51
54
|
| "delegationId"
|
|
55
|
+
| "continuationOf"
|
|
52
56
|
| "target"
|
|
53
57
|
| "idempotencyKey"
|
|
54
58
|
| "encodedParameters"
|
|
@@ -137,6 +141,10 @@ export class WorkerReportPreparationFailure extends Schema.TaggedError<WorkerRep
|
|
|
137
141
|
export interface WorkerReporting<E = never, R = never> {
|
|
138
142
|
readonly delegationId: DelegationId;
|
|
139
143
|
readonly target: Agent.AnyDefinition;
|
|
144
|
+
/** Pure first-emission selection. False retains the canonical update without parent delivery. */
|
|
145
|
+
readonly reportUpdate?: (update: Update) => boolean;
|
|
146
|
+
/** False retains a filtered report receipt without waking the parent. */
|
|
147
|
+
readonly reportCompletion?: (report: WorkerRunReport) => boolean;
|
|
140
148
|
readonly prepare: (report: WorkerRunReport) => Effect.Effect<
|
|
141
149
|
{
|
|
142
150
|
readonly message: WorkerCompletion;
|
|
@@ -162,6 +170,7 @@ export class SubagentHost extends Context.Service<
|
|
|
162
170
|
readonly context: Effect.Effect<WorkerContext, WorkerError>;
|
|
163
171
|
/** Resolve prepared input through host authority; None retains legacy target inheritance. */
|
|
164
172
|
readonly resolveTargetPolicy: (request: {
|
|
173
|
+
readonly continuationOf?: WorkerRef;
|
|
165
174
|
readonly target: Agent.AnyDefinition;
|
|
166
175
|
readonly encodedInput: unknown;
|
|
167
176
|
}) => Effect.Effect<Option.Option<AgentPolicy>, WorkerError>;
|