effect-agent 0.1.0-beta.156 → 0.1.0-beta.158
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-BjmupLN3.d.mts → Admin-BbTZHSLu.d.mts} +23 -11
- package/dist/{Agent-1DMSO_Fl.mjs → Agent-BMATXYsI.mjs} +9 -2
- package/dist/Agent-BMATXYsI.mjs.map +1 -0
- package/dist/{AgentRuntime-BAjT5gXl.d.mts → AgentRuntime-BPlAn5nA.d.mts} +6 -6
- package/dist/{AgentRuntime-IF_1GoUf.mjs → AgentRuntime-D4eoBpIW.mjs} +32 -10
- package/dist/AgentRuntime-D4eoBpIW.mjs.map +1 -0
- package/dist/{Digest-CaJ2RIsF.d.mts → Digest-CNHImGy0.d.mts} +2 -2
- package/dist/{DurableAgentRuntime-BQzYkFVy.mjs → DurableAgentRuntime-eImXoGqD.mjs} +78 -27
- package/dist/DurableAgentRuntime-eImXoGqD.mjs.map +1 -0
- package/dist/{EventSource-C8CKwQy5.d.mts → EventSource-CETtQTiH.d.mts} +3 -3
- package/dist/InMemory.d.mts +1 -1
- package/dist/{PreparedInputAdmission-CU1PzUVD.d.mts → PreparedInputAdmission-Swp9t800.d.mts} +4 -4
- package/dist/{Records-BrEpibum.d.mts → Records-BxGWRs-t.d.mts} +2 -2
- package/dist/{RunEvent-DV_llBcq.d.mts → RunEvent-D0aepYwN.d.mts} +2 -2
- package/dist/{RunEventSink-D5aVhISG.d.mts → RunEventSink-DsbcGXog.d.mts} +2 -2
- package/dist/{RunOptions-CkRYnlJa.d.mts → RunOptions-GjDlAuKh.d.mts} +5 -2
- package/dist/{Schedule-B_z7PMg-.d.mts → Schedule-B94iS2X3.d.mts} +2 -2
- package/dist/{Subagent-CmFtZaeI.mjs → Subagent-211Oz2IN.mjs} +2 -2
- package/dist/{Subagent-CmFtZaeI.mjs.map → Subagent-211Oz2IN.mjs.map} +1 -1
- package/dist/{Subagent-Dld4W1BY.d.mts → Subagent-CLaMeZKu.d.mts} +6 -6
- package/dist/{Subscription-BomcQ9_W.d.mts → Subscription-DaMCppa_.d.mts} +4 -4
- package/dist/{SubscriptionInput-gpZSR9vB.d.mts → SubscriptionInput-B0ZtrQoY.d.mts} +3 -3
- package/dist/{ThreadHistory-ZEu_ja6L.d.mts → ThreadHistory-FD-o4TsR.d.mts} +2 -2
- package/dist/{Usage-Dx0aknfk.d.mts → Usage-BNjPR7Zr.d.mts} +9 -1
- package/dist/{WorkerAdmission-CNbm4o_x.mjs → WorkerAdmission-N9hZV85Q.mjs} +2 -2
- package/dist/{WorkerAdmission-CNbm4o_x.mjs.map → WorkerAdmission-N9hZV85Q.mjs.map} +1 -1
- package/dist/{agent-registration-U3kmV7nW.mjs → agent-registration-BIOzAej4.mjs} +10 -1
- package/dist/agent-registration-BIOzAej4.mjs.map +1 -0
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/Redaction.d.mts +1 -1
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/Subagent.d.mts +1 -1
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/capabilities/ToolDiscovery.d.mts +5 -0
- package/dist/capabilities/ToolDiscovery.mjs +18 -9
- package/dist/capabilities/ToolDiscovery.mjs.map +1 -1
- package/dist/capabilities/WebSearch.d.mts +5 -1
- package/dist/capabilities/WebSearch.mjs +9 -1
- package/dist/capabilities/WebSearch.mjs.map +1 -1
- package/dist/core/Agent.mjs +1 -1
- package/dist/core/RunEvent.d.mts +1 -1
- package/dist/core/Usage.d.mts +1 -1
- package/dist/core/Usage.mjs +22 -1
- package/dist/core/Usage.mjs.map +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/AgentRegistration.mjs +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +3 -3
- package/dist/durable/Digest.d.mts +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/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/LifecyclePublication.mjs +2 -2
- package/dist/durable/LifecyclePublication.mjs.map +1 -1
- package/dist/durable/MessageDelivery.d.mts +24 -10
- package/dist/durable/MessageDelivery.mjs +49 -17
- package/dist/durable/MessageDelivery.mjs.map +1 -1
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +5 -5
- package/dist/durable/PersistentHistory.d.mts +2 -2
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/Records.d.mts +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 -3
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +2 -2
- 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/SubscriptionInput.mjs +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionTools.d.mts +4 -4
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/Subscriptions.d.mts +6 -6
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
- package/dist/durable/ThreadInvariants.d.mts +2 -2
- 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/WorkerAdmission.d.mts +2 -2
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +2 -2
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/RunEventSink.d.mts +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/RunOptions.mjs +1 -0
- package/dist/engine/RunOptions.mjs.map +1 -1
- package/dist/engine/ThreadHistory.d.mts +1 -1
- package/dist/index.d.mts +15 -15
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
- package/src/capabilities/ToolDiscovery.ts +24 -10
- package/src/capabilities/WebSearch.ts +15 -0
- package/src/core/Agent.ts +16 -2
- package/src/core/Usage.ts +41 -0
- package/src/durable/DurableAgentRuntime.ts +119 -21
- package/src/durable/LifecyclePublication.ts +15 -2
- package/src/durable/MessageDelivery.ts +64 -20
- package/src/durable/internal/agent-registration.ts +11 -0
- package/src/engine/RunOptions.ts +3 -0
- package/src/engine/internal/agent-runtime.ts +91 -20
- package/dist/Agent-1DMSO_Fl.mjs.map +0 -1
- package/dist/AgentRuntime-IF_1GoUf.mjs.map +0 -1
- package/dist/DurableAgentRuntime-BQzYkFVy.mjs.map +0 -1
- package/dist/agent-registration-U3kmV7nW.mjs.map +0 -1
|
@@ -167,6 +167,7 @@ import { makeMessagingRuntime } from "./internal/messaging-host.ts";
|
|
|
167
167
|
import * as ThreadInitialization from "./internal/thread-initialization.ts";
|
|
168
168
|
import { makeWorkerRuntime, WorkerInputControl } from "./internal/worker-host.ts";
|
|
169
169
|
import { WorkerRuntime } from "./internal/worker-runtime.ts";
|
|
170
|
+
import { MessageDeliveryStore } from "./MessageDelivery.ts";
|
|
170
171
|
import {
|
|
171
172
|
OperationAuthorizationRequest,
|
|
172
173
|
OperationAuthorizer,
|
|
@@ -1266,6 +1267,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
1266
1267
|
const ledger = yield* SubmissionLedger;
|
|
1267
1268
|
const submissionScheduling = yield* SubmissionScheduling;
|
|
1268
1269
|
const store = yield* ThreadStore;
|
|
1270
|
+
const deliveries = yield* Effect.serviceOption(MessageDeliveryStore);
|
|
1269
1271
|
|
|
1270
1272
|
// Disposable: canonical tail and owner identify the exact projection, never ownership.
|
|
1271
1273
|
// Retain only the most recent view; persisted checkpoints still govern cold recovery.
|
|
@@ -3112,7 +3114,75 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3112
3114
|
*/
|
|
3113
3115
|
const notifyParentOfChildSettlement = Effect.fn(
|
|
3114
3116
|
"DurableAgentRuntime.notifyParentOfChildSettlement",
|
|
3115
|
-
)(function* (
|
|
3117
|
+
)(function* (
|
|
3118
|
+
submission: SubmissionSnapshot,
|
|
3119
|
+
record: RecordEnvelope,
|
|
3120
|
+
): Effect.fn.Return<void, LedgerError> {
|
|
3121
|
+
const admission = submission.messageAdmission;
|
|
3122
|
+
const worker = submission.workerAdmission;
|
|
3123
|
+
|
|
3124
|
+
const key =
|
|
3125
|
+
admission === undefined
|
|
3126
|
+
? worker === undefined
|
|
3127
|
+
? undefined
|
|
3128
|
+
: {
|
|
3129
|
+
ownerThreadId: worker.origin.source.threadId,
|
|
3130
|
+
messageId: worker.messageId,
|
|
3131
|
+
}
|
|
3132
|
+
: Schema.is(MessageAdmission)(admission)
|
|
3133
|
+
? admission.message
|
|
3134
|
+
: {
|
|
3135
|
+
ownerThreadId:
|
|
3136
|
+
admission._tag === "WorkerCompletion"
|
|
3137
|
+
? admission.report.worker.threadId
|
|
3138
|
+
: admission.worker.threadId,
|
|
3139
|
+
messageId: submission.idempotencyKey,
|
|
3140
|
+
};
|
|
3141
|
+
|
|
3142
|
+
// Commit the destination's exact canonical acknowledgement at the source before
|
|
3143
|
+
// making the ledger terminal. A failed/lost response is replayed during recovery.
|
|
3144
|
+
if (key !== undefined && Option.isSome(deliveries)) {
|
|
3145
|
+
const settled = yield* settlementPayloadFromRecord(record, submission.submissionId);
|
|
3146
|
+
|
|
3147
|
+
yield* deliveries.value
|
|
3148
|
+
.change(key, {
|
|
3149
|
+
_tag: "Complete",
|
|
3150
|
+
nowMillis: yield* Clock.currentTimeMillis,
|
|
3151
|
+
admissionKey: submission.idempotencyKey,
|
|
3152
|
+
inputDigest: submission.inputDigest,
|
|
3153
|
+
receipt: Receipt.make({
|
|
3154
|
+
threadId: submission.threadId,
|
|
3155
|
+
submissionId: submission.submissionId,
|
|
3156
|
+
receiptId: submission.receiptId,
|
|
3157
|
+
queueSequence: submission.queueSequence,
|
|
3158
|
+
}),
|
|
3159
|
+
settlement: Settlement.make({
|
|
3160
|
+
submissionId: settled.submissionId,
|
|
3161
|
+
receiptId: settled.receiptId,
|
|
3162
|
+
settlementId: settled.settlementId,
|
|
3163
|
+
outcome: settled.outcome,
|
|
3164
|
+
settledAt: record.createdAt,
|
|
3165
|
+
...(settled.outcome === "failed" ? { failure: settled.result } : {}),
|
|
3166
|
+
...(settled.usageSummary === undefined ? {} : { usageSummary: settled.usageSummary }),
|
|
3167
|
+
...(settled.runDisposition === undefined
|
|
3168
|
+
? {}
|
|
3169
|
+
: { runDisposition: settled.runDisposition }),
|
|
3170
|
+
}),
|
|
3171
|
+
})
|
|
3172
|
+
.pipe(
|
|
3173
|
+
Effect.catchCause((cause) =>
|
|
3174
|
+
Effect.failCause(
|
|
3175
|
+
Cause.map(cause, (error) =>
|
|
3176
|
+
LedgerError.make({
|
|
3177
|
+
operation: "delivery-completion",
|
|
3178
|
+
message: "Destination acknowledgement remains pending",
|
|
3179
|
+
cause: error,
|
|
3180
|
+
}),
|
|
3181
|
+
),
|
|
3182
|
+
),
|
|
3183
|
+
),
|
|
3184
|
+
);
|
|
3185
|
+
}
|
|
3116
3186
|
if (submission.workerAdmission?.origin.reporting?.mode === "standard")
|
|
3117
3187
|
yield* updateRuntime.repair(submission.threadId).pipe(
|
|
3118
3188
|
Effect.mapError(() =>
|
|
@@ -3227,14 +3297,14 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3227
3297
|
Effect.asVoid,
|
|
3228
3298
|
);
|
|
3229
3299
|
yield* hit("terminalize:after-canonical-append");
|
|
3230
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3300
|
+
yield* notifyParentOfChildSettlement(submission, record);
|
|
3231
3301
|
|
|
3232
3302
|
const settlement = yield* ledger.finalizeSettlement(
|
|
3233
3303
|
SettlementFinalization.make({ submissionId, settlementId }),
|
|
3234
3304
|
);
|
|
3235
3305
|
|
|
3236
3306
|
yield* wake.notify(submission.threadId);
|
|
3237
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3307
|
+
yield* notifyParentOfChildSettlement(submission, record);
|
|
3238
3308
|
|
|
3239
3309
|
return settlement;
|
|
3240
3310
|
});
|
|
@@ -3349,7 +3419,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3349
3419
|
Effect.asVoid,
|
|
3350
3420
|
);
|
|
3351
3421
|
yield* hit("terminalize:after-canonical-append");
|
|
3352
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3422
|
+
yield* notifyParentOfChildSettlement(submission, reserved.record);
|
|
3353
3423
|
|
|
3354
3424
|
const settlement = yield* ledger.finalizeSettlement(
|
|
3355
3425
|
SettlementFinalization.make({ submissionId, settlementId }),
|
|
@@ -3358,7 +3428,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3358
3428
|
const canonicalSettlement = yield* settlementPayloadFromRecord(reserved.record, submissionId);
|
|
3359
3429
|
|
|
3360
3430
|
yield* wake.notify(submission.threadId);
|
|
3361
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3431
|
+
yield* notifyParentOfChildSettlement(submission, reserved.record);
|
|
3362
3432
|
yield* settleJoinedSubmissions(ctx, canonicalSettlement);
|
|
3363
3433
|
|
|
3364
3434
|
return materializeSettlement(settlement, reserved.record);
|
|
@@ -3385,7 +3455,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3385
3455
|
);
|
|
3386
3456
|
yield* hit("terminalize:after-canonical-append");
|
|
3387
3457
|
}
|
|
3388
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3458
|
+
yield* notifyParentOfChildSettlement(submission, reservation.record);
|
|
3389
3459
|
|
|
3390
3460
|
const settlement = yield* ledger.finalizeSettlement(
|
|
3391
3461
|
SettlementFinalization.make({
|
|
@@ -3400,7 +3470,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3400
3470
|
);
|
|
3401
3471
|
|
|
3402
3472
|
yield* wake.notify(submission.threadId);
|
|
3403
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3473
|
+
yield* notifyParentOfChildSettlement(submission, reservation.record);
|
|
3404
3474
|
yield* settleJoinedSubmissions(ctx, canonicalSettlement);
|
|
3405
3475
|
|
|
3406
3476
|
return materializeSettlement(settlement, reservation.record);
|
|
@@ -3413,7 +3483,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3413
3483
|
): Effect.fn.Return<Settlement, LedgerError | SettlementConflict> {
|
|
3414
3484
|
const canonicalSettlement = yield* settlementPayloadFromRecord(record, submission.submissionId);
|
|
3415
3485
|
|
|
3416
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3486
|
+
yield* notifyParentOfChildSettlement(submission, record);
|
|
3417
3487
|
|
|
3418
3488
|
const settlement = yield* ledger.finalizeSettlement(
|
|
3419
3489
|
SettlementFinalization.make({
|
|
@@ -3427,7 +3497,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
3427
3497
|
);
|
|
3428
3498
|
|
|
3429
3499
|
yield* wake.notify(submission.threadId);
|
|
3430
|
-
yield* notifyParentOfChildSettlement(submission);
|
|
3500
|
+
yield* notifyParentOfChildSettlement(submission, record);
|
|
3431
3501
|
|
|
3432
3502
|
return materializeSettlement(settlement, snapshot.reservation?.record);
|
|
3433
3503
|
});
|
|
@@ -4559,6 +4629,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
4559
4629
|
ctx: AttemptAppendContext,
|
|
4560
4630
|
submission: SubmissionSnapshot,
|
|
4561
4631
|
tokenRef: Ref.Ref<OwnershipToken>,
|
|
4632
|
+
renewAtRef: Ref.Ref<number>,
|
|
4562
4633
|
records: ReadonlyArray<CanonicalRecordEnvelope>,
|
|
4563
4634
|
canonical: Stream.Stream<CanonicalRecordEnvelope, ThreadStoreError | ThreadNotMaterialized>,
|
|
4564
4635
|
canonicalThrough: CanonicalSequence,
|
|
@@ -5258,6 +5329,9 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
5258
5329
|
);
|
|
5259
5330
|
|
|
5260
5331
|
return RunUsageSummary.make({
|
|
5332
|
+
...(legacyCalls === 0 && detailed.webSearchCalls !== undefined
|
|
5333
|
+
? { webSearchCalls: detailed.webSearchCalls }
|
|
5334
|
+
: {}),
|
|
5261
5335
|
modelCalls,
|
|
5262
5336
|
inputTokens: InputTokenUsage.make({
|
|
5263
5337
|
total: inputTokens,
|
|
@@ -7798,18 +7872,33 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
7798
7872
|
// Liveness only: the lease keeps the claim visible; correctness stays with the epoch fence.
|
|
7799
7873
|
// OwnershipLost ends the race and interrupts the Run fiber cleanly.
|
|
7800
7874
|
const renewal = halt(
|
|
7801
|
-
Effect.
|
|
7802
|
-
|
|
7803
|
-
|
|
7875
|
+
Effect.gen(function* () {
|
|
7876
|
+
// Binding selection and preparation consume the acquired lease too. Carry the next
|
|
7877
|
+
// deadline across model continuations; an overdue first renewal must run immediately.
|
|
7878
|
+
const renewAt = yield* Ref.get(renewAtRef);
|
|
7879
|
+
const now = yield* Clock.currentTimeMillis;
|
|
7804
7880
|
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
)
|
|
7881
|
+
yield* Effect.sleep(Math.max(0, renewAt - now));
|
|
7882
|
+
yield* Effect.repeat(
|
|
7883
|
+
Effect.gen(function* () {
|
|
7884
|
+
const ownershipToken = yield* Ref.get(tokenRef);
|
|
7885
|
+
const renewingAt = yield* Clock.currentTimeMillis;
|
|
7808
7886
|
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7887
|
+
const renewal = yield* ledger.renewOwnership(
|
|
7888
|
+
RenewOwnershipRequest.make({ submissionId, ownershipToken }),
|
|
7889
|
+
);
|
|
7890
|
+
|
|
7891
|
+
yield* Ref.set(tokenRef, renewal.ownershipToken);
|
|
7892
|
+
yield* Ref.set(
|
|
7893
|
+
renewAtRef,
|
|
7894
|
+
renewingAt + Duration.toMillis(config.leaseRenewalInterval),
|
|
7895
|
+
);
|
|
7896
|
+
}).pipe(Effect.uninterruptible),
|
|
7897
|
+
{ schedule: Schedule.spaced(config.leaseRenewalInterval) },
|
|
7898
|
+
);
|
|
7899
|
+
|
|
7900
|
+
return yield* Effect.never;
|
|
7901
|
+
}),
|
|
7813
7902
|
);
|
|
7814
7903
|
|
|
7815
7904
|
const execution = Effect.raceFirst(consume, Effect.raceFirst(abortWatcher, renewal));
|
|
@@ -8031,6 +8120,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8031
8120
|
threadId: ThreadId,
|
|
8032
8121
|
claim: Claim,
|
|
8033
8122
|
tokenRef: Ref.Ref<OwnershipToken>,
|
|
8123
|
+
renewAtRef: Ref.Ref<number>,
|
|
8034
8124
|
resumeAfterRetention: () => void,
|
|
8035
8125
|
onHandoff: (nextSubmissionId: SubmissionId) => void,
|
|
8036
8126
|
yieldAfter?: DateTime.Utc,
|
|
@@ -8467,6 +8557,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8467
8557
|
ctx,
|
|
8468
8558
|
submission,
|
|
8469
8559
|
tokenRef,
|
|
8560
|
+
renewAtRef,
|
|
8470
8561
|
currentRecords,
|
|
8471
8562
|
canonical,
|
|
8472
8563
|
tail.tailSequence,
|
|
@@ -8647,6 +8738,8 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8647
8738
|
threadId: ThreadId,
|
|
8648
8739
|
handoff?: ClaimHandoff,
|
|
8649
8740
|
) {
|
|
8741
|
+
const acquiringAt = yield* Clock.currentTimeMillis;
|
|
8742
|
+
|
|
8650
8743
|
const claimed = yield* ledger.claim(
|
|
8651
8744
|
ClaimRequest.make({
|
|
8652
8745
|
threadId,
|
|
@@ -8659,6 +8752,10 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8659
8752
|
const claim = claimed.value;
|
|
8660
8753
|
const tokenRef = yield* Ref.make(claim.ownershipToken);
|
|
8661
8754
|
|
|
8755
|
+
const renewAtRef = yield* Ref.make(
|
|
8756
|
+
acquiringAt + Duration.toMillis(config.leaseRenewalInterval),
|
|
8757
|
+
);
|
|
8758
|
+
|
|
8662
8759
|
yield* Effect.addFinalizer(() =>
|
|
8663
8760
|
Ref.get(tokenRef).pipe(
|
|
8664
8761
|
Effect.flatMap((ownershipToken) =>
|
|
@@ -8681,7 +8778,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8681
8778
|
message: "The submission adapter did not honor the requested handoff",
|
|
8682
8779
|
});
|
|
8683
8780
|
|
|
8684
|
-
return Option.some({ claim, tokenRef });
|
|
8781
|
+
return Option.some({ claim, tokenRef, renewAtRef });
|
|
8685
8782
|
}, Effect.uninterruptible);
|
|
8686
8783
|
|
|
8687
8784
|
const processThreadHead = (
|
|
@@ -8701,7 +8798,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8701
8798
|
const claimed = yield* acquireClaim(threadId, handoff);
|
|
8702
8799
|
|
|
8703
8800
|
if (Option.isNone(claimed)) return Option.none();
|
|
8704
|
-
const { claim, tokenRef } = claimed.value;
|
|
8801
|
+
const { claim, tokenRef, renewAtRef } = claimed.value;
|
|
8705
8802
|
|
|
8706
8803
|
const attributes = {
|
|
8707
8804
|
threadId,
|
|
@@ -8781,6 +8878,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8781
8878
|
attemptThreadId,
|
|
8782
8879
|
attemptClaim,
|
|
8783
8880
|
tokenRef,
|
|
8881
|
+
renewAtRef,
|
|
8784
8882
|
() => {
|
|
8785
8883
|
resumeAfterRetention = true;
|
|
8786
8884
|
},
|
|
@@ -146,10 +146,13 @@ export type LifecyclePublicationBatch = typeof LifecyclePublicationBatch.Type;
|
|
|
146
146
|
|
|
147
147
|
/** Native recovery state, independent of Attempts. Hosts serialize drains per storage owner. */
|
|
148
148
|
export interface LifecyclePublicationStorage {
|
|
149
|
-
/** Select up to `limit` due owners, with a bounded pending prefix for each selected owner.
|
|
149
|
+
/** Select up to `limit` due owners, with a bounded pending prefix for each selected owner.
|
|
150
|
+
* `retainedOnly` excludes unmaterialized source facts, for a precommitted start prefix.
|
|
151
|
+
*/
|
|
150
152
|
readonly pending: (
|
|
151
153
|
nowMillis: number,
|
|
152
154
|
limit: number,
|
|
155
|
+
options?: { readonly retainedOnly?: boolean },
|
|
153
156
|
) => Effect.Effect<ReadonlyArray<LifecyclePublicationBatch>, LifecyclePublicationError>;
|
|
154
157
|
/** Atomically acknowledge the exact batch, retaining its identities and fingerprints. */
|
|
155
158
|
readonly acknowledge: (
|
|
@@ -166,6 +169,15 @@ export interface LifecyclePublicationStorage {
|
|
|
166
169
|
timeoutMillis: number,
|
|
167
170
|
) => Effect.Effect<boolean, LifecyclePublicationError>;
|
|
168
171
|
readonly pendingDeadline: Effect.Effect<Option.Option<number>, LifecyclePublicationError>;
|
|
172
|
+
/**
|
|
173
|
+
* Deadline for `pending(..., { retainedOnly: true })`, excluding unmaterialized source facts.
|
|
174
|
+
* Source-backed stores provide this when `pendingDeadline` also includes source intent.
|
|
175
|
+
* Otherwise `pendingDeadline` already describes retained work.
|
|
176
|
+
*/
|
|
177
|
+
readonly retainedPendingDeadline?: Effect.Effect<
|
|
178
|
+
Option.Option<number>,
|
|
179
|
+
LifecyclePublicationError
|
|
180
|
+
>;
|
|
169
181
|
/** Explicit operator retry after repairing a parked owner's destination. */
|
|
170
182
|
readonly retryParked: (
|
|
171
183
|
ownerThreadId: ThreadId,
|
|
@@ -259,9 +271,10 @@ export const drainLifecyclePublications = Effect.fn("LifecyclePublication.drain"
|
|
|
259
271
|
storage: LifecyclePublicationStorage,
|
|
260
272
|
timeoutMillis = 10_000,
|
|
261
273
|
limit = 4,
|
|
274
|
+
options?: { readonly retainedOnly?: boolean },
|
|
262
275
|
) {
|
|
263
276
|
const handler = yield* LifecyclePublicationHandler;
|
|
264
|
-
const pending = yield* storage.pending(yield* Clock.currentTimeMillis, limit);
|
|
277
|
+
const pending = yield* storage.pending(yield* Clock.currentTimeMillis, limit, options);
|
|
265
278
|
|
|
266
279
|
let failures: Cause.Cause<LifecyclePublicationError> = Cause.empty;
|
|
267
280
|
|
|
@@ -14,6 +14,8 @@ import { PreparedInput } from "./Subscription.ts";
|
|
|
14
14
|
|
|
15
15
|
const Positive = Schema.Int.check(Schema.isGreaterThan(0));
|
|
16
16
|
const BoundedName = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256));
|
|
17
|
+
const receiptsEqual = Schema.toEquivalence(Receipt);
|
|
18
|
+
const settlementsEqual = Schema.toEquivalence(Settlement);
|
|
17
19
|
|
|
18
20
|
/** An owner is always a source Thread. Destination admission has its own frozen key. */
|
|
19
21
|
export const MessageDeliveryKey = Schema.Struct({
|
|
@@ -66,7 +68,12 @@ export const defaultMessageDeliveryStoreLimits: MessageDeliveryStoreLimits = {
|
|
|
66
68
|
maxRetainedUpdatesPerOwner: 256,
|
|
67
69
|
};
|
|
68
70
|
|
|
69
|
-
const ParkReason = Schema.Literals([
|
|
71
|
+
const ParkReason = Schema.Literals([
|
|
72
|
+
"exhausted",
|
|
73
|
+
"deadline",
|
|
74
|
+
"status-unavailable",
|
|
75
|
+
"awaiting-settlement",
|
|
76
|
+
]);
|
|
70
77
|
|
|
71
78
|
export const MessageDeliveryRecord = Schema.Struct({
|
|
72
79
|
schemaVersion: Schema.Literal(1),
|
|
@@ -152,7 +159,20 @@ export const MessageDeliveryFailpoint = Context.Reference<{
|
|
|
152
159
|
|
|
153
160
|
const fence = { expectedVersion: Positive, nowMillis: ScheduleInstant };
|
|
154
161
|
|
|
162
|
+
/** Terminal destination evidence, independent of an expiring source transport claim. */
|
|
163
|
+
export const MessageDeliveryCompletion = Schema.Struct({
|
|
164
|
+
receipt: Receipt,
|
|
165
|
+
settlement: Settlement,
|
|
166
|
+
admissionKey: IdempotencyKey,
|
|
167
|
+
inputDigest: Digest,
|
|
168
|
+
});
|
|
169
|
+
|
|
155
170
|
export const MessageDeliveryChange = Schema.Union([
|
|
171
|
+
Schema.Struct({
|
|
172
|
+
_tag: Schema.Literal("Complete"),
|
|
173
|
+
nowMillis: ScheduleInstant,
|
|
174
|
+
...MessageDeliveryCompletion.fields,
|
|
175
|
+
}),
|
|
156
176
|
Schema.Struct({ _tag: Schema.Literal("Claim"), ...fence }),
|
|
157
177
|
Schema.Struct({ _tag: Schema.Literal("Accept"), ...fence, receipt: Receipt }),
|
|
158
178
|
Schema.Struct({ _tag: Schema.Literal("Process"), ...fence, settlement: Settlement }),
|
|
@@ -424,6 +444,34 @@ export const applyMessageDeliveryChange = (
|
|
|
424
444
|
): Result.Result<MessageDeliveryRecord, MessageDeliveryError> => {
|
|
425
445
|
const conflict = () => Result.fail(error("conflict", change._tag));
|
|
426
446
|
|
|
447
|
+
if (change._tag === "Complete") {
|
|
448
|
+
if (
|
|
449
|
+
change.admissionKey !== record.envelope.admissionKey ||
|
|
450
|
+
change.inputDigest !== record.envelope.inputDigest ||
|
|
451
|
+
change.receipt.threadId !== record.envelope.threadId ||
|
|
452
|
+
change.settlement.submissionId !== change.receipt.submissionId ||
|
|
453
|
+
change.settlement.receiptId !== change.receipt.receiptId ||
|
|
454
|
+
(record.receipt !== null && !receiptsEqual(record.receipt, change.receipt))
|
|
455
|
+
)
|
|
456
|
+
return Result.fail(error("corrupt", "completion-identity"));
|
|
457
|
+
if (record.status === "refused") return conflict();
|
|
458
|
+
if (record.status === "processed")
|
|
459
|
+
return record.settlement !== null && settlementsEqual(record.settlement, change.settlement)
|
|
460
|
+
? Result.succeed(record)
|
|
461
|
+
: Result.fail(error("corrupt", "completion-identity"));
|
|
462
|
+
|
|
463
|
+
return Result.succeed({
|
|
464
|
+
...record,
|
|
465
|
+
version: record.version + 1,
|
|
466
|
+
status: "processed",
|
|
467
|
+
receipt: change.receipt,
|
|
468
|
+
settlement: change.settlement,
|
|
469
|
+
leaseUntilMillis: null,
|
|
470
|
+
parkReason: null,
|
|
471
|
+
retry: { ...record.retry, parked: false },
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
|
|
427
475
|
if (record.version !== change.expectedVersion) return conflict();
|
|
428
476
|
if (record.status === "processed" || record.status === "refused") return conflict();
|
|
429
477
|
const now = change.nowMillis;
|
|
@@ -540,21 +588,8 @@ export const applyMessageDeliveryChange = (
|
|
|
540
588
|
}
|
|
541
589
|
if (change._tag === "ObservePending") {
|
|
542
590
|
if (record.status !== "accepted") return conflict();
|
|
543
|
-
if (now >= record.deadlineAtMillis) return Result.succeed(parked("deadline"));
|
|
544
591
|
|
|
545
|
-
return Result.succeed(
|
|
546
|
-
...base,
|
|
547
|
-
leaseUntilMillis: null,
|
|
548
|
-
retry: {
|
|
549
|
-
...record.retry,
|
|
550
|
-
automaticAttempts: 0,
|
|
551
|
-
lastFailure: null,
|
|
552
|
-
nextAttemptAtMillis: Math.min(
|
|
553
|
-
now + record.policy.settlementPollMillis,
|
|
554
|
-
record.deadlineAtMillis,
|
|
555
|
-
),
|
|
556
|
-
},
|
|
557
|
-
});
|
|
592
|
+
return Result.succeed(parked("awaiting-settlement"));
|
|
558
593
|
}
|
|
559
594
|
if (change._tag === "Refuse") {
|
|
560
595
|
if (record.status !== "pending") return conflict();
|
|
@@ -700,9 +735,10 @@ export class MessageDeliveryDriver extends Context.Service<
|
|
|
700
735
|
// Digest computation cannot extend this claim's admission authority.
|
|
701
736
|
if (timeout <= 0) return claimed;
|
|
702
737
|
|
|
703
|
-
type WithoutFence<T> =
|
|
704
|
-
|
|
705
|
-
|
|
738
|
+
type WithoutFence<T> =
|
|
739
|
+
T extends Exclude<MessageDeliveryChange, { _tag: "Complete" }>
|
|
740
|
+
? Omit<T, "expectedVersion" | "nowMillis">
|
|
741
|
+
: never;
|
|
706
742
|
|
|
707
743
|
const commit = (change: WithoutFence<MessageDeliveryChange>) =>
|
|
708
744
|
Clock.currentTimeMillis.pipe(
|
|
@@ -722,8 +758,16 @@ export class MessageDeliveryDriver extends Context.Service<
|
|
|
722
758
|
).pipe(Effect.mapError((cause) => error("corrupt", "admission", cause)));
|
|
723
759
|
|
|
724
760
|
yield* failpoint.hit("message-delivery:admission:after");
|
|
725
|
-
if (outcome._tag === "Receipt")
|
|
726
|
-
|
|
761
|
+
if (outcome._tag === "Receipt") {
|
|
762
|
+
const accepted = yield* commit({ _tag: "Accept", receipt: outcome.receipt });
|
|
763
|
+
|
|
764
|
+
return yield* store.change(key, {
|
|
765
|
+
_tag: "Park",
|
|
766
|
+
reason: "awaiting-settlement",
|
|
767
|
+
expectedVersion: accepted.version,
|
|
768
|
+
nowMillis: yield* Clock.currentTimeMillis,
|
|
769
|
+
});
|
|
770
|
+
}
|
|
727
771
|
if (outcome._tag === "Refused")
|
|
728
772
|
return yield* commit({
|
|
729
773
|
_tag: "Refuse",
|
|
@@ -111,6 +111,17 @@ export const toolReplayContracts = Effect.fn("AgentRegistration.toolReplayContra
|
|
|
111
111
|
name: tool.name,
|
|
112
112
|
contract: {
|
|
113
113
|
version,
|
|
114
|
+
...(Tool.isProviderDefined(tool)
|
|
115
|
+
? {
|
|
116
|
+
provider: {
|
|
117
|
+
id: tool.id,
|
|
118
|
+
providerName: tool.providerName,
|
|
119
|
+
args: Schema.decodeUnknownSync(Schema.Json)(tool.args ?? null),
|
|
120
|
+
requiresHandler: tool.requiresHandler,
|
|
121
|
+
},
|
|
122
|
+
readonly: Context.get(tool.annotations, Tool.Readonly),
|
|
123
|
+
}
|
|
124
|
+
: {}),
|
|
114
125
|
parameters: jsonSchema(tool.parametersSchema),
|
|
115
126
|
success: jsonSchema(tool.successSchema),
|
|
116
127
|
failure: jsonSchema(tool.failureSchema),
|
package/src/engine/RunOptions.ts
CHANGED
|
@@ -348,6 +348,8 @@ export type RunCostEstimateValue = number | RunCostEstimate;
|
|
|
348
348
|
|
|
349
349
|
/** Model identity presented beside the legacy raw-usage estimator argument. */
|
|
350
350
|
export interface RunCostEstimateRequest {
|
|
351
|
+
/** Observed hosted web search calls, separately billed from tokens. */
|
|
352
|
+
readonly webSearchCalls?: number | undefined;
|
|
351
353
|
readonly provider: string;
|
|
352
354
|
/** Configured binding identity; only response.model identifies the returned model. */
|
|
353
355
|
readonly model: string;
|
|
@@ -816,6 +818,7 @@ export type RunTurnResumeSettledCall = typeof RunTurnResumeSettledCallSchema.Typ
|
|
|
816
818
|
export const RunResumeUsageSchema = Schema.Struct({
|
|
817
819
|
...RunPolicyUsage.fields,
|
|
818
820
|
modelCalls: Schema.Natural,
|
|
821
|
+
webSearchCalls: Schema.optionalKey(Schema.Natural),
|
|
819
822
|
inputTokens: Schema.Natural,
|
|
820
823
|
outputTokens: Schema.Natural,
|
|
821
824
|
lastInputTokens: Schema.Natural,
|