effect-agent 0.1.0-beta.155 → 0.1.0-beta.157
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-GQACxY_m.mjs} +21 -5
- package/dist/AgentRuntime-GQACxY_m.mjs.map +1 -0
- package/dist/{Digest-CaJ2RIsF.d.mts → Digest-CNHImGy0.d.mts} +2 -2
- package/dist/{DurableAgentRuntime-BQzYkFVy.mjs → DurableAgentRuntime-BAQvZK1e.mjs} +30 -18
- package/dist/DurableAgentRuntime-BAQvZK1e.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-Dld4W1BY.d.mts → Subagent-CLaMeZKu.d.mts} +6 -6
- package/dist/{Subagent-CmFtZaeI.mjs → Subagent-JjcidJ7q.mjs} +2 -2
- package/dist/{Subagent-CmFtZaeI.mjs.map → Subagent-JjcidJ7q.mjs.map} +1 -1
- 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 +4 -4
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +3 -3
- 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/SqlMemoryStore.d.mts +715 -5
- package/dist/durable/SqlMemoryStore.mjs +313 -123
- package/dist/durable/SqlMemoryStore.mjs.map +1 -1
- 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 +40 -12
- package/src/durable/LifecyclePublication.ts +15 -2
- package/src/durable/SqlMemoryStore.ts +462 -188
- package/src/durable/internal/agent-registration.ts +11 -0
- package/src/engine/RunOptions.ts +3 -0
- package/src/engine/internal/agent-runtime.ts +68 -5
- 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
package/src/core/Agent.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
type Model,
|
|
7
7
|
type Prompt,
|
|
8
8
|
Tool,
|
|
9
|
-
|
|
9
|
+
Toolkit,
|
|
10
10
|
} from "effect/unstable/ai";
|
|
11
11
|
|
|
12
12
|
import type { AgentInputError, AgentOutputError, AgentRunDispositionError } from "./AgentError.ts";
|
|
@@ -569,9 +569,23 @@ export function make(
|
|
|
569
569
|
completionNames.add(declaration.tool);
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
const tools = Object.values(options.toolkit.tools);
|
|
573
|
+
|
|
574
|
+
const readonlyTools = tools.map((tool) =>
|
|
575
|
+
Tool.isProviderDefined(tool) &&
|
|
576
|
+
!tool.requiresHandler &&
|
|
577
|
+
["web_search", "web_search_preview", "file_search"].includes(tool.providerName)
|
|
578
|
+
? tool.annotate(Tool.Readonly, true)
|
|
579
|
+
: tool,
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
const toolkit = readonlyTools.some((tool, index) => tool !== tools[index])
|
|
583
|
+
? Toolkit.make(...readonlyTools)
|
|
584
|
+
: options.toolkit;
|
|
585
|
+
|
|
572
586
|
return Object.freeze({
|
|
573
587
|
...options,
|
|
574
|
-
toolkit: withUpdateTool(
|
|
588
|
+
toolkit: withUpdateTool(toolkit, options.updates),
|
|
575
589
|
policy: AgentPolicy.resolve(options.policy),
|
|
576
590
|
policyOverrides: Object.freeze({ ...options.policy }),
|
|
577
591
|
toolExposure:
|
package/src/core/Usage.ts
CHANGED
|
@@ -68,6 +68,8 @@ export class ModelCallUsage extends Schema.Class<ModelCallUsage>(
|
|
|
68
68
|
pricingStatus: Schema.optionalKey(Schema.Literals(["estimated", "unknown"])),
|
|
69
69
|
inputTokens: InputTokenUsage,
|
|
70
70
|
outputTokens: OutputTokenUsage,
|
|
71
|
+
/** Observed hosted web searches; excludes OpenAI page/find actions. Absent in legacy records. */
|
|
72
|
+
webSearchCalls: Schema.optionalKey(Schema.Natural),
|
|
71
73
|
costMicrousd: Schema.Natural,
|
|
72
74
|
}) {}
|
|
73
75
|
|
|
@@ -80,6 +82,8 @@ export class RunTotals extends Schema.Class<RunTotals>("@effect-agent/core/RunTo
|
|
|
80
82
|
modelCalls: Schema.Natural,
|
|
81
83
|
inputTokens: Schema.Natural,
|
|
82
84
|
outputTokens: Schema.Natural,
|
|
85
|
+
/** Observed hosted web searches; excludes OpenAI page/find actions. Absent in legacy records. */
|
|
86
|
+
webSearchCalls: Schema.optionalKey(Schema.Natural),
|
|
83
87
|
costMicrousd: Schema.Natural,
|
|
84
88
|
usageStatus: Schema.optionalKey(UsageCompleteness),
|
|
85
89
|
pricingStatus: Schema.optionalKey(UsageCompleteness),
|
|
@@ -104,6 +108,7 @@ export class ChildRunUsage extends Schema.Class<ChildRunUsage>("@effect-agent/co
|
|
|
104
108
|
export const emptyRunTotals = (): RunTotals =>
|
|
105
109
|
RunTotals.make({
|
|
106
110
|
modelCalls: 0,
|
|
111
|
+
webSearchCalls: 0,
|
|
107
112
|
inputTokens: 0,
|
|
108
113
|
outputTokens: 0,
|
|
109
114
|
costMicrousd: 0,
|
|
@@ -133,6 +138,8 @@ export class ModelUsageGroup extends Schema.Class<ModelUsageGroup>(
|
|
|
133
138
|
modelCalls: Schema.Natural.check(Schema.isGreaterThan(0)),
|
|
134
139
|
inputTokens: InputTokenUsage,
|
|
135
140
|
outputTokens: OutputTokenUsage,
|
|
141
|
+
/** Observed hosted web searches; excludes OpenAI page/find actions. Absent in legacy records. */
|
|
142
|
+
webSearchCalls: Schema.optionalKey(Schema.Natural),
|
|
136
143
|
costMicrousd: Schema.Natural,
|
|
137
144
|
}) {}
|
|
138
145
|
|
|
@@ -140,6 +147,8 @@ const RunUsageSummaryFields = Schema.Struct({
|
|
|
140
147
|
modelCalls: Schema.Natural,
|
|
141
148
|
inputTokens: InputTokenUsage,
|
|
142
149
|
outputTokens: OutputTokenUsage,
|
|
150
|
+
/** Observed hosted web searches; excludes OpenAI page/find actions. Absent in legacy records. */
|
|
151
|
+
webSearchCalls: Schema.optionalKey(Schema.Natural),
|
|
143
152
|
costMicrousd: Schema.Natural,
|
|
144
153
|
byModel: Schema.Array(ModelUsageGroup),
|
|
145
154
|
/** Coverage of recorded calls only; interruptions can make the Run less complete. */
|
|
@@ -162,6 +171,11 @@ const RunUsageSummaryFields = Schema.Struct({
|
|
|
162
171
|
|
|
163
172
|
return (
|
|
164
173
|
new Set(identities).size === identities.length &&
|
|
174
|
+
(summary.webSearchCalls === undefined ||
|
|
175
|
+
hasAdditiveTotal(
|
|
176
|
+
summary.webSearchCalls,
|
|
177
|
+
summary.byModel.map((group) => group.webSearchCalls ?? 0),
|
|
178
|
+
)) &&
|
|
165
179
|
hasAdditiveTotal(
|
|
166
180
|
summary.modelCalls,
|
|
167
181
|
summary.byModel.map((group) => group.modelCalls),
|
|
@@ -219,6 +233,7 @@ interface MutableUsageGroup {
|
|
|
219
233
|
readonly serviceTier?: string | undefined;
|
|
220
234
|
readonly pricingVersion?: string | undefined;
|
|
221
235
|
modelCalls: number;
|
|
236
|
+
webSearchCalls: number | undefined;
|
|
222
237
|
inputTokens: {
|
|
223
238
|
total: number;
|
|
224
239
|
uncached: number;
|
|
@@ -267,6 +282,7 @@ export const sumRunTotals = Effect.fn("sumRunTotals")(function* (
|
|
|
267
282
|
contributions: ReadonlyArray<RunTotals>,
|
|
268
283
|
): Effect.fn.Return<RunTotals, UsageAggregationError> {
|
|
269
284
|
let modelCalls = 0;
|
|
285
|
+
let webSearchCalls: number | undefined = 0;
|
|
270
286
|
let inputTokens = 0;
|
|
271
287
|
let outputTokens = 0;
|
|
272
288
|
let costMicrousd = 0;
|
|
@@ -282,6 +298,13 @@ export const sumRunTotals = Effect.fn("sumRunTotals")(function* (
|
|
|
282
298
|
);
|
|
283
299
|
|
|
284
300
|
modelCalls = yield* checkedAdd("modelCalls", modelCalls, value.modelCalls);
|
|
301
|
+
if (value.webSearchCalls === undefined && value.modelCalls > 0) webSearchCalls = undefined;
|
|
302
|
+
else if (webSearchCalls !== undefined)
|
|
303
|
+
webSearchCalls = yield* checkedAdd(
|
|
304
|
+
"webSearchCalls",
|
|
305
|
+
webSearchCalls,
|
|
306
|
+
value.webSearchCalls ?? 0,
|
|
307
|
+
);
|
|
285
308
|
inputTokens = yield* checkedAdd("inputTokens", inputTokens, value.inputTokens);
|
|
286
309
|
outputTokens = yield* checkedAdd("outputTokens", outputTokens, value.outputTokens);
|
|
287
310
|
costMicrousd = yield* checkedAdd("costMicrousd", costMicrousd, value.costMicrousd);
|
|
@@ -316,6 +339,7 @@ export const sumRunTotals = Effect.fn("sumRunTotals")(function* (
|
|
|
316
339
|
|
|
317
340
|
return RunTotals.make({
|
|
318
341
|
modelCalls,
|
|
342
|
+
...(webSearchCalls === undefined ? {} : { webSearchCalls }),
|
|
319
343
|
inputTokens,
|
|
320
344
|
outputTokens,
|
|
321
345
|
costMicrousd,
|
|
@@ -329,6 +353,7 @@ export const sumRunTotals = Effect.fn("sumRunTotals")(function* (
|
|
|
329
353
|
export const runTotalsFromSummary = (summary: RunUsageSummary): RunTotals =>
|
|
330
354
|
RunTotals.make({
|
|
331
355
|
modelCalls: summary.modelCalls,
|
|
356
|
+
...(summary.webSearchCalls === undefined ? {} : { webSearchCalls: summary.webSearchCalls }),
|
|
332
357
|
inputTokens: summary.inputTokens.total,
|
|
333
358
|
outputTokens: summary.outputTokens.total,
|
|
334
359
|
costMicrousd: summary.costMicrousd,
|
|
@@ -363,6 +388,10 @@ export const summarizeModelUsage = Effect.fn("summarizeModelUsage")(function* (
|
|
|
363
388
|
const outputTokens = initial === undefined ? emptyOutputTokens() : { ...initial.outputTokens };
|
|
364
389
|
const groups = new Map<string, MutableUsageGroup>();
|
|
365
390
|
let modelCalls = initial?.modelCalls ?? 0;
|
|
391
|
+
|
|
392
|
+
let webSearchCalls =
|
|
393
|
+
initial === undefined || initial.modelCalls === 0 ? 0 : initial.webSearchCalls;
|
|
394
|
+
|
|
366
395
|
let costMicrousd = initial?.costMicrousd ?? 0;
|
|
367
396
|
const hasSeedCalls = modelCalls > 0;
|
|
368
397
|
|
|
@@ -387,6 +416,7 @@ export const summarizeModelUsage = Effect.fn("summarizeModelUsage")(function* (
|
|
|
387
416
|
|
|
388
417
|
groups.set(key, {
|
|
389
418
|
...group,
|
|
419
|
+
webSearchCalls: group.webSearchCalls,
|
|
390
420
|
inputTokens: { ...group.inputTokens },
|
|
391
421
|
outputTokens: { ...group.outputTokens },
|
|
392
422
|
});
|
|
@@ -398,6 +428,10 @@ export const summarizeModelUsage = Effect.fn("summarizeModelUsage")(function* (
|
|
|
398
428
|
allPricingUnknown &&= call.pricingStatus !== "estimated";
|
|
399
429
|
allPricingComplete &&= call.pricingStatus === "estimated";
|
|
400
430
|
modelCalls = yield* checkedAdd("modelCalls", modelCalls, 1);
|
|
431
|
+
webSearchCalls =
|
|
432
|
+
webSearchCalls === undefined || call.webSearchCalls === undefined
|
|
433
|
+
? undefined
|
|
434
|
+
: yield* checkedAdd("webSearchCalls", webSearchCalls, call.webSearchCalls);
|
|
401
435
|
inputTokens.total = yield* checkedAdd(
|
|
402
436
|
"inputTokens.total",
|
|
403
437
|
inputTokens.total,
|
|
@@ -453,6 +487,7 @@ export const summarizeModelUsage = Effect.fn("summarizeModelUsage")(function* (
|
|
|
453
487
|
...(call.serviceTier === undefined ? {} : { serviceTier: call.serviceTier }),
|
|
454
488
|
...(call.pricingVersion === undefined ? {} : { pricingVersion: call.pricingVersion }),
|
|
455
489
|
modelCalls: 0,
|
|
490
|
+
webSearchCalls: 0,
|
|
456
491
|
inputTokens: emptyInputTokens(),
|
|
457
492
|
outputTokens: emptyOutputTokens(),
|
|
458
493
|
costMicrousd: 0,
|
|
@@ -460,6 +495,10 @@ export const summarizeModelUsage = Effect.fn("summarizeModelUsage")(function* (
|
|
|
460
495
|
groups.set(key, group);
|
|
461
496
|
}
|
|
462
497
|
group.modelCalls = yield* checkedAdd("byModel.modelCalls", group.modelCalls, 1);
|
|
498
|
+
group.webSearchCalls =
|
|
499
|
+
group.webSearchCalls === undefined || call.webSearchCalls === undefined
|
|
500
|
+
? undefined
|
|
501
|
+
: yield* checkedAdd("byModel.webSearchCalls", group.webSearchCalls, call.webSearchCalls);
|
|
463
502
|
group.inputTokens.total = yield* checkedAdd(
|
|
464
503
|
"byModel.inputTokens.total",
|
|
465
504
|
group.inputTokens.total,
|
|
@@ -504,6 +543,7 @@ export const summarizeModelUsage = Effect.fn("summarizeModelUsage")(function* (
|
|
|
504
543
|
|
|
505
544
|
return RunUsageSummary.make({
|
|
506
545
|
modelCalls,
|
|
546
|
+
...(webSearchCalls === undefined ? {} : { webSearchCalls }),
|
|
507
547
|
inputTokens: InputTokenUsage.make(inputTokens),
|
|
508
548
|
outputTokens: OutputTokenUsage.make(outputTokens),
|
|
509
549
|
costMicrousd,
|
|
@@ -520,6 +560,7 @@ export const summarizeModelUsage = Effect.fn("summarizeModelUsage")(function* (
|
|
|
520
560
|
...(group.serviceTier === undefined ? {} : { serviceTier: group.serviceTier }),
|
|
521
561
|
...(group.pricingVersion === undefined ? {} : { pricingVersion: group.pricingVersion }),
|
|
522
562
|
modelCalls: group.modelCalls,
|
|
563
|
+
...(group.webSearchCalls === undefined ? {} : { webSearchCalls: group.webSearchCalls }),
|
|
523
564
|
inputTokens: InputTokenUsage.make(group.inputTokens),
|
|
524
565
|
outputTokens: OutputTokenUsage.make(group.outputTokens),
|
|
525
566
|
costMicrousd: group.costMicrousd,
|
|
@@ -4559,6 +4559,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
4559
4559
|
ctx: AttemptAppendContext,
|
|
4560
4560
|
submission: SubmissionSnapshot,
|
|
4561
4561
|
tokenRef: Ref.Ref<OwnershipToken>,
|
|
4562
|
+
renewAtRef: Ref.Ref<number>,
|
|
4562
4563
|
records: ReadonlyArray<CanonicalRecordEnvelope>,
|
|
4563
4564
|
canonical: Stream.Stream<CanonicalRecordEnvelope, ThreadStoreError | ThreadNotMaterialized>,
|
|
4564
4565
|
canonicalThrough: CanonicalSequence,
|
|
@@ -5258,6 +5259,9 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
5258
5259
|
);
|
|
5259
5260
|
|
|
5260
5261
|
return RunUsageSummary.make({
|
|
5262
|
+
...(legacyCalls === 0 && detailed.webSearchCalls !== undefined
|
|
5263
|
+
? { webSearchCalls: detailed.webSearchCalls }
|
|
5264
|
+
: {}),
|
|
5261
5265
|
modelCalls,
|
|
5262
5266
|
inputTokens: InputTokenUsage.make({
|
|
5263
5267
|
total: inputTokens,
|
|
@@ -7798,18 +7802,33 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
7798
7802
|
// Liveness only: the lease keeps the claim visible; correctness stays with the epoch fence.
|
|
7799
7803
|
// OwnershipLost ends the race and interrupts the Run fiber cleanly.
|
|
7800
7804
|
const renewal = halt(
|
|
7801
|
-
Effect.
|
|
7802
|
-
|
|
7803
|
-
|
|
7805
|
+
Effect.gen(function* () {
|
|
7806
|
+
// Binding selection and preparation consume the acquired lease too. Carry the next
|
|
7807
|
+
// deadline across model continuations; an overdue first renewal must run immediately.
|
|
7808
|
+
const renewAt = yield* Ref.get(renewAtRef);
|
|
7809
|
+
const now = yield* Clock.currentTimeMillis;
|
|
7804
7810
|
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
)
|
|
7811
|
+
yield* Effect.sleep(Math.max(0, renewAt - now));
|
|
7812
|
+
yield* Effect.repeat(
|
|
7813
|
+
Effect.gen(function* () {
|
|
7814
|
+
const ownershipToken = yield* Ref.get(tokenRef);
|
|
7815
|
+
const renewingAt = yield* Clock.currentTimeMillis;
|
|
7816
|
+
|
|
7817
|
+
const renewal = yield* ledger.renewOwnership(
|
|
7818
|
+
RenewOwnershipRequest.make({ submissionId, ownershipToken }),
|
|
7819
|
+
);
|
|
7808
7820
|
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7821
|
+
yield* Ref.set(tokenRef, renewal.ownershipToken);
|
|
7822
|
+
yield* Ref.set(
|
|
7823
|
+
renewAtRef,
|
|
7824
|
+
renewingAt + Duration.toMillis(config.leaseRenewalInterval),
|
|
7825
|
+
);
|
|
7826
|
+
}).pipe(Effect.uninterruptible),
|
|
7827
|
+
{ schedule: Schedule.spaced(config.leaseRenewalInterval) },
|
|
7828
|
+
);
|
|
7829
|
+
|
|
7830
|
+
return yield* Effect.never;
|
|
7831
|
+
}),
|
|
7813
7832
|
);
|
|
7814
7833
|
|
|
7815
7834
|
const execution = Effect.raceFirst(consume, Effect.raceFirst(abortWatcher, renewal));
|
|
@@ -8031,6 +8050,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8031
8050
|
threadId: ThreadId,
|
|
8032
8051
|
claim: Claim,
|
|
8033
8052
|
tokenRef: Ref.Ref<OwnershipToken>,
|
|
8053
|
+
renewAtRef: Ref.Ref<number>,
|
|
8034
8054
|
resumeAfterRetention: () => void,
|
|
8035
8055
|
onHandoff: (nextSubmissionId: SubmissionId) => void,
|
|
8036
8056
|
yieldAfter?: DateTime.Utc,
|
|
@@ -8467,6 +8487,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8467
8487
|
ctx,
|
|
8468
8488
|
submission,
|
|
8469
8489
|
tokenRef,
|
|
8490
|
+
renewAtRef,
|
|
8470
8491
|
currentRecords,
|
|
8471
8492
|
canonical,
|
|
8472
8493
|
tail.tailSequence,
|
|
@@ -8647,6 +8668,8 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8647
8668
|
threadId: ThreadId,
|
|
8648
8669
|
handoff?: ClaimHandoff,
|
|
8649
8670
|
) {
|
|
8671
|
+
const acquiringAt = yield* Clock.currentTimeMillis;
|
|
8672
|
+
|
|
8650
8673
|
const claimed = yield* ledger.claim(
|
|
8651
8674
|
ClaimRequest.make({
|
|
8652
8675
|
threadId,
|
|
@@ -8659,6 +8682,10 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8659
8682
|
const claim = claimed.value;
|
|
8660
8683
|
const tokenRef = yield* Ref.make(claim.ownershipToken);
|
|
8661
8684
|
|
|
8685
|
+
const renewAtRef = yield* Ref.make(
|
|
8686
|
+
acquiringAt + Duration.toMillis(config.leaseRenewalInterval),
|
|
8687
|
+
);
|
|
8688
|
+
|
|
8662
8689
|
yield* Effect.addFinalizer(() =>
|
|
8663
8690
|
Ref.get(tokenRef).pipe(
|
|
8664
8691
|
Effect.flatMap((ownershipToken) =>
|
|
@@ -8681,7 +8708,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8681
8708
|
message: "The submission adapter did not honor the requested handoff",
|
|
8682
8709
|
});
|
|
8683
8710
|
|
|
8684
|
-
return Option.some({ claim, tokenRef });
|
|
8711
|
+
return Option.some({ claim, tokenRef, renewAtRef });
|
|
8685
8712
|
}, Effect.uninterruptible);
|
|
8686
8713
|
|
|
8687
8714
|
const processThreadHead = (
|
|
@@ -8701,7 +8728,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8701
8728
|
const claimed = yield* acquireClaim(threadId, handoff);
|
|
8702
8729
|
|
|
8703
8730
|
if (Option.isNone(claimed)) return Option.none();
|
|
8704
|
-
const { claim, tokenRef } = claimed.value;
|
|
8731
|
+
const { claim, tokenRef, renewAtRef } = claimed.value;
|
|
8705
8732
|
|
|
8706
8733
|
const attributes = {
|
|
8707
8734
|
threadId,
|
|
@@ -8781,6 +8808,7 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (
|
|
|
8781
8808
|
attemptThreadId,
|
|
8782
8809
|
attemptClaim,
|
|
8783
8810
|
tokenRef,
|
|
8811
|
+
renewAtRef,
|
|
8784
8812
|
() => {
|
|
8785
8813
|
resumeAfterRetention = true;
|
|
8786
8814
|
},
|
|
@@ -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
|
|