@yielded/agent 0.1.0-beta.173 → 0.1.0-beta.175
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-BX9ns28E.d.mts → Admin-Qa3I1oA5.d.mts} +61 -21
- package/dist/{Agent-9aBoIi74.d.mts → Agent-B39jRnFv.d.mts} +2 -2
- package/dist/{Agent-0WvBWWbM.mjs → Agent-BiRbr73L.mjs} +7 -6
- package/dist/Agent-BiRbr73L.mjs.map +1 -0
- package/dist/{AgentRuntime-BfP14534.d.mts → AgentRuntime-CHDyRbSf.d.mts} +12 -12
- package/dist/{AgentRuntime-CQ-qcETl.mjs → AgentRuntime-DaDKMasp.mjs} +290 -273
- package/dist/AgentRuntime-DaDKMasp.mjs.map +1 -0
- package/dist/{Digest-DCuPlhNk.mjs → Digest-C3EODOee.mjs} +42 -15
- package/dist/Digest-C3EODOee.mjs.map +1 -0
- package/dist/{DurableAgentRuntime-BAmSkWYr.mjs → DurableAgentRuntime-CPlw5_7e.mjs} +1557 -1458
- package/dist/DurableAgentRuntime-CPlw5_7e.mjs.map +1 -0
- package/dist/{EventSource-BwliwQz9.d.mts → EventSource-BTu68yDW.d.mts} +2 -2
- package/dist/InMemory.d.mts +2 -2
- package/dist/{MessageDelivery-B943ebI_.d.mts → MessageDelivery-DjAZJ4Fd.d.mts} +42 -42
- package/dist/{Messaging-C_6OOg_s.d.mts → Messaging-SVu6rWV8.d.mts} +12 -6
- package/dist/{MessagingHost-B8oKM7AC.d.mts → MessagingHost-C6SOAcoG.d.mts} +2 -2
- package/dist/{MessagingHost-CRUK4JBi.mjs → MessagingHost-CZCyrnvJ.mjs} +27 -26
- package/dist/MessagingHost-CZCyrnvJ.mjs.map +1 -0
- package/dist/{Output-Dsx6k52t.d.mts → Output-CRamN1Fy.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-CxSJSiTl.d.mts → PreparedInputAdmission-wgY4JMZY.d.mts} +3 -3
- package/dist/{Records-BiuJDWNe.mjs → Records-DzL4Kbtw.mjs} +2 -2
- package/dist/{Records-BiuJDWNe.mjs.map → Records-DzL4Kbtw.mjs.map} +1 -1
- package/dist/{RunContinuation-FHM7XPjq.d.mts → RunContinuation-3jB5pULC.d.mts} +13 -7
- package/dist/{RunContinuation-DHYNAQFi.mjs → RunContinuation-BiyKJK32.mjs} +173 -82
- package/dist/RunContinuation-BiyKJK32.mjs.map +1 -0
- package/dist/{RunJournal-kfKVxJj7.mjs → RunJournal-CPMKcfd0.mjs} +106 -73
- package/dist/RunJournal-CPMKcfd0.mjs.map +1 -0
- package/dist/{RunOptions-D8zxFIrZ.d.mts → RunOptions-Be77lKVZ.d.mts} +2 -2
- package/dist/{RunStorage-uqPxps09.mjs → RunStorage-CzutHJBE.mjs} +10 -6
- package/dist/RunStorage-CzutHJBE.mjs.map +1 -0
- package/dist/{Scheduling-CVyfXlBR.mjs → Scheduling-07_dsGED.mjs} +12 -12
- package/dist/Scheduling-07_dsGED.mjs.map +1 -0
- package/dist/{Subagent-vpffemql.mjs → Subagent-CexndZSp.mjs} +53 -40
- package/dist/Subagent-CexndZSp.mjs.map +1 -0
- package/dist/{Subagent-E6tvd7-k.d.mts → Subagent-xhN_aD1r.d.mts} +20 -9
- package/dist/{SubagentHost-B6w2m-SI.d.mts → SubagentHost-D1xBgn9g.d.mts} +2 -2
- package/dist/{Subscription-DONig54Q.d.mts → Subscription-DmIHlOJK.d.mts} +2 -2
- package/dist/{SubscriptionInput-mJIRxWJM.d.mts → SubscriptionInput-DgcQhvbe.d.mts} +2 -2
- package/dist/{Thread-dk-QiNml.d.mts → Thread-DzdJAY4J.d.mts} +4 -3
- package/dist/{ThreadHistory-ByxS8HU1.d.mts → ThreadHistory-KPPBJLJb.d.mts} +12 -2
- package/dist/{ThreadImport-DckUMEqJ.mjs → ThreadImport-CjlG57vH.mjs} +9 -9
- package/dist/ThreadImport-CjlG57vH.mjs.map +1 -0
- package/dist/{ThreadImport-DpHxjBrA.d.mts → ThreadImport-DP-vOk2F.d.mts} +5 -5
- package/dist/{ThreadStore-CEekRa80.mjs → ThreadStore-EuUilthA.mjs} +162 -85
- package/dist/ThreadStore-EuUilthA.mjs.map +1 -0
- package/dist/{ThreadTransfer-B4gTQLIl.mjs → ThreadTransfer-DB_zsrtJ.mjs} +4 -4
- package/dist/{ThreadTransfer-B4gTQLIl.mjs.map → ThreadTransfer-DB_zsrtJ.mjs.map} +1 -1
- package/dist/{WorkerAdmission-DFVbbVh2.mjs → WorkerAdmission-eBeXt_mu.mjs} +5 -5
- package/dist/{WorkerAdmission-DFVbbVh2.mjs.map → WorkerAdmission-eBeXt_mu.mjs.map} +1 -1
- package/dist/{agent-registration-ByMZ_cK5.mjs → agent-registration-a6QYaG3h.mjs} +70 -57
- package/dist/agent-registration-a6QYaG3h.mjs.map +1 -0
- package/dist/capabilities/Approval.mjs +2 -2
- package/dist/capabilities/Approval.mjs.map +1 -1
- package/dist/capabilities/BrowserUse.d.mts +102 -1867
- package/dist/capabilities/BrowserUse.mjs +74 -798
- package/dist/capabilities/BrowserUse.mjs.map +1 -1
- package/dist/capabilities/Budget.mjs +3 -1
- package/dist/capabilities/Budget.mjs.map +1 -1
- package/dist/capabilities/CodeMode.d.mts +1 -1
- package/dist/capabilities/CodeMode.mjs +16 -9
- package/dist/capabilities/CodeMode.mjs.map +1 -1
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/McpClient.mjs +1 -1
- package/dist/capabilities/McpClient.mjs.map +1 -1
- package/dist/capabilities/Messaging.d.mts +1 -1
- package/dist/capabilities/Messaging.mjs +5 -5
- package/dist/capabilities/Messaging.mjs.map +1 -1
- package/dist/capabilities/ModelContext.d.mts +1 -1
- package/dist/capabilities/ModelContext.mjs +7 -5
- package/dist/capabilities/ModelContext.mjs.map +1 -1
- package/dist/capabilities/Redaction.mjs +49 -19
- package/dist/capabilities/Redaction.mjs.map +1 -1
- package/dist/capabilities/RunHooks.d.mts +2 -2
- package/dist/capabilities/RunHooks.mjs +1 -1
- package/dist/capabilities/RunHooks.mjs.map +1 -1
- package/dist/capabilities/Subagent.d.mts +1 -1
- package/dist/capabilities/Subagent.mjs +1 -1
- package/dist/capabilities/SubagentReservations.mjs +3 -1
- package/dist/capabilities/SubagentReservations.mjs.map +1 -1
- package/dist/capabilities/WebCapture.mjs.map +1 -1
- package/dist/capabilities/WebSearch.mjs +7 -7
- package/dist/capabilities/WebSearch.mjs.map +1 -1
- package/dist/core/Agent.d.mts +1 -1
- package/dist/core/Agent.mjs +1 -1
- package/dist/core/AgentUpdates.mjs +8 -8
- package/dist/core/AgentUpdates.mjs.map +1 -1
- package/dist/core/Thread.d.mts +2 -2
- package/dist/core/Thread.mjs +6 -4
- package/dist/core/Thread.mjs.map +1 -1
- package/dist/core/Usage.mjs +2 -2
- package/dist/core/Usage.mjs.map +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 +7 -7
- package/dist/durable/EventSource.mjs.map +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/MessageDelivery.d.mts +1 -1
- package/dist/durable/MessageDelivery.mjs +2 -2
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +40 -40
- package/dist/durable/MessageDeliveryStoreConformance.mjs +2 -2
- package/dist/durable/PersistentHistory.d.mts +2 -2
- package/dist/durable/PersistentHistory.mjs +4 -4
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/RecordFormat.mjs +3 -3
- package/dist/durable/RecordFormat.mjs.map +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 +2 -2
- package/dist/durable/RunJournal.mjs +2 -2
- 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/SqlMemoryStore.mjs +5 -3
- package/dist/durable/SqlMemoryStore.mjs.map +1 -1
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +11 -3
- package/dist/durable/SubmissionLedger.mjs.map +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +6 -6
- 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 +4 -4
- package/dist/durable/SubscriptionInput.mjs.map +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +3 -3
- package/dist/durable/SubscriptionStoreConformance.mjs.map +1 -1
- package/dist/durable/SubscriptionTools.d.mts +2 -2
- 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 +3 -3
- package/dist/durable/Subscriptions.mjs.map +1 -1
- 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 +5 -5
- package/dist/durable/ThreadInvariants.mjs.map +1 -1
- 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 +2 -2
- package/dist/durable/ThreadWork.mjs +12 -6
- package/dist/durable/ThreadWork.mjs.map +1 -1
- package/dist/durable/ToolReconciler.mjs +1 -1
- package/dist/durable/WakeScheduler.mjs +23 -39
- package/dist/durable/WakeScheduler.mjs.map +1 -1
- package/dist/durable/WorkerAdmission.d.mts +1 -1
- 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/MessagingHost.d.mts +1 -1
- package/dist/engine/MessagingHost.mjs +1 -1
- package/dist/engine/Output.d.mts +1 -1
- package/dist/engine/Output.mjs +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/SubagentHost.d.mts +1 -1
- package/dist/engine/ThreadHistory.d.mts +1 -1
- package/dist/engine/ThreadHistory.mjs +3 -2
- package/dist/engine/ThreadHistory.mjs.map +1 -1
- package/dist/index.d.mts +21 -21
- package/dist/index.mjs +16 -16
- package/dist/{output-contract-CMIhu4Cw.mjs → output-contract-DCnLYCdp.mjs} +12 -15
- package/dist/{output-contract-CMIhu4Cw.mjs.map → output-contract-DCnLYCdp.mjs.map} +1 -1
- package/dist/{run-context-reader-OcsZr4bk.d.mts → run-context-reader-DVhJZ1Qe.d.mts} +2 -2
- package/package.json +1 -1
- package/src/capabilities/Approval.ts +58 -60
- package/src/capabilities/BrowserUse.ts +89 -944
- package/src/capabilities/Budget.ts +8 -1
- package/src/capabilities/CodeMode.ts +57 -33
- package/src/capabilities/McpClient.ts +2 -2
- package/src/capabilities/Messaging.ts +51 -55
- package/src/capabilities/ModelContext.ts +5 -2
- package/src/capabilities/Redaction.ts +64 -34
- package/src/capabilities/RunHooks.ts +52 -55
- package/src/capabilities/Subagent.ts +33 -33
- package/src/capabilities/SubagentReservations.ts +9 -1
- package/src/capabilities/WebCapture.ts +6 -0
- package/src/capabilities/WebSearch.ts +10 -7
- package/src/capabilities/internal/subagent-background.ts +202 -158
- package/src/core/Agent.ts +11 -6
- package/src/core/AgentUpdates.ts +8 -8
- package/src/core/Thread.ts +142 -146
- package/src/core/Usage.ts +7 -8
- package/src/core/internal/agent-updates.ts +1 -0
- package/src/durable/DurableAgentRuntime.ts +1024 -829
- package/src/durable/EventSource.ts +15 -9
- package/src/durable/RecordFormat.ts +5 -3
- package/src/durable/RunContinuation.ts +316 -113
- package/src/durable/RunJournal.ts +106 -114
- package/src/durable/RunStorage.ts +129 -124
- package/src/durable/Scheduling.ts +639 -651
- package/src/durable/SqlMemoryStore.ts +8 -6
- package/src/durable/SubmissionLedger.ts +11 -0
- package/src/durable/SubscriptionInput.ts +5 -3
- package/src/durable/SubscriptionStoreConformance.ts +23 -23
- package/src/durable/Subscriptions.ts +18 -19
- package/src/durable/ThreadImport.ts +18 -19
- package/src/durable/ThreadInvariants.ts +2 -1
- package/src/durable/ThreadStore.ts +217 -111
- package/src/durable/ThreadWork.ts +11 -2
- package/src/durable/WakeScheduler.ts +34 -66
- package/src/durable/internal/StorageOwner.ts +10 -4
- package/src/durable/internal/agent-registration.ts +96 -89
- package/src/durable/internal/canonical-json.ts +61 -20
- package/src/durable/internal/prompt-history-cache.ts +13 -4
- package/src/durable/internal/record-encoding.ts +120 -64
- package/src/durable/internal/schedule-time.ts +6 -6
- package/src/durable/internal/usage-totals.ts +35 -0
- package/src/durable/internal/worker-host.ts +69 -74
- package/src/engine/MessagingHost.ts +4 -2
- package/src/engine/ThreadHistory.ts +47 -48
- package/src/engine/internal/agent-runtime.ts +1298 -1217
- package/src/engine/internal/output-contract.ts +15 -15
- package/src/engine/internal/primitive-delta.ts +2 -3
- package/src/engine/internal/provisional-text.ts +12 -10
- package/src/engine/internal/tool-exposure.ts +22 -18
- package/src/engine/internal/tool-telemetry.ts +15 -12
- package/dist/Agent-0WvBWWbM.mjs.map +0 -1
- package/dist/AgentRuntime-CQ-qcETl.mjs.map +0 -1
- package/dist/Digest-DCuPlhNk.mjs.map +0 -1
- package/dist/DurableAgentRuntime-BAmSkWYr.mjs.map +0 -1
- package/dist/MessagingHost-CRUK4JBi.mjs.map +0 -1
- package/dist/RunContinuation-DHYNAQFi.mjs.map +0 -1
- package/dist/RunJournal-kfKVxJj7.mjs.map +0 -1
- package/dist/RunStorage-uqPxps09.mjs.map +0 -1
- package/dist/Scheduling-CVyfXlBR.mjs.map +0 -1
- package/dist/Subagent-vpffemql.mjs.map +0 -1
- package/dist/ThreadImport-DckUMEqJ.mjs.map +0 -1
- package/dist/ThreadStore-CEekRa80.mjs.map +0 -1
- package/dist/agent-registration-ByMZ_cK5.mjs.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Context,
|
|
1
|
+
import { Context, DateTime, Effect, Option, Result, Schema, Semaphore, Stream } from "effect";
|
|
2
2
|
import { Prompt } from "effect/ai";
|
|
3
3
|
|
|
4
4
|
import { AgentPersistenceCapacityError } from "../core/AgentError.ts";
|
|
5
5
|
import type { RunId, SubmissionId, ThreadId } from "../core/Identifiers.ts";
|
|
6
6
|
import { ToolCallId } from "../core/Identifiers.ts";
|
|
7
7
|
import { utf8ByteLength } from "../core/internal/utf8.ts";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { resolveEvidence } from "./internal/evidence.ts";
|
|
9
|
+
import { continuationUsage } from "./internal/usage-totals.ts";
|
|
10
10
|
export { reference, resolveEvidence } from "./internal/evidence.ts";
|
|
11
11
|
import {
|
|
12
12
|
captureRecord,
|
|
@@ -119,56 +119,124 @@ const isExecutionProgressRecord = (
|
|
|
119
119
|
record.payload._tag === "RunContinuation";
|
|
120
120
|
|
|
121
121
|
const decodeResponsePrompt = Schema.decodeUnknownEffect(Prompt.Prompt);
|
|
122
|
+
// The decoded Prompt stays private. Progress and capacity are recomputed on every invocation.
|
|
123
|
+
const responsePrompts = new WeakMap<ModelResponseRecorded, Prompt.Prompt>();
|
|
122
124
|
|
|
123
|
-
|
|
125
|
+
/** Cache eligibility only: freezing does not make accessors or custom iterators immutable. */
|
|
126
|
+
const isFrozenJsonData = (input: Schema.Json): boolean => {
|
|
127
|
+
const pending: Array<unknown> = [input];
|
|
128
|
+
const seen = new WeakSet<object>();
|
|
129
|
+
|
|
130
|
+
while (pending.length > 0) {
|
|
131
|
+
const value = pending.pop();
|
|
132
|
+
|
|
133
|
+
if (value === null) continue;
|
|
134
|
+
if (typeof value !== "object") {
|
|
135
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean")
|
|
136
|
+
return false;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (seen.has(value)) continue;
|
|
140
|
+
seen.add(value);
|
|
141
|
+
const prototype = Object.getPrototypeOf(value);
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
!Object.isFrozen(value) ||
|
|
145
|
+
(prototype !== null && prototype !== Object.prototype && prototype !== Array.prototype)
|
|
146
|
+
)
|
|
147
|
+
return false;
|
|
148
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
149
|
+
if (typeof key !== "string") return false;
|
|
150
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
151
|
+
|
|
152
|
+
if (descriptor === undefined || !("value" in descriptor)) return false;
|
|
153
|
+
pending.push(descriptor.value);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return true;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const validateBatchShape = Schema.decodeUnknownSync(
|
|
124
161
|
Schema.Struct({
|
|
125
162
|
batchId: CanonicalBatch.fields.batchId,
|
|
126
163
|
producerId: CanonicalBatch.fields.producerId,
|
|
164
|
+
records: Schema.NonEmptyArray(Schema.Unknown).check(Schema.isMaxLength(256)),
|
|
127
165
|
}),
|
|
128
166
|
);
|
|
129
167
|
|
|
130
|
-
const validateBatchCount = Schema.decodeUnknownSync(
|
|
131
|
-
Schema.NonEmptyArray(Schema.Unknown).check(Schema.isMaxLength(256)),
|
|
132
|
-
);
|
|
133
|
-
|
|
134
168
|
const ContinuationBytes = Schema.Struct({
|
|
135
169
|
turnBytes: RunContinuation.fields.turnBytes,
|
|
136
170
|
terminalBytes: RunContinuation.fields.terminalBytes,
|
|
137
171
|
});
|
|
138
172
|
|
|
173
|
+
const decodeExecutionFrontier = Schema.decodeUnknownEffect(
|
|
174
|
+
Schema.Struct({
|
|
175
|
+
canonicalRecords: ExecutionCheckpoint.fields.canonicalRecords,
|
|
176
|
+
throughSequence: ExecutionCheckpoint.fields.throughSequence,
|
|
177
|
+
}),
|
|
178
|
+
);
|
|
179
|
+
|
|
139
180
|
/** One private snapshot for every retry; callers cannot change facts while awaiting the gate. */
|
|
140
181
|
const captureFacts = (batch: CommitBatch) =>
|
|
141
182
|
Effect.try({
|
|
142
|
-
try: () =>
|
|
143
|
-
|
|
183
|
+
try: () =>
|
|
184
|
+
Result.gen(function* () {
|
|
185
|
+
const inputs = batch.records;
|
|
186
|
+
|
|
187
|
+
const { batchId, producerId } = validateBatchShape({
|
|
188
|
+
batchId: batch.batchId,
|
|
189
|
+
producerId: batch.producerId,
|
|
190
|
+
records: inputs,
|
|
191
|
+
});
|
|
144
192
|
|
|
145
|
-
|
|
146
|
-
|
|
193
|
+
const encodings = yield* Result.all(inputs.map(captureRecord));
|
|
194
|
+
const records = encodings.map((record) => record.canonical);
|
|
147
195
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
196
|
+
return Object.freeze(
|
|
197
|
+
CanonicalBatch.make(
|
|
198
|
+
{ batchId, producerId, records: [records[0]!, ...records.slice(1)] },
|
|
199
|
+
{ disableChecks: true },
|
|
200
|
+
),
|
|
201
|
+
);
|
|
202
|
+
}),
|
|
155
203
|
catch: (cause) => failure("Cannot capture canonical progress facts", cause),
|
|
156
|
-
})
|
|
204
|
+
}).pipe(
|
|
205
|
+
Effect.flatMap(Effect.fromResult),
|
|
206
|
+
Effect.mapError((cause) =>
|
|
207
|
+
Schema.is(ThreadStoreError)(cause)
|
|
208
|
+
? cause
|
|
209
|
+
: failure("Cannot capture canonical progress facts", cause),
|
|
210
|
+
),
|
|
211
|
+
);
|
|
157
212
|
|
|
158
213
|
/** Exact UTF-8 wire accounting reuses the append's privately captured Schema encoding. */
|
|
159
|
-
export const canonicalRecordBytes = (record: RecordEnvelope): number =>
|
|
160
|
-
recordEncoding(record)
|
|
214
|
+
export const canonicalRecordBytes = (record: RecordEnvelope): number => {
|
|
215
|
+
const encoded = recordEncoding(record);
|
|
216
|
+
|
|
217
|
+
if (Result.isFailure(encoded)) {
|
|
218
|
+
// oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- Public synchronous byte-accounting validation must reject malformed records before returning a number.
|
|
219
|
+
throw encoded.failure.cause ?? new RangeError(encoded.failure.message);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return encoded.success.bytes;
|
|
223
|
+
};
|
|
161
224
|
|
|
162
225
|
export type { ProgressAppendRecord } from "./internal/record-encoding.ts";
|
|
163
226
|
|
|
164
227
|
/** Capture before acquiring the mutation owner; summaries never cross a wire boundary. */
|
|
165
228
|
export const prepareProgressAppend = (
|
|
166
229
|
records: ReadonlyArray<RecordEnvelope>,
|
|
167
|
-
): ReadonlyArray<ProgressAppendRecord> =>
|
|
168
|
-
|
|
230
|
+
): ReadonlyArray<ProgressAppendRecord> => {
|
|
231
|
+
const encodings = Result.all(records.map(captureRecord));
|
|
232
|
+
|
|
233
|
+
if (Result.isFailure(encodings)) {
|
|
234
|
+
// oxlint-disable-next-line effect/no-untyped-throw, effect/no-native-error -- Public synchronous progress construction must reject malformed records before acquiring a mutation owner.
|
|
235
|
+
throw encodings.failure.cause ?? new RangeError(encodings.failure.message);
|
|
236
|
+
}
|
|
169
237
|
|
|
170
|
-
|
|
171
|
-
|
|
238
|
+
return Object.freeze(encodings.success.map((record) => record.progress));
|
|
239
|
+
};
|
|
172
240
|
|
|
173
241
|
/** These values belong to the active Run, not its permanent conversation history. */
|
|
174
242
|
export const isOperationalRecord = ({ payload }: RecordEnvelope): boolean =>
|
|
@@ -643,9 +711,27 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
643
711
|
let results = new Map(previous?.results);
|
|
644
712
|
let childResults = new Map(previous?.childResults);
|
|
645
713
|
let completionBytes = previous?.completionBytes;
|
|
714
|
+
let factBytes = 0;
|
|
715
|
+
let turn = previous?.continuation.turn ?? 1;
|
|
716
|
+
let usageCharge = 0;
|
|
717
|
+
let closingBytes = 0;
|
|
718
|
+
let closingCount = 0;
|
|
646
719
|
|
|
647
720
|
for (const fact of facts) {
|
|
648
721
|
const payload = fact.payload;
|
|
722
|
+
const captured = recordEncoding(fact);
|
|
723
|
+
|
|
724
|
+
if (Result.isFailure(captured))
|
|
725
|
+
return yield* failure("Cannot account canonical progress facts", captured.failure);
|
|
726
|
+
const encoded = captured.success;
|
|
727
|
+
|
|
728
|
+
factBytes += encoded.bytes;
|
|
729
|
+
if ("turn" in payload) turn = Math.max(turn, payload.turn);
|
|
730
|
+
usageCharge += encoded.progress.terminalUsageBytes;
|
|
731
|
+
if (encoded.progress.terminal) {
|
|
732
|
+
closingBytes += encoded.bytes;
|
|
733
|
+
closingCount++;
|
|
734
|
+
}
|
|
649
735
|
|
|
650
736
|
switch (payload._tag) {
|
|
651
737
|
case "RunStarted":
|
|
@@ -654,7 +740,7 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
654
740
|
case "RunContextRecorded":
|
|
655
741
|
if (savedContext !== undefined)
|
|
656
742
|
return yield* failure("A Run's original context cannot be replaced");
|
|
657
|
-
savedContext =
|
|
743
|
+
savedContext = EvidenceReference.make({ recordId: fact.recordId });
|
|
658
744
|
position = "awaiting-model";
|
|
659
745
|
break;
|
|
660
746
|
case "ModelResponseRecorded": {
|
|
@@ -663,10 +749,27 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
663
749
|
if (payload.turn !== accounting.committedTurns + 1)
|
|
664
750
|
return yield* failure("Canonical Turn progress must advance once");
|
|
665
751
|
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
);
|
|
752
|
+
const promptInput = payload.messages;
|
|
753
|
+
const retainedPrompt = responsePrompts.get(payload);
|
|
669
754
|
|
|
755
|
+
const messages =
|
|
756
|
+
retainedPrompt ??
|
|
757
|
+
(yield* decodeResponsePrompt(promptInput).pipe(
|
|
758
|
+
Effect.mapError((cause) => failure("Invalid model evidence", cause)),
|
|
759
|
+
));
|
|
760
|
+
|
|
761
|
+
if (retainedPrompt === undefined) {
|
|
762
|
+
const property = Object.getOwnPropertyDescriptor(payload, "messages");
|
|
763
|
+
|
|
764
|
+
if (
|
|
765
|
+
Object.isFrozen(payload) &&
|
|
766
|
+
property !== undefined &&
|
|
767
|
+
"value" in property &&
|
|
768
|
+
property.value === promptInput &&
|
|
769
|
+
isFrozenJsonData(promptInput)
|
|
770
|
+
)
|
|
771
|
+
responsePrompts.set(payload, messages);
|
|
772
|
+
}
|
|
670
773
|
responsePrompt = messages;
|
|
671
774
|
|
|
672
775
|
const calls = messages.content.flatMap((message) =>
|
|
@@ -678,20 +781,20 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
678
781
|
const summary =
|
|
679
782
|
payload.modelUsage === undefined
|
|
680
783
|
? undefined
|
|
681
|
-
: yield*
|
|
784
|
+
: yield* continuationUsage(payload.modelUsage).pipe(
|
|
682
785
|
Effect.mapError((cause) => failure("Invalid usage evidence", cause)),
|
|
683
786
|
);
|
|
684
787
|
|
|
685
788
|
accounting.committedTurns = payload.turn;
|
|
686
789
|
accounting.toolCalls += calls.length;
|
|
687
790
|
accounting.modelCalls += summary?.modelCalls ?? 1;
|
|
688
|
-
accounting.inputTokens += summary?.inputTokens
|
|
689
|
-
accounting.outputTokens += summary?.outputTokens
|
|
791
|
+
accounting.inputTokens += summary?.inputTokens ?? payload.inputTokens ?? 0;
|
|
792
|
+
accounting.outputTokens += summary?.outputTokens ?? payload.outputTokens ?? 0;
|
|
690
793
|
accounting.costMicrousd += summary?.costMicrousd ?? payload.costMicrousd ?? 0;
|
|
691
|
-
accounting.lastInputTokens = summary?.inputTokens
|
|
692
|
-
accounting.lastOutputTokens = summary?.outputTokens
|
|
794
|
+
accounting.lastInputTokens = summary?.inputTokens ?? payload.inputTokens ?? 0;
|
|
795
|
+
accounting.lastOutputTokens = summary?.outputTokens ?? payload.outputTokens ?? 0;
|
|
693
796
|
accounting.unobservedModelCalls += payload.unobservedModelCalls ?? 0;
|
|
694
|
-
latestResponse =
|
|
797
|
+
latestResponse = EvidenceReference.make({ recordId: fact.recordId });
|
|
695
798
|
response = payload;
|
|
696
799
|
results = new Map();
|
|
697
800
|
childResults = new Map();
|
|
@@ -754,14 +857,14 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
754
857
|
if (payload.restart !== (accounting.modelRestarts ?? 0) + 1)
|
|
755
858
|
return yield* failure("Model restart progress must advance once");
|
|
756
859
|
|
|
757
|
-
const summary = yield*
|
|
860
|
+
const summary = yield* continuationUsage(payload.modelUsage).pipe(
|
|
758
861
|
Effect.mapError((cause) => failure("Invalid cancelled model usage", cause)),
|
|
759
862
|
);
|
|
760
863
|
|
|
761
864
|
accounting.modelRestarts = payload.restart;
|
|
762
865
|
accounting.modelCalls += summary.modelCalls;
|
|
763
|
-
accounting.inputTokens += summary.inputTokens
|
|
764
|
-
accounting.outputTokens += summary.outputTokens
|
|
866
|
+
accounting.inputTokens += summary.inputTokens;
|
|
867
|
+
accounting.outputTokens += summary.outputTokens;
|
|
765
868
|
accounting.costMicrousd += summary.costMicrousd;
|
|
766
869
|
accounting.unobservedModelCalls += payload.unobservedModelCalls;
|
|
767
870
|
break;
|
|
@@ -775,12 +878,12 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
775
878
|
? 0
|
|
776
879
|
: utf8ByteLength(JSON.stringify(payload.runDisposition)))
|
|
777
880
|
: undefined;
|
|
778
|
-
terminal =
|
|
881
|
+
terminal = EvidenceReference.make({ recordId: fact.recordId });
|
|
779
882
|
position = "settling";
|
|
780
883
|
break;
|
|
781
884
|
case "SubmissionSettled":
|
|
782
885
|
if (payload.submissionId !== submissionId) break;
|
|
783
|
-
terminal =
|
|
886
|
+
terminal = EvidenceReference.make({ recordId: fact.recordId });
|
|
784
887
|
position = "settled";
|
|
785
888
|
if (payload.usageSummary !== undefined) {
|
|
786
889
|
accounting.modelCalls = payload.usageSummary.modelCalls;
|
|
@@ -802,6 +905,7 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
802
905
|
) {
|
|
803
906
|
const messages =
|
|
804
907
|
responsePrompt ??
|
|
908
|
+
responsePrompts.get(response) ??
|
|
805
909
|
(yield* decodeResponsePrompt(response.messages).pipe(
|
|
806
910
|
Effect.mapError((cause) => failure("Invalid batch evidence", cause)),
|
|
807
911
|
));
|
|
@@ -837,22 +941,13 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
837
941
|
if (previous?.continuation.position === "settled") position = "settled";
|
|
838
942
|
else if (previous?.continuation.position === "settling" && position !== "settled")
|
|
839
943
|
position = "settling";
|
|
840
|
-
const factBytes = facts.reduce((bytes, fact) => bytes + canonicalRecordBytes(fact), 0);
|
|
841
|
-
|
|
842
|
-
const turn = facts.reduce(
|
|
843
|
-
(current, fact) => ("turn" in fact.payload ? Math.max(current, fact.payload.turn) : current),
|
|
844
|
-
previous?.continuation.turn ?? 1,
|
|
845
|
-
);
|
|
846
944
|
|
|
847
945
|
const turnBase =
|
|
848
946
|
(previous?.continuation.turn === turn ? previous.continuation.turnBytes : initialBytes) +
|
|
849
947
|
factBytes;
|
|
850
948
|
|
|
851
|
-
const usageCharge = factUsageCharge(facts);
|
|
852
949
|
const terminalUsageBytes = (previous?.continuation.terminalUsageBytes ?? 0) + usageCharge;
|
|
853
950
|
|
|
854
|
-
const closing = facts.filter(isTerminalBudgetFact);
|
|
855
|
-
|
|
856
951
|
return {
|
|
857
952
|
accounting,
|
|
858
953
|
savedContext,
|
|
@@ -869,11 +964,9 @@ const advanceFacts = Effect.fnUntraced(function* (
|
|
|
869
964
|
turnBase,
|
|
870
965
|
usageCharge,
|
|
871
966
|
terminalUsageBytes,
|
|
872
|
-
terminalBytes:
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
terminalRecords: (previous?.continuation.terminalRecords ?? 0) + closing.length,
|
|
876
|
-
closing: closing.length > 0,
|
|
967
|
+
terminalBytes: (previous?.continuation.terminalBytes ?? 0) + closingBytes,
|
|
968
|
+
terminalRecords: (previous?.continuation.terminalRecords ?? 0) + closingCount,
|
|
969
|
+
closing: closingCount > 0,
|
|
877
970
|
};
|
|
878
971
|
});
|
|
879
972
|
|
|
@@ -951,10 +1044,17 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
951
1044
|
deploymentId: DeploymentId,
|
|
952
1045
|
) {
|
|
953
1046
|
const reader = yield* ThreadReader;
|
|
954
|
-
const crypto = yield* Crypto.Crypto;
|
|
955
1047
|
const gate = yield* Semaphore.make(1);
|
|
956
1048
|
const cached = new Map<RunId, ProgressState>();
|
|
957
1049
|
|
|
1050
|
+
let verifiedEmpty:
|
|
1051
|
+
| {
|
|
1052
|
+
readonly runId: RunId;
|
|
1053
|
+
readonly through: CanonicalSequence;
|
|
1054
|
+
readonly writer: CurrentRunWriter["Service"];
|
|
1055
|
+
}
|
|
1056
|
+
| undefined;
|
|
1057
|
+
|
|
958
1058
|
const reservations = new Map<
|
|
959
1059
|
RecordId,
|
|
960
1060
|
{
|
|
@@ -967,16 +1067,10 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
967
1067
|
|
|
968
1068
|
const stagedUsage = new Map<RunId, number>();
|
|
969
1069
|
|
|
970
|
-
const provide = <A, E>(effect: Effect.Effect<A, E, ThreadReader
|
|
971
|
-
|
|
972
|
-
Effect.provideService(ThreadReader, reader),
|
|
973
|
-
Effect.provideService(Crypto.Crypto, crypto),
|
|
974
|
-
);
|
|
975
|
-
|
|
976
|
-
const loadState = Effect.fnUntraced(function* (runId: RunId, after: CanonicalSequence) {
|
|
977
|
-
const retained = cached.get(runId);
|
|
1070
|
+
const provide = <A, E>(effect: Effect.Effect<A, E, ThreadReader>) =>
|
|
1071
|
+
Effect.provideService(effect, ThreadReader, reader);
|
|
978
1072
|
|
|
979
|
-
|
|
1073
|
+
const loadUncachedState = Effect.fnUntraced(function* (runId: RunId, after: CanonicalSequence) {
|
|
980
1074
|
const loaded = yield* provide(readContinuation(threadId, runId, after));
|
|
981
1075
|
|
|
982
1076
|
if (Option.isNone(loaded)) return undefined;
|
|
@@ -1095,11 +1189,14 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1095
1189
|
};
|
|
1096
1190
|
});
|
|
1097
1191
|
|
|
1098
|
-
const checkFutureShapes = (
|
|
1192
|
+
const checkFutureShapes = (
|
|
1193
|
+
state: ProgressState,
|
|
1194
|
+
cursorBytes?: number,
|
|
1195
|
+
): Effect.Effect<void, ThreadStoreError> => {
|
|
1099
1196
|
const progress = state.continuation;
|
|
1100
1197
|
|
|
1101
1198
|
if (progress.position === "settled") return Effect.void;
|
|
1102
|
-
const size = canonicalRecordBytes(state.record);
|
|
1199
|
+
const size = cursorBytes ?? canonicalRecordBytes(state.record);
|
|
1103
1200
|
const textBytes = (value: string) => utf8ByteLength(JSON.stringify(value));
|
|
1104
1201
|
const refBytes = (value: EvidenceReference) => utf8ByteLength(JSON.stringify(value));
|
|
1105
1202
|
|
|
@@ -1213,14 +1310,17 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1213
1310
|
return Effect.void;
|
|
1214
1311
|
};
|
|
1215
1312
|
|
|
1216
|
-
const prepare = Effect.fnUntraced(function* (
|
|
1313
|
+
const prepare = Effect.fnUntraced(function* (
|
|
1314
|
+
batch: CanonicalBatch,
|
|
1315
|
+
after: CanonicalSequence,
|
|
1316
|
+
mode: "commit" | "preflight" = "commit",
|
|
1317
|
+
) {
|
|
1217
1318
|
if (batch.records.some((record) => record.payload._tag === "RunContinuation"))
|
|
1218
1319
|
return yield* failure("A caller cannot supply interpreter progress to the progress writer");
|
|
1219
1320
|
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
});
|
|
1321
|
+
// Every private caller passes captureFacts' owned snapshot. Keep a mutable
|
|
1322
|
+
// list for settlement accounting without capturing that snapshot a second time.
|
|
1323
|
+
const ownedRecords = [...batch.records];
|
|
1224
1324
|
|
|
1225
1325
|
const groups = new Map<RunId, Array<RecordEnvelope>>();
|
|
1226
1326
|
|
|
@@ -1234,9 +1334,19 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1234
1334
|
}
|
|
1235
1335
|
const executions: Array<ExecutionUpdate> = [];
|
|
1236
1336
|
const accepted = new Map<RunId, ProgressState>();
|
|
1337
|
+
let executionCount = 0;
|
|
1237
1338
|
|
|
1238
1339
|
for (const [runId, facts] of groups) {
|
|
1239
|
-
const
|
|
1340
|
+
const empty =
|
|
1341
|
+
verifiedEmpty?.runId === runId &&
|
|
1342
|
+
verifiedEmpty.through === after &&
|
|
1343
|
+
// Settlement preparation need not have a Run writer; absence disables reuse.
|
|
1344
|
+
verifiedEmpty.writer ===
|
|
1345
|
+
Option.getOrUndefined(yield* Effect.serviceOption(CurrentRunWriter));
|
|
1346
|
+
|
|
1347
|
+
const previous = empty
|
|
1348
|
+
? undefined
|
|
1349
|
+
: (cached.get(runId) ?? (yield* loadUncachedState(runId, after)));
|
|
1240
1350
|
|
|
1241
1351
|
let original = facts.find(
|
|
1242
1352
|
(record) =>
|
|
@@ -1277,7 +1387,7 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1277
1387
|
if (previous === undefined && original === undefined)
|
|
1278
1388
|
return yield* failure("Run has no accepted original input");
|
|
1279
1389
|
|
|
1280
|
-
if (previous === undefined) {
|
|
1390
|
+
if (previous === undefined && !empty) {
|
|
1281
1391
|
const settled = yield* provide(
|
|
1282
1392
|
getRecord({
|
|
1283
1393
|
threadId,
|
|
@@ -1337,12 +1447,17 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1337
1447
|
|
|
1338
1448
|
if (payload._tag !== "SubmissionSettled" || payload.runId !== runId) continue;
|
|
1339
1449
|
|
|
1340
|
-
const retained =
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1450
|
+
const retained = yield* Effect.fromResult(
|
|
1451
|
+
captureRecord(
|
|
1452
|
+
RecordEnvelope.make({
|
|
1453
|
+
...fact,
|
|
1454
|
+
payload: { ...payload, historyRecordCount: canonicalRecords },
|
|
1455
|
+
}),
|
|
1456
|
+
),
|
|
1457
|
+
).pipe(
|
|
1458
|
+
Effect.map((record) => record.canonical),
|
|
1459
|
+
Effect.mapError((cause) => failure("Cannot capture canonical progress facts", cause)),
|
|
1460
|
+
);
|
|
1346
1461
|
|
|
1347
1462
|
facts[index] = retained;
|
|
1348
1463
|
ownedRecords[ownedRecords.indexOf(fact)] = retained;
|
|
@@ -1353,9 +1468,9 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1353
1468
|
? previous.continuation.originalInput
|
|
1354
1469
|
: original === undefined
|
|
1355
1470
|
? yield* failure("Run progress has no original input")
|
|
1356
|
-
:
|
|
1471
|
+
: EvidenceReference.make({ recordId: original.recordId });
|
|
1357
1472
|
|
|
1358
|
-
const next = yield*
|
|
1473
|
+
const next = yield* advanceFacts(previous, facts, submissionId, initialBytes);
|
|
1359
1474
|
|
|
1360
1475
|
const {
|
|
1361
1476
|
accounting,
|
|
@@ -1391,7 +1506,7 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1391
1506
|
...(savedContext === undefined ? {} : { savedContext }),
|
|
1392
1507
|
...(latestResponse === undefined ? {} : { latestResponse }),
|
|
1393
1508
|
...(terminal === undefined ? {} : { terminal }),
|
|
1394
|
-
lastFact:
|
|
1509
|
+
lastFact: EvidenceReference.make({ recordId: last.recordId }),
|
|
1395
1510
|
position,
|
|
1396
1511
|
accounting,
|
|
1397
1512
|
}).pipe(
|
|
@@ -1451,23 +1566,63 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1451
1566
|
);
|
|
1452
1567
|
|
|
1453
1568
|
// Every other field was checked above; byte accounting changes only these counters.
|
|
1454
|
-
continuation =
|
|
1569
|
+
continuation = RunContinuation.make(
|
|
1455
1570
|
{ ...continuation, ...checkedBytes },
|
|
1456
1571
|
{ disableChecks: true },
|
|
1457
1572
|
);
|
|
1458
1573
|
|
|
1459
|
-
const
|
|
1460
|
-
|
|
1461
|
-
|
|
1574
|
+
const proposedRecord = RecordEnvelope.make(
|
|
1575
|
+
{ ...header, payload: continuation },
|
|
1576
|
+
{ disableChecks: true },
|
|
1577
|
+
);
|
|
1462
1578
|
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
if (
|
|
1466
|
-
return yield* failure("Continuation byte accounting differs from its Schema encoding");
|
|
1467
|
-
if (canonicalRecordBytes(record) > MAX_RUN_CONTINUATION_BYTES)
|
|
1579
|
+
const cursorBytes = turnBytes - turnBase;
|
|
1580
|
+
|
|
1581
|
+
if (cursorBytes > MAX_RUN_CONTINUATION_BYTES)
|
|
1468
1582
|
return yield* capacityFailure(
|
|
1469
1583
|
"Encoded continuation exceeds 8192 bytes including its envelope",
|
|
1470
1584
|
);
|
|
1585
|
+
executionCount++;
|
|
1586
|
+
if (
|
|
1587
|
+
mode === "preflight" &&
|
|
1588
|
+
previous?.checkpoint !== undefined &&
|
|
1589
|
+
facts.every(({ payload }) => payload._tag === "ModelResponseRecorded")
|
|
1590
|
+
) {
|
|
1591
|
+
// The payload and header are validated, and operational facts are unchanged.
|
|
1592
|
+
// Dispatch needs their capacity proof; only a commit needs checkpoint wire.
|
|
1593
|
+
yield* decodeExecutionFrontier({
|
|
1594
|
+
canonicalRecords,
|
|
1595
|
+
throughSequence: after + ownedRecords.filter((fact) => !isOperationalRecord(fact)).length,
|
|
1596
|
+
}).pipe(Effect.mapError((cause) => failure("Active execution exceeds its bounds", cause)));
|
|
1597
|
+
|
|
1598
|
+
const state: ProgressState = {
|
|
1599
|
+
continuation,
|
|
1600
|
+
record: proposedRecord,
|
|
1601
|
+
...(response === undefined ? {} : { response }),
|
|
1602
|
+
results,
|
|
1603
|
+
childResults,
|
|
1604
|
+
...(completionBytes === undefined ? {} : { completionBytes }),
|
|
1605
|
+
};
|
|
1606
|
+
|
|
1607
|
+
yield* checkCapacity(
|
|
1608
|
+
state,
|
|
1609
|
+
new Set(batch.records.map(({ recordId }) => recordId)),
|
|
1610
|
+
undefined,
|
|
1611
|
+
usageCharge,
|
|
1612
|
+
);
|
|
1613
|
+
yield* checkFutureShapes(state, cursorBytes);
|
|
1614
|
+
continue;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
const record = yield* Effect.fromResult(captureRecord(proposedRecord)).pipe(
|
|
1618
|
+
Effect.map((record) => record.canonical),
|
|
1619
|
+
Effect.mapError((cause) => failure("Cannot capture canonical progress facts", cause)),
|
|
1620
|
+
);
|
|
1621
|
+
|
|
1622
|
+
if (!isExecutionProgressRecord(record))
|
|
1623
|
+
return yield* failure("Captured execution has no Run continuation");
|
|
1624
|
+
if (canonicalRecordBytes(record) !== cursorBytes)
|
|
1625
|
+
return yield* failure("Continuation byte accounting differs from its Schema encoding");
|
|
1471
1626
|
|
|
1472
1627
|
const operational = new Map(
|
|
1473
1628
|
(previous?.checkpoint?.operational ?? []).map((fact) => [fact.recordId, fact]),
|
|
@@ -1478,7 +1633,15 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1478
1633
|
for (const fact of changed) {
|
|
1479
1634
|
const prior = operational.get(fact.recordId);
|
|
1480
1635
|
|
|
1481
|
-
if (
|
|
1636
|
+
if (
|
|
1637
|
+
prior !== undefined &&
|
|
1638
|
+
(yield* Effect.fromResult(recordEncoding(prior)).pipe(
|
|
1639
|
+
Effect.mapError((cause) => failure("Cannot encode active Run fact", cause)),
|
|
1640
|
+
)).json !==
|
|
1641
|
+
(yield* Effect.fromResult(recordEncoding(fact)).pipe(
|
|
1642
|
+
Effect.mapError((cause) => failure("Cannot encode active Run fact", cause)),
|
|
1643
|
+
)).json
|
|
1644
|
+
)
|
|
1482
1645
|
return yield* failure("An active Run fact cannot change after becoming durable");
|
|
1483
1646
|
operational.set(fact.recordId, fact);
|
|
1484
1647
|
}
|
|
@@ -1535,10 +1698,10 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1535
1698
|
accepted.set(runId, state);
|
|
1536
1699
|
}
|
|
1537
1700
|
|
|
1538
|
-
if (ownedRecords.length +
|
|
1701
|
+
if (ownedRecords.length + executionCount > 256)
|
|
1539
1702
|
return yield* failure("Progress and facts exceed the atomic batch bound");
|
|
1540
1703
|
|
|
1541
|
-
const prepared =
|
|
1704
|
+
const prepared = CommitBatch.make(
|
|
1542
1705
|
{
|
|
1543
1706
|
...batch,
|
|
1544
1707
|
records: ownedRecords.filter((fact) => !isOperationalRecord(fact)),
|
|
@@ -1566,14 +1729,11 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1566
1729
|
};
|
|
1567
1730
|
});
|
|
1568
1731
|
|
|
1569
|
-
const tail = Effect.
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
return (yield* writer.tail).sequence;
|
|
1576
|
-
});
|
|
1732
|
+
const tail = Effect.flatMap(CurrentRunWriter, (writer) =>
|
|
1733
|
+
writer.threadId !== threadId
|
|
1734
|
+
? Effect.fail(failure("Progress writer belongs to another Thread"))
|
|
1735
|
+
: Effect.map(writer.tail, (position) => position.sequence),
|
|
1736
|
+
);
|
|
1577
1737
|
|
|
1578
1738
|
const commitCaptured = Effect.fnUntraced(
|
|
1579
1739
|
function* (batch: CanonicalBatch) {
|
|
@@ -1672,7 +1832,7 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1672
1832
|
|
|
1673
1833
|
yield* prepare(yield* captureFacts(probe), after);
|
|
1674
1834
|
const recordId = probe.records[0].recordId;
|
|
1675
|
-
const state = yield*
|
|
1835
|
+
const state = cached.get(runId) ?? (yield* loadUncachedState(runId, after));
|
|
1676
1836
|
|
|
1677
1837
|
if (state === undefined) return yield* failure("Dispatch has no canonical Run progress");
|
|
1678
1838
|
if (reservations.has(recordId))
|
|
@@ -1699,7 +1859,7 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1699
1859
|
|
|
1700
1860
|
const owned = yield* captureFacts(batch);
|
|
1701
1861
|
|
|
1702
|
-
yield* prepare(owned, after);
|
|
1862
|
+
yield* prepare(owned, after, "preflight");
|
|
1703
1863
|
|
|
1704
1864
|
const response = owned.records.find(
|
|
1705
1865
|
(record) => record.payload._tag === "ModelResponseRecorded",
|
|
@@ -1707,7 +1867,10 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1707
1867
|
|
|
1708
1868
|
if (response === undefined || response.payload._tag !== "ModelResponseRecorded")
|
|
1709
1869
|
return yield* failure("Deferred dispatch has no response");
|
|
1710
|
-
|
|
1870
|
+
|
|
1871
|
+
const progress =
|
|
1872
|
+
cached.get(response.payload.runId) ??
|
|
1873
|
+
(yield* loadUncachedState(response.payload.runId, after));
|
|
1711
1874
|
|
|
1712
1875
|
if (progress === undefined) return yield* failure("Deferred dispatch has no Run progress");
|
|
1713
1876
|
|
|
@@ -1741,16 +1904,33 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1741
1904
|
}),
|
|
1742
1905
|
);
|
|
1743
1906
|
|
|
1907
|
+
const checkState = (state: ProgressState | undefined, recovered: boolean) => {
|
|
1908
|
+
if (state === undefined) return Effect.fail(failure("Execution has no canonical Run progress"));
|
|
1909
|
+
|
|
1910
|
+
const capacity = () =>
|
|
1911
|
+
state.continuation.position === "settling" || state.continuation.position === "settled"
|
|
1912
|
+
? Effect.void
|
|
1913
|
+
: checkCapacity(state);
|
|
1914
|
+
|
|
1915
|
+
// Accepted states were shape-checked, but usage and reservations remain live inputs.
|
|
1916
|
+
return recovered ? Effect.andThen(checkFutureShapes(state), capacity) : capacity();
|
|
1917
|
+
};
|
|
1918
|
+
|
|
1744
1919
|
const check = (runId: RunId) =>
|
|
1745
1920
|
gate.withPermits(1)(
|
|
1746
|
-
Effect.
|
|
1747
|
-
|
|
1921
|
+
Effect.flatMap(CurrentRunWriter, (writer) => {
|
|
1922
|
+
if (writer.threadId !== threadId)
|
|
1923
|
+
return Effect.fail(failure("Progress writer belongs to another Thread"));
|
|
1748
1924
|
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
if (
|
|
1752
|
-
|
|
1753
|
-
|
|
1925
|
+
const retained = cached.get(runId);
|
|
1926
|
+
|
|
1927
|
+
if (retained !== undefined) return checkState(retained, false);
|
|
1928
|
+
|
|
1929
|
+
return Effect.flatMap(writer.tail, (position) =>
|
|
1930
|
+
Effect.flatMap(loadUncachedState(runId, position.sequence), (state) =>
|
|
1931
|
+
checkState(state, true),
|
|
1932
|
+
),
|
|
1933
|
+
);
|
|
1754
1934
|
}),
|
|
1755
1935
|
);
|
|
1756
1936
|
|
|
@@ -1760,6 +1940,29 @@ export const makeProgressWriter = Effect.fnUntraced(function* (
|
|
|
1760
1940
|
reserve,
|
|
1761
1941
|
defer,
|
|
1762
1942
|
check,
|
|
1943
|
+
/** Internal read view immediately after this writer's acknowledged commit, while
|
|
1944
|
+
* holding its initialization gates. Never authority across ownership or writes. */
|
|
1945
|
+
acceptedCheckpoint: (runId: RunId) => cached.get(runId)?.checkpoint,
|
|
1946
|
+
/** Scope a verified empty execution/evidence view to one owned initialization body.
|
|
1947
|
+
* The caller holds progress+mutation gates; a changed writer or tail never reuses it. */
|
|
1948
|
+
withVerifiedEmptyRun: <A, E, R>(
|
|
1949
|
+
runId: RunId,
|
|
1950
|
+
through: CanonicalSequence,
|
|
1951
|
+
body: Effect.Effect<A, E, R>,
|
|
1952
|
+
): Effect.Effect<A, E, R | CurrentRunWriter> =>
|
|
1953
|
+
Effect.flatMap(CurrentRunWriter, (writer) => {
|
|
1954
|
+
const view = { runId, through, writer };
|
|
1955
|
+
|
|
1956
|
+
verifiedEmpty = view;
|
|
1957
|
+
|
|
1958
|
+
return body.pipe(
|
|
1959
|
+
Effect.ensuring(
|
|
1960
|
+
Effect.sync(() => {
|
|
1961
|
+
if (verifiedEmpty === view) verifiedEmpty = undefined;
|
|
1962
|
+
}),
|
|
1963
|
+
),
|
|
1964
|
+
);
|
|
1965
|
+
}),
|
|
1763
1966
|
stageUsage: (runId: RunId, bytes: number) => {
|
|
1764
1967
|
if (bytes === 0) stagedUsage.delete(runId);
|
|
1765
1968
|
else stagedUsage.set(runId, bytes);
|