effect-agent 0.1.0-beta.100 → 0.1.0-beta.101
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/{DurableAgentRuntime-BE_OjQjz.mjs → DurableAgentRuntime-HOZ3AeSi.mjs} +166 -101
- package/dist/DurableAgentRuntime-HOZ3AeSi.mjs.map +1 -0
- package/dist/{EventSource-EKNxvkLe.d.mts → EventSource-K7XUzurY.d.mts} +3 -3
- package/dist/{PreparedInputAdmission-D0yepgfa.d.mts → PreparedInputAdmission-KLk5rGFI.d.mts} +4 -4
- package/dist/{Records-Uh_ktvNK.d.mts → Records-Bidb7ByL.d.mts} +173 -8
- package/dist/{Records-DR1xtbXY.mjs → Records-D8167fHn.mjs} +4 -2
- package/dist/{Records-DR1xtbXY.mjs.map → Records-D8167fHn.mjs.map} +1 -1
- package/dist/{RunJournal-DNs3PM4K.mjs → RunJournal-srpbEBEy.mjs} +25 -4
- package/dist/RunJournal-srpbEBEy.mjs.map +1 -0
- package/dist/{Schedule-CVNtnIpG.d.mts → Schedule-Cy9up8Uf.d.mts} +2 -2
- package/dist/{Scheduling-HFH0pST1.mjs → Scheduling-CHCsSCGo.mjs} +2 -2
- package/dist/{Scheduling-HFH0pST1.mjs.map → Scheduling-CHCsSCGo.mjs.map} +1 -1
- package/dist/{Subscription-D94jLq3n.d.mts → Subscription-CHyoQelH.d.mts} +3 -3
- package/dist/{SubscriptionInput-CfefvQng.d.mts → SubscriptionInput-DqrHW-Ja.d.mts} +3 -3
- package/dist/{agent-registration-cXpB8cBU.mjs → agent-registration-ByeHejH3.mjs} +2 -2
- package/dist/{agent-registration-cXpB8cBU.mjs.map → agent-registration-ByeHejH3.mjs.map} +1 -1
- package/dist/durable/ActivityStore.d.mts +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 +1 -1
- package/dist/durable/Digest.d.mts +1 -1
- package/dist/durable/Digest.mjs +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +1 -1
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/EventSource.mjs +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/GitHubWorkflowSource.mjs +1 -1
- package/dist/durable/MessageDelivery.d.mts +348 -8
- package/dist/durable/MessageDelivery.mjs +38 -4
- package/dist/durable/MessageDelivery.mjs.map +1 -1
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +1 -1
- package/dist/durable/MessageDeliveryStoreConformance.mjs +31 -4
- package/dist/durable/MessageDeliveryStoreConformance.mjs.map +1 -1
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PersistentHistory.mjs +2 -2
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/Records.d.mts +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/RunJournal.d.mts +2 -2
- package/dist/durable/RunJournal.mjs +2 -2
- package/dist/durable/Schedule.d.mts +1 -1
- package/dist/durable/Schedule.mjs +1 -1
- package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
- package/dist/durable/ScheduleStoreConformance.mjs +1 -1
- package/dist/durable/ScheduleTransition.d.mts +1 -1
- package/dist/durable/ScheduleTransition.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +2 -2
- package/dist/durable/Scheduling.mjs +1 -1
- package/dist/durable/SqlMessageDeliveryStore.d.mts +3 -0
- package/dist/durable/SqlMessageDeliveryStore.mjs +6 -2
- package/dist/durable/SqlMessageDeliveryStore.mjs.map +1 -1
- package/dist/durable/SqlStorageV2Upgrade.d.mts +2 -2
- package/dist/durable/SqlStorageV2Upgrade.mjs +1 -1
- package/dist/durable/SqlSubscriptionStore.d.mts +2 -2
- package/dist/durable/SqlSubscriptionStore.mjs +1 -1
- package/dist/durable/SqlThreadNativeReads.d.mts +49 -0
- package/dist/durable/SqlThreadNativeReads.mjs +153 -0
- package/dist/durable/SqlThreadNativeReads.mjs.map +1 -0
- package/dist/durable/SubmissionLedger.d.mts +1 -1
- package/dist/durable/SubmissionLedger.mjs +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +1 -1
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/Subscription.mjs +1 -1
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +2 -2
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.mjs +1 -1
- package/dist/durable/SubscriptionTools.d.mts +3 -3
- package/dist/durable/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 +1 -1
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistory.mjs +1 -1
- package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
- package/dist/durable/ThreadContextHistoryProjection.mjs +1 -1
- package/dist/durable/ThreadInvariants.d.mts +1 -1
- package/dist/durable/ThreadInvariants.mjs +2 -2
- package/dist/durable/ThreadProjection.d.mts +1 -1
- package/dist/durable/ThreadProjection.mjs +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadStore.d.mts +2 -2
- package/dist/durable/ThreadStore.mjs +195 -6
- package/dist/durable/ThreadStore.mjs.map +1 -1
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +290 -35
- package/dist/durable/ThreadStoreConformance.mjs.map +1 -1
- package/dist/durable/ToolReconciler.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +1 -1
- package/dist/index.d.mts +8 -7
- package/dist/index.mjs +6 -5
- package/package.json +1 -1
- package/src/durable/DurableAgentRuntime.ts +10 -0
- package/src/durable/MessageDelivery.ts +56 -5
- package/src/durable/MessageDeliveryStoreConformance.ts +48 -1
- package/src/durable/Records.ts +2 -0
- package/src/durable/RunJournal.ts +27 -0
- package/src/durable/SqlMessageDeliveryStore.ts +8 -1
- package/src/durable/SqlThreadNativeReads.ts +256 -0
- package/src/durable/ThreadStore.ts +315 -5
- package/src/durable/ThreadStoreConformance.ts +447 -1
- package/src/durable/internal/messaging-host.ts +67 -29
- package/src/durable/internal/worker-host.ts +180 -58
- package/src/index.ts +2 -0
- package/dist/DurableAgentRuntime-BE_OjQjz.mjs.map +0 -1
- package/dist/RunJournal-DNs3PM4K.mjs.map +0 -1
|
@@ -20,20 +20,20 @@ import { getToolExecutionClass } from "./engine/DurableStep.mjs";
|
|
|
20
20
|
import { CompactionError, ContextCompactor } from "./engine/ContextCompactor.mjs";
|
|
21
21
|
import { RunPolicyUsage } from "./core/RunPolicyUsage.mjs";
|
|
22
22
|
import { AgentUpdateAcceptance, CurrentToolFailureObserver, ModelUsageAccounting, RunContextPreparation, RunContextPreparationPassthrough, RunToolAuthorization, RunToolScheduling } from "./engine/RunOptions.mjs";
|
|
23
|
-
import { $ as ToolCallSettled, B as SubagentJoined, E as ProducerEpoch, G as SubmissionSettledRecord, H as SubagentRequested, I as RunPolicyUsageReserved, J as ToolApprovalDecided, K as SubtreeBudgetReserved, L as RunStartedRecord, O as RecordEnvelope, P as RunDurationExhausted, Q as ToolCallResolved, R as SettlementFailureDiagnostic, T as PersistedJson, U as SubagentStarted, V as SubagentLineageRecorded, W as SubmissionSettled, X as ToolCallPrepared, Y as ToolApprovalRequested, at as WorkerAdmission, c as CanonicalRecordEnvelope, ct as WorkerOrigin, d as CompactionCreated, dt as WorkerReportRefused, et as ToolCallUnknown, ft as WorkerReportingIntent, h as Digest, i as BatchId, it as UserInputRecorded, j as RepairAnnotated, k as RecordId, lt as WorkerOriginRecorded, n as AgentUpdateEmitted, nt as ToolStepSettled, o as CanonicalBatch, ot as WorkerInputCompleted, p as DefinitionDigests, q as ThreadCreated, rt as ToolUnavailable, st as WorkerInputRequested, t as AbortRequested, tt as ToolOperation, u as CanonicalSequence, ut as WorkerReportPrepared, w as PeerMessagePrepared, x as ModelResponseInterrupted } from "./Records-
|
|
23
|
+
import { $ as ToolCallSettled, B as SubagentJoined, E as ProducerEpoch, G as SubmissionSettledRecord, H as SubagentRequested, I as RunPolicyUsageReserved, J as ToolApprovalDecided, K as SubtreeBudgetReserved, L as RunStartedRecord, O as RecordEnvelope, P as RunDurationExhausted, Q as ToolCallResolved, R as SettlementFailureDiagnostic, T as PersistedJson, U as SubagentStarted, V as SubagentLineageRecorded, W as SubmissionSettled, X as ToolCallPrepared, Y as ToolApprovalRequested, at as WorkerAdmission, c as CanonicalRecordEnvelope, ct as WorkerOrigin, d as CompactionCreated, dt as WorkerReportRefused, et as ToolCallUnknown, ft as WorkerReportingIntent, h as Digest, i as BatchId, it as UserInputRecorded, j as RepairAnnotated, k as RecordId, lt as WorkerOriginRecorded, n as AgentUpdateEmitted, nt as ToolStepSettled, o as CanonicalBatch, ot as WorkerInputCompleted, p as DefinitionDigests, q as ThreadCreated, rt as ToolUnavailable, st as WorkerInputRequested, t as AbortRequested, tt as ToolOperation, u as CanonicalSequence, ut as WorkerReportPrepared, w as PeerMessagePrepared, x as ModelResponseInterrupted } from "./Records-D8167fHn.mjs";
|
|
24
24
|
import { AbortCommand, AbortIntentRequest, AdmissionPolicyError, AdmissionRequest, ApprovalDecisionCommand, ApprovalPendingSuspension, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildBudgetReservationRequest, ChildReservationId, ChildSettledNotification, ClaimJoiningRequest, ClaimRequest, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipToken, ParentLinkage, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, RevertJoiningRequest, Settlement, SettlementFinalization, SettlementReservation, SubmissionLedger, SubmissionLookupById, SubmissionLookupByKey, SuspendRequest, UnknownResolutionCommand, WaitingChild, WaitingForChildSuspension, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId } from "./durable/SubmissionLedger.mjs";
|
|
25
25
|
import { DeclaredPendingBatchEvidence, OpenDelegationCallEvidence, OpenToolCallEvidence, PendingApprovalEvidence, RecoveryDecision, RecoveryEvidence, classifyRecovery } from "./durable/Recovery.mjs";
|
|
26
26
|
import { ExplainedEvidence, ExplainedSubmission, ExplainedUnknownCall, IntegrityCheck, IntegrityReport, ObligationEntry, ObligationReport, RecoveryExplanation, RetryRefused, obligationSeverityOf, predictRecoveryDisposition, recoveryDecisionMeaning } from "./durable/Admin.mjs";
|
|
27
27
|
import { digestJson } from "./durable/Digest.mjs";
|
|
28
|
-
import { a as definitionDigestsEqual, c as resolveWorkerBinding, i as compileRegistrations, l as toolReplayContracts, o as makeLegacyWorkerBinding, s as resolveDefinitionBinding, t as BindingUnavailable } from "./agent-registration-
|
|
29
|
-
import {
|
|
28
|
+
import { a as definitionDigestsEqual, c as resolveWorkerBinding, i as compileRegistrations, l as toolReplayContracts, o as makeLegacyWorkerBinding, s as resolveDefinitionBinding, t as BindingUnavailable } from "./agent-registration-ByeHejH3.mjs";
|
|
29
|
+
import { $ as workerOriginRecordId, A as subagentRequestedRecordId, B as toolCallUnknownRecordId, C as runStartedBatchId, D as subagentLineageBatchId, E as subagentJoinedRecordId, F as toolCallPreparedRecordId, G as turnCanonicalBatch, H as toolStepSettledRecordId, I as toolCallResolutionBatchId, J as turnResponseBatch, K as turnIdForRun, L as toolCallResolvedRecordId, M as subagentStartedRecordId, N as toolApprovalDecisionRecordId, O as subagentLineageRecordId, P as toolApprovalRequestRecordId, Q as workerInputRecordId, R as toolCallResultBatchId, S as runIdForSubmission, T as subagentJoinBatchId, U as turnApprovalsBatchId, V as toolStepSettledBatchId, X as turnResultsBatch, a as childIdempotencyKeyFor, b as runDurationBatchId, c as compactionRecordId, d as modelResponseInterruptedBatchId, et as workerReportRecordId, f as modelResponseInterruptedRecordId, g as projectRunJournalStream, i as approvalDecisionBatchId, j as subagentStartedBatchId, k as subagentRequestedBatchId, l as firstWorkerInputRecordId, m as peerMessageRecordId, o as childThreadIdFor, p as modelResponseRecordId, q as turnPreparedBatchId, r as agentUpdateRecordId, s as compactionBatchId, t as RunJournalError, tt as makeJournalMetadata, u as markUnknownBatchId, v as runCompletedRecordId, w as runStartedRecordId, x as runDurationRecordId, y as runCompletionDigest, z as toolCallSettledRecordId } from "./RunJournal-srpbEBEy.mjs";
|
|
30
|
+
import { FencedAppendRequest, LoadCheckpointRequest, MAX_THREAD_EXPORT_RECORDS, SaveRecoveryCheckpointRequest, ThreadCheckpoint, ThreadExportRequest, ThreadMaterialization, ThreadObservation, ThreadRead, ThreadStore, ThreadStoreError, ThreadTailRequest, getRecord, readWorkerState } from "./durable/ThreadStore.mjs";
|
|
30
31
|
import { DurableRuntimeFailpoint } from "./durable/DurableFailpoint.mjs";
|
|
31
32
|
import { ScheduledInputRefused, ScheduledInputRetryable } from "./durable/Schedule.mjs";
|
|
32
33
|
import { PreparedInputAdmission } from "./durable/PreparedInputAdmission.mjs";
|
|
33
34
|
import { PreparedInput } from "./durable/Subscription.mjs";
|
|
34
35
|
import { MessageDeliveryDriver, MessageDeliveryFailpoint, MessageDeliveryRecord, MessageDeliveryStore, messageDeliveryCapacity, messageDeliveryUsesCapacity, prepareMessageDelivery } from "./durable/MessageDelivery.mjs";
|
|
35
36
|
import { n as safeUnknownString, t as inspectForeignDiagnostic } from "./foreign-diagnostic-DBQ1XHKh.mjs";
|
|
36
|
-
import { A as toolApprovalDecisionRecordId, B as turnApprovalsBatchId, C as subagentJoinedRecordId, D as subagentRequestedRecordId, E as subagentRequestedBatchId, F as toolCallResultBatchId, G as turnResponseBatch, H as turnCanonicalBatch, I as toolCallSettledRecordId, L as toolCallUnknownRecordId, M as toolCallPreparedRecordId, N as toolCallResolutionBatchId, O as subagentStartedBatchId, P as toolCallResolvedRecordId, R as toolStepSettledBatchId, S as subagentJoinBatchId, T as subagentLineageRecordId, U as turnIdForRun, W as turnPreparedBatchId, Y as makeJournalMetadata, _ as runDurationBatchId, a as childThreadIdFor, b as runStartedBatchId, c as markUnknownBatchId, d as modelResponseRecordId, g as runCompletionDigest, h as runCompletedRecordId, i as childIdempotencyKeyFor, j as toolApprovalRequestRecordId, k as subagentStartedRecordId, l as modelResponseInterruptedBatchId, o as compactionBatchId, p as projectRunJournalStream, q as turnResultsBatch, r as approvalDecisionBatchId, s as compactionRecordId, t as RunJournalError, u as modelResponseInterruptedRecordId, v as runDurationRecordId, w as subagentLineageBatchId, x as runStartedRecordId, y as runIdForSubmission, z as toolStepSettledRecordId } from "./RunJournal-DNs3PM4K.mjs";
|
|
37
37
|
import { WorkerBudgetAuthorizer, WorkerConcurrencyLimit, WorkerConcurrencyResolver, WorkerHostAuthorizer, WorkerHostConfig, WorkerPolicyResolver } from "./durable/WorkerHost.mjs";
|
|
38
38
|
import { OperationAuthorizationRequest, OperationAuthorizer, OperationDenied } from "./durable/OperationAuthorizer.mjs";
|
|
39
39
|
import { PendingSubmission, SettledSubmission } from "./durable/SubmissionStatus.mjs";
|
|
@@ -42,6 +42,61 @@ import { PreparedToolCallEvidence, ToolReconciler } from "./durable/ToolReconcil
|
|
|
42
42
|
import { WakeScheduler } from "./durable/WakeScheduler.mjs";
|
|
43
43
|
import { Prompt } from "effect/unstable/ai";
|
|
44
44
|
import { Cause, Clock, Context, Crypto, DateTime, Deferred, Duration, Effect, Equal, Layer, Option, Ref, Schedule, Schema, Semaphore, Stream } from "effect";
|
|
45
|
+
//#region src/durable/internal/journal-checkpoint.ts
|
|
46
|
+
/** Retired accounting is additive; the latest Tool batch always remains replayable verbatim. */
|
|
47
|
+
var JournalCheckpointSeed = class extends Schema.Class("@effect-agent/thread/internal/JournalCheckpointSeed")({
|
|
48
|
+
runId: RunId,
|
|
49
|
+
throughSequence: CanonicalSequence,
|
|
50
|
+
firstSequence: Schema.optionalKey(CanonicalSequence),
|
|
51
|
+
toolSelection: Schema.optionalKey(Selection),
|
|
52
|
+
committedTurns: Schema.Natural,
|
|
53
|
+
policyUsage: RunPolicyUsage,
|
|
54
|
+
modelCalls: Schema.Natural,
|
|
55
|
+
unobservedModelCalls: Schema.Natural,
|
|
56
|
+
inputTokens: Schema.Natural,
|
|
57
|
+
outputTokens: Schema.Natural,
|
|
58
|
+
lastInputTokens: Schema.Natural,
|
|
59
|
+
lastOutputTokens: Schema.Natural,
|
|
60
|
+
costMicrousd: Schema.Natural,
|
|
61
|
+
summarizedModelUsage: RunUsageSummary,
|
|
62
|
+
protectedContext: Schema.optionalKey(PersistedJson),
|
|
63
|
+
contextWindowId: Schema.optionalKey(Schema.String),
|
|
64
|
+
frontier: Schema.optionalKey(Schema.Struct({
|
|
65
|
+
sequence: CanonicalSequence,
|
|
66
|
+
tag: Schema.Literals(["ModelResponseRecorded", "ToolCallSettled"])
|
|
67
|
+
})),
|
|
68
|
+
/** Canonical replacement whose covered batches were validated before retirement. */
|
|
69
|
+
compaction: CanonicalRecordEnvelope
|
|
70
|
+
}) {};
|
|
71
|
+
/** A bounded sparse projection, never a canonical log or a submission-ownership record. */
|
|
72
|
+
var RecoveryCheckpointState = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointState")({
|
|
73
|
+
schemaVersion: Schema.Literal(1),
|
|
74
|
+
policyAccountingVersion: Schema.Literal(1),
|
|
75
|
+
submissionId: SubmissionId,
|
|
76
|
+
submissionIds: Schema.Array(SubmissionId).check(Schema.isMaxLength(4096)),
|
|
77
|
+
seed: JournalCheckpointSeed,
|
|
78
|
+
records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(4096))
|
|
79
|
+
}) {};
|
|
80
|
+
var RecoveryCheckpointContents = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointContents")({
|
|
81
|
+
state: RecoveryCheckpointState,
|
|
82
|
+
digest: Digest
|
|
83
|
+
}) {};
|
|
84
|
+
const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@1";
|
|
85
|
+
/**
|
|
86
|
+
* Late evidence can invalidate an old compaction. Such histories use full canonical replay;
|
|
87
|
+
* an omitted run/turn must never be treated as proven absent by a sparse projection.
|
|
88
|
+
*/
|
|
89
|
+
const checkpointSuffixCompatible = (seed, records, retained) => records.every(({ sequence, record: { payload } }) => {
|
|
90
|
+
if ("runId" in payload && payload.runId !== void 0 && payload.runId !== seed.runId) return false;
|
|
91
|
+
if ("turn" in payload && payload.turn <= seed.committedTurns) return false;
|
|
92
|
+
if (payload._tag === "ToolCallSettled" || payload._tag === "ToolCallResolved") return [...retained, ...records].some(({ sequence: declarationSequence, record: { payload: candidate } }) => {
|
|
93
|
+
if (candidate._tag !== "ModelResponseRecorded" || candidate.runId !== payload.runId || candidate.turn <= seed.committedTurns || seed.compaction.record.payload._tag !== "CompactionCreated" || declarationSequence <= seed.compaction.record.payload.coversThrough || declarationSequence >= sequence) return false;
|
|
94
|
+
const decoded = Schema.decodeUnknownOption(Prompt.Prompt)(candidate.messages);
|
|
95
|
+
return Option.isSome(decoded) && decoded.value.content.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "tool-call" && part.id === payload.toolCallId));
|
|
96
|
+
});
|
|
97
|
+
return payload._tag !== "CompactionCreated" || payload.coversThrough >= seed.throughSequence;
|
|
98
|
+
});
|
|
99
|
+
//#endregion
|
|
45
100
|
//#region src/durable/internal/worker-runtime.ts
|
|
46
101
|
/** Canonical worker operations constructed once by the durable coordinator. */
|
|
47
102
|
var WorkerRuntime = class extends Context.Service()("@effect-agent/thread/internal/WorkerRuntime") {};
|
|
@@ -191,61 +246,6 @@ const makeAgentUpdateRuntime = Effect.fn("AgentUpdates.makeDurable")(function* (
|
|
|
191
246
|
};
|
|
192
247
|
});
|
|
193
248
|
//#endregion
|
|
194
|
-
//#region src/durable/internal/journal-checkpoint.ts
|
|
195
|
-
/** Retired accounting is additive; the latest Tool batch always remains replayable verbatim. */
|
|
196
|
-
var JournalCheckpointSeed = class extends Schema.Class("@effect-agent/thread/internal/JournalCheckpointSeed")({
|
|
197
|
-
runId: RunId,
|
|
198
|
-
throughSequence: CanonicalSequence,
|
|
199
|
-
firstSequence: Schema.optionalKey(CanonicalSequence),
|
|
200
|
-
toolSelection: Schema.optionalKey(Selection),
|
|
201
|
-
committedTurns: Schema.Natural,
|
|
202
|
-
policyUsage: RunPolicyUsage,
|
|
203
|
-
modelCalls: Schema.Natural,
|
|
204
|
-
unobservedModelCalls: Schema.Natural,
|
|
205
|
-
inputTokens: Schema.Natural,
|
|
206
|
-
outputTokens: Schema.Natural,
|
|
207
|
-
lastInputTokens: Schema.Natural,
|
|
208
|
-
lastOutputTokens: Schema.Natural,
|
|
209
|
-
costMicrousd: Schema.Natural,
|
|
210
|
-
summarizedModelUsage: RunUsageSummary,
|
|
211
|
-
protectedContext: Schema.optionalKey(PersistedJson),
|
|
212
|
-
contextWindowId: Schema.optionalKey(Schema.String),
|
|
213
|
-
frontier: Schema.optionalKey(Schema.Struct({
|
|
214
|
-
sequence: CanonicalSequence,
|
|
215
|
-
tag: Schema.Literals(["ModelResponseRecorded", "ToolCallSettled"])
|
|
216
|
-
})),
|
|
217
|
-
/** Canonical replacement whose covered batches were validated before retirement. */
|
|
218
|
-
compaction: CanonicalRecordEnvelope
|
|
219
|
-
}) {};
|
|
220
|
-
/** A bounded sparse projection, never a canonical log or a submission-ownership record. */
|
|
221
|
-
var RecoveryCheckpointState = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointState")({
|
|
222
|
-
schemaVersion: Schema.Literal(1),
|
|
223
|
-
policyAccountingVersion: Schema.Literal(1),
|
|
224
|
-
submissionId: SubmissionId,
|
|
225
|
-
submissionIds: Schema.Array(SubmissionId).check(Schema.isMaxLength(4096)),
|
|
226
|
-
seed: JournalCheckpointSeed,
|
|
227
|
-
records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(4096))
|
|
228
|
-
}) {};
|
|
229
|
-
var RecoveryCheckpointContents = class extends Schema.Class("@effect-agent/thread/internal/RecoveryCheckpointContents")({
|
|
230
|
-
state: RecoveryCheckpointState,
|
|
231
|
-
digest: Digest
|
|
232
|
-
}) {};
|
|
233
|
-
const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@1";
|
|
234
|
-
/**
|
|
235
|
-
* Late evidence can invalidate an old compaction. Such histories use full canonical replay;
|
|
236
|
-
* an omitted run/turn must never be treated as proven absent by a sparse projection.
|
|
237
|
-
*/
|
|
238
|
-
const checkpointSuffixCompatible = (seed, records, retained) => records.every(({ sequence, record: { payload } }) => {
|
|
239
|
-
if ("runId" in payload && payload.runId !== void 0 && payload.runId !== seed.runId) return false;
|
|
240
|
-
if ("turn" in payload && payload.turn <= seed.committedTurns) return false;
|
|
241
|
-
if (payload._tag === "ToolCallSettled" || payload._tag === "ToolCallResolved") return [...retained, ...records].some(({ sequence: declarationSequence, record: { payload: candidate } }) => {
|
|
242
|
-
if (candidate._tag !== "ModelResponseRecorded" || candidate.runId !== payload.runId || candidate.turn <= seed.committedTurns || seed.compaction.record.payload._tag !== "CompactionCreated" || declarationSequence <= seed.compaction.record.payload.coversThrough || declarationSequence >= sequence) return false;
|
|
243
|
-
const decoded = Schema.decodeUnknownOption(Prompt.Prompt)(candidate.messages);
|
|
244
|
-
return Option.isSome(decoded) && decoded.value.content.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "tool-call" && part.id === payload.toolCallId));
|
|
245
|
-
});
|
|
246
|
-
return payload._tag !== "CompactionCreated" || payload.coversThrough >= seed.throughSequence;
|
|
247
|
-
});
|
|
248
|
-
//#endregion
|
|
249
249
|
//#region src/durable/internal/messaging-host.ts
|
|
250
250
|
const failure$1 = (operation, reason) => MessagingError.make({
|
|
251
251
|
operation,
|
|
@@ -259,6 +259,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
|
|
|
259
259
|
const deps = {
|
|
260
260
|
...options,
|
|
261
261
|
store: yield* ThreadStore,
|
|
262
|
+
ledger: yield* SubmissionLedger,
|
|
262
263
|
deliveries: yield* Effect.serviceOption(MessageDeliveryStore),
|
|
263
264
|
crypto: yield* Crypto.Crypto,
|
|
264
265
|
authorizer: yield* PeerAuthorizer,
|
|
@@ -268,10 +269,18 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
|
|
|
268
269
|
failpoint: yield* MessageDeliveryFailpoint
|
|
269
270
|
};
|
|
270
271
|
const digest = (value) => digestJson(value).pipe(Effect.provideService(Crypto.Crypto, deps.crypto), Effect.mapError(() => failure$1("send", "storage")));
|
|
271
|
-
const
|
|
272
|
+
const exactRecord = Effect.fn("MessagingHost.exactRecord")(function* (threadId, recordId) {
|
|
273
|
+
return Option.getOrUndefined(yield* getRecord({
|
|
274
|
+
threadId,
|
|
275
|
+
recordId
|
|
276
|
+
}).pipe(Effect.provideService(ThreadStore, deps.store)).pipe(Effect.mapError(() => failure$1("send", "storage"))))?.record;
|
|
277
|
+
});
|
|
272
278
|
const sourceOf = Effect.fn("MessagingHost.source")(function* (threadId) {
|
|
273
|
-
const log = yield*
|
|
274
|
-
const created =
|
|
279
|
+
const log = yield* deps.store.inspectTail(ThreadTailRequest.make({ threadId })).pipe(Effect.mapError(() => failure$1("context", "storage")));
|
|
280
|
+
const created = (yield* deps.store.read(ThreadRead.make({
|
|
281
|
+
threadId,
|
|
282
|
+
limit: 1
|
|
283
|
+
})).pipe(Stream.runCollect, Effect.mapError(() => failure$1("context", "storage"))))[0]?.record.payload;
|
|
275
284
|
if (created?._tag !== "ThreadCreated") return yield* failure$1("context", "not-found");
|
|
276
285
|
if (deps.bindings.filter((binding) => binding.agentId === created.agentId).length !== 1) return yield* failure$1("context", "binding-mismatch");
|
|
277
286
|
return {
|
|
@@ -296,7 +305,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
|
|
|
296
305
|
});
|
|
297
306
|
const proof = Effect.fn("MessagingHost.proof")(function* (message) {
|
|
298
307
|
const source = yield* sourceOf(message.ownerThreadId);
|
|
299
|
-
const record =
|
|
308
|
+
const record = yield* exactRecord(message.ownerThreadId, peerMessageRecordId(message.messageId));
|
|
300
309
|
if (record === void 0) return yield* failure$1("reply", "invalid-reference");
|
|
301
310
|
const saved = yield* decodeProof(record);
|
|
302
311
|
if (!Schema.is(MessageAdmission)(saved.envelope.messageAdmission) || saved.envelope.messageAdmission.sender.agentId !== source.address.agentId || !sameRef(saved.envelope.messageAdmission.message, message)) return yield* failure$1("reply", "invalid-reference");
|
|
@@ -371,7 +380,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
|
|
|
371
380
|
const maxMessages = yield* capacity;
|
|
372
381
|
for (let attempt = 0; attempt < 8; attempt++) {
|
|
373
382
|
const current = attempt === 0 ? initial : yield* sourceOf(threadId);
|
|
374
|
-
const prior =
|
|
383
|
+
const prior = yield* exactRecord(threadId, peerMessageRecordId(message.messageId));
|
|
375
384
|
let saved;
|
|
376
385
|
if (prior !== void 0) {
|
|
377
386
|
saved = yield* decodeProof(prior);
|
|
@@ -383,12 +392,23 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
|
|
|
383
392
|
});
|
|
384
393
|
yield* authorizeEnvelope(saved, operation);
|
|
385
394
|
} else {
|
|
386
|
-
if (
|
|
395
|
+
if (deps.store.countPeerMessages === void 0) return yield* failure$1(operation, "unavailable");
|
|
396
|
+
if ((yield* deps.store.countPeerMessages({
|
|
397
|
+
threadId,
|
|
398
|
+
limit: maxMessages
|
|
399
|
+
}).pipe(Effect.mapError(mapStore(operation)))) >= maxMessages) return yield* failure$1(operation, "capacity");
|
|
387
400
|
let destinationThread;
|
|
388
401
|
if (operation === "reply") {
|
|
389
402
|
if (inReplyTo === void 0) return yield* failure$1(operation, "invalid-reference");
|
|
390
|
-
const
|
|
391
|
-
if (
|
|
403
|
+
const original = yield* proof(inReplyTo);
|
|
404
|
+
if (original.envelope.threadId !== threadId || original.envelope.agentId !== current.address.agentId) return yield* failure$1(operation, "invalid-reference");
|
|
405
|
+
const accepted = yield* deps.ledger.lookup(SubmissionLookupByKey.make({
|
|
406
|
+
threadId,
|
|
407
|
+
principal: original.envelope.deliveryPrincipal,
|
|
408
|
+
idempotencyKey: inReplyTo.messageId
|
|
409
|
+
})).pipe(Effect.mapError(mapStore(operation)));
|
|
410
|
+
const inbound = Option.isNone(accepted) ? void 0 : (yield* exactRecord(threadId, submissionInputRecordId(accepted.value.submissionId)))?.payload;
|
|
411
|
+
if (inbound?._tag !== "UserInputRecorded" || !Schema.is(MessageAdmission)(inbound.messageAdmission) || inbound.messageAdmission.sender.agentId !== target.agentId || !sameRef(inbound.messageAdmission.message, inReplyTo) || !Schema.is(MessageAdmission)(original.envelope.messageAdmission) || !sameAdmission$1(inbound.messageAdmission, original.envelope.messageAdmission) || Option.isNone(accepted) || inbound.submissionId !== accepted.value.submissionId) return yield* failure$1(operation, "invalid-reference");
|
|
392
412
|
destinationThread = inbound.messageAdmission.returnAddress.threadId;
|
|
393
413
|
} else destinationThread = yield* deps.routes.resolve({
|
|
394
414
|
source: current.address,
|
|
@@ -437,7 +457,7 @@ const makeMessagingRuntime = Effect.fn("MessagingHost.make")(function* (options)
|
|
|
437
457
|
batchId: Schema.decodeSync(BatchId)(message.messageId),
|
|
438
458
|
producerId: deps.producerId,
|
|
439
459
|
records: [RecordEnvelope.make({
|
|
440
|
-
recordId:
|
|
460
|
+
recordId: peerMessageRecordId(message.messageId),
|
|
441
461
|
family: "thread",
|
|
442
462
|
schemaVersion: 1,
|
|
443
463
|
createdAt: DateTime.makeUnsafe(createdAtMillis),
|
|
@@ -638,6 +658,36 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
638
658
|
});
|
|
639
659
|
});
|
|
640
660
|
const read = (threadId, operation) => deps.store.export(ThreadExportRequest.make({ threadId })).pipe(Effect.mapError(storageFailure(operation)));
|
|
661
|
+
const exactRecord = Effect.fn("WorkerHost.exactRecord")(function* (threadId, recordId, operation) {
|
|
662
|
+
return yield* getRecord({
|
|
663
|
+
threadId,
|
|
664
|
+
recordId
|
|
665
|
+
}).pipe(Effect.provideService(ThreadStore, deps.store), Effect.mapError(storageFailure(operation)));
|
|
666
|
+
});
|
|
667
|
+
const readIdentity = Effect.fn("WorkerHost.readIdentity")(function* (threadId, operation) {
|
|
668
|
+
const tail = yield* deps.store.inspectTail(ThreadTailRequest.make({ threadId })).pipe(Effect.mapError(storageFailure(operation)));
|
|
669
|
+
const first = yield* deps.store.read(ThreadRead.make({
|
|
670
|
+
threadId,
|
|
671
|
+
limit: 1
|
|
672
|
+
})).pipe(Stream.runCollect, Effect.mapError(storageFailure(operation)));
|
|
673
|
+
const worker = yield* exactRecord(threadId, workerOriginRecordId(threadId), operation);
|
|
674
|
+
const attached = yield* exactRecord(threadId, subagentLineageRecordId(threadId), operation);
|
|
675
|
+
return {
|
|
676
|
+
...tail,
|
|
677
|
+
records: [
|
|
678
|
+
...first,
|
|
679
|
+
...Option.toArray(worker),
|
|
680
|
+
...Option.toArray(attached)
|
|
681
|
+
]
|
|
682
|
+
};
|
|
683
|
+
});
|
|
684
|
+
const readWorkerState$1 = Effect.fn("WorkerHost.readWorkerState")(function* (threadId, operation, sourceSubmissionId) {
|
|
685
|
+
return yield* readWorkerState({
|
|
686
|
+
threadId,
|
|
687
|
+
limit: MAX_THREAD_EXPORT_RECORDS,
|
|
688
|
+
...sourceSubmissionId === void 0 ? {} : { sourceSubmissionId }
|
|
689
|
+
}).pipe(Effect.provideService(ThreadStore, deps.store), Effect.mapError(storageFailure(operation)));
|
|
690
|
+
});
|
|
641
691
|
const hit = (location, operation) => deps.failpoint.hit(location).pipe(Effect.mapError(storageFailure(operation)));
|
|
642
692
|
const append = Effect.fn("WorkerHost.append")(function* (threadId, id, payload, current, phase) {
|
|
643
693
|
const operation = "start";
|
|
@@ -681,10 +731,10 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
681
731
|
const matches = deps.bindings.filter((entry) => entry.agentId === agentId);
|
|
682
732
|
return matches.length === 1 ? matches[0] : void 0;
|
|
683
733
|
};
|
|
684
|
-
const sourceAuthority = Effect.fn("WorkerHost.sourceAuthority")(function* (threadId, submissionId) {
|
|
685
|
-
const current = yield*
|
|
734
|
+
const sourceAuthority = Effect.fn("WorkerHost.sourceAuthority")(function* (threadId, submissionId, reservations = false) {
|
|
735
|
+
const current = yield* reservations ? readWorkerState$1(threadId, "start", submissionId) : readIdentity(threadId, "start");
|
|
686
736
|
const created = current.records[0]?.record.payload;
|
|
687
|
-
if (created?._tag !== "ThreadCreated") return yield* failure("start", "not-found");
|
|
737
|
+
if (created?._tag !== "ThreadCreated" || current.records[0]?.sequence !== 1) return yield* failure("start", "not-found");
|
|
688
738
|
const binding = currentBinding(created.agentId);
|
|
689
739
|
const worker = current.records.find(({ record }) => record.payload._tag === "WorkerOriginRecorded")?.record.payload;
|
|
690
740
|
const attached = current.records.find(({ record }) => record.payload._tag === "SubagentLineageRecorded")?.record.payload;
|
|
@@ -760,7 +810,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
760
810
|
const payload = yield* decode(SubtreeBudgetReserved, requested, "start");
|
|
761
811
|
const recordId = `subtree:${payload.reservationId}`;
|
|
762
812
|
for (let attempt = 0; attempt < 16; attempt++) {
|
|
763
|
-
const source = yield* sourceAuthority(sourceThreadId, payload.sourceSubmissionId);
|
|
813
|
+
const source = yield* sourceAuthority(sourceThreadId, payload.sourceSubmissionId, true);
|
|
764
814
|
const previous = source.current.records.find(({ record }) => record.recordId === recordId)?.record.payload;
|
|
765
815
|
if (previous !== void 0) {
|
|
766
816
|
if (previous._tag !== "SubtreeBudgetReserved" || !Schema.toEquivalence(SubtreeBudgetReserved)(previous, payload)) return yield* failure("start", "idempotency-conflict");
|
|
@@ -809,9 +859,9 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
809
859
|
});
|
|
810
860
|
const reservation = Effect.fn("WorkerHost.reserveInput")(function* (admission, inputDigest, input, principal, retainedFrameworkInput) {
|
|
811
861
|
const origin = admission.origin;
|
|
812
|
-
const id =
|
|
862
|
+
const id = workerInputRecordId(admission.messageId);
|
|
813
863
|
for (let attempt = 0; attempt < 16; attempt++) {
|
|
814
|
-
const source = yield* sourceAuthority(origin.source.threadId, admission.sourceSubmissionId);
|
|
864
|
+
const source = yield* sourceAuthority(origin.source.threadId, admission.sourceSubmissionId, true);
|
|
815
865
|
const current = source.current;
|
|
816
866
|
const rows = requests(current.records);
|
|
817
867
|
const existing = current.records.find(({ record }) => record.recordId === id)?.record.payload;
|
|
@@ -899,7 +949,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
899
949
|
});
|
|
900
950
|
const ensureOrigin = Effect.fn("WorkerHost.ensureOrigin")(function* (origin) {
|
|
901
951
|
for (let attempt = 0; attempt < 16; attempt++) {
|
|
902
|
-
const current = yield*
|
|
952
|
+
const current = yield* readIdentity(origin.worker.threadId, "start");
|
|
903
953
|
const existing = current.records.find(({ record }) => record.payload._tag === "WorkerOriginRecorded")?.record.payload;
|
|
904
954
|
if (existing?._tag === "WorkerOriginRecorded") {
|
|
905
955
|
if (!sameOrigin(existing.origin, origin)) return yield* failure("start", "worker-mismatch");
|
|
@@ -907,7 +957,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
907
957
|
}
|
|
908
958
|
const first = current.records[0]?.record.payload;
|
|
909
959
|
if (first?._tag !== "ThreadCreated" || first.agentId !== origin.worker.targetAgentId || !definitionDigestsEqual(first.definitions, origin.targetDigests) || current.records.some(({ record }) => record.payload._tag === "SubagentLineageRecorded")) return yield* failure("start", "worker-mismatch");
|
|
910
|
-
if (yield* append(origin.worker.threadId,
|
|
960
|
+
if (yield* append(origin.worker.threadId, workerOriginRecordId(origin.worker.threadId), WorkerOriginRecorded.make({ origin }), current, "origin")) return;
|
|
911
961
|
}
|
|
912
962
|
return yield* failure("start", "storage");
|
|
913
963
|
});
|
|
@@ -937,9 +987,8 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
937
987
|
const intent = origin?.reporting;
|
|
938
988
|
if (origin === void 0 || intent?.mode !== "standard") return void 0;
|
|
939
989
|
if (update.threadId !== submission.threadId || update.agentId !== origin.worker.targetAgentId) return yield* failure("followUp", "worker-mismatch");
|
|
940
|
-
const
|
|
941
|
-
|
|
942
|
-
if (first === void 0 || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "corrupt");
|
|
990
|
+
const first = Option.getOrUndefined(yield* exactRecord(origin.source.threadId, workerInputRecordId(origin.firstMessageId), "followUp"))?.record.payload;
|
|
991
|
+
if (first?._tag !== "WorkerInputRequested" || first.admission.messageId !== origin.firstMessageId || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "corrupt");
|
|
943
992
|
const source = yield* sourceAuthority(origin.source.threadId, first.admission.sourceSubmissionId);
|
|
944
993
|
if (source.binding === void 0 || source.submission === void 0) return yield* failure("followUp", "declaration-unavailable");
|
|
945
994
|
const sourceBinding = currentBinding(origin.source.agentId);
|
|
@@ -1028,7 +1077,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1028
1077
|
submission.threadId,
|
|
1029
1078
|
runId
|
|
1030
1079
|
])).pipe(Effect.map((value) => Schema.decodeSync(IdempotencyKey)(`report:${value}`)), Effect.mapError(storageFailure("inspect")));
|
|
1031
|
-
const recordId =
|
|
1080
|
+
const recordId = workerReportRecordId(messageId);
|
|
1032
1081
|
const prepare = Effect.fn("WorkerHost.prepareReport")(function* () {
|
|
1033
1082
|
const refused = (reason) => WorkerReportRefused.make({
|
|
1034
1083
|
runId,
|
|
@@ -1039,9 +1088,8 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1039
1088
|
if (Option.isNone(selected) || selected.value.threadId !== submission.threadId || selected.value.receiptId !== host.receiptId || selected.value.workerAdmission === void 0 || !sameOrigin(selected.value.workerAdmission.origin, origin)) return yield* failure("inspect", "corrupt");
|
|
1040
1089
|
const hostSubmission = selected.value;
|
|
1041
1090
|
const hostAdmission = selected.value.workerAdmission;
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
if (firstInput === void 0 || !sameOrigin(firstInput.admission.origin, origin)) return yield* failure("inspect", "corrupt");
|
|
1091
|
+
const firstInput = Option.getOrUndefined(yield* exactRecord(origin.source.threadId, workerInputRecordId(origin.firstMessageId), "inspect"))?.record.payload;
|
|
1092
|
+
if (firstInput?._tag !== "WorkerInputRequested" || firstInput.admission.messageId !== origin.firstMessageId || !sameOrigin(firstInput.admission.origin, origin)) return yield* failure("inspect", "corrupt");
|
|
1045
1093
|
const source = yield* sourceAuthority(origin.source.threadId, firstInput.admission.sourceSubmissionId);
|
|
1046
1094
|
if (source.binding === void 0) return refused("declaration-unavailable");
|
|
1047
1095
|
const sourceBinding = currentBinding(origin.source.agentId);
|
|
@@ -1192,7 +1240,15 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1192
1240
|
const settledEnvelope = child.records.find(({ record }) => record.payload._tag === "SubmissionSettled" && record.payload.submissionId === submission.submissionId)?.record;
|
|
1193
1241
|
const settled = settledEnvelope?.payload;
|
|
1194
1242
|
if (settled?._tag !== "SubmissionSettled" || settled.receiptId !== submission.receiptId || settledEnvelope === void 0) return yield* failure("inspect", "corrupt");
|
|
1243
|
+
const unresolved = /* @__PURE__ */ new Set();
|
|
1244
|
+
for (const { record } of child.records) {
|
|
1245
|
+
const value = record.payload;
|
|
1246
|
+
if ((value._tag === "ToolCallPrepared" || value._tag === "ToolCallUnknown") && value.runId === settled.runId) unresolved.add(value.toolCallId);
|
|
1247
|
+
if (value._tag === "ToolCallSettled" && value.runId === settled.runId) unresolved.delete(value.toolCallId);
|
|
1248
|
+
}
|
|
1249
|
+
if (unresolved.size > 0) return;
|
|
1195
1250
|
const payload = WorkerInputCompleted.make({
|
|
1251
|
+
effectsResolved: true,
|
|
1196
1252
|
messageId: admission.messageId,
|
|
1197
1253
|
workerThreadId: submission.threadId,
|
|
1198
1254
|
submissionId: submission.submissionId,
|
|
@@ -1202,12 +1258,15 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1202
1258
|
});
|
|
1203
1259
|
for (let attempt = 0; attempt < 16; attempt++) {
|
|
1204
1260
|
const source = yield* read(admission.origin.source.threadId, "inspect");
|
|
1205
|
-
const existing = source.records.
|
|
1261
|
+
const existing = source.records.findLast(({ record }) => record.payload._tag === "WorkerInputCompleted" && record.payload.messageId === admission.messageId)?.record.payload;
|
|
1206
1262
|
if (existing !== void 0) {
|
|
1207
|
-
if (existing._tag !== "WorkerInputCompleted" || !Schema.toEquivalence(WorkerInputCompleted)(
|
|
1208
|
-
|
|
1263
|
+
if (existing._tag !== "WorkerInputCompleted" || !Schema.toEquivalence(WorkerInputCompleted)({
|
|
1264
|
+
...existing,
|
|
1265
|
+
effectsResolved: true
|
|
1266
|
+
}, payload)) return yield* failure("inspect", "corrupt");
|
|
1267
|
+
if (existing.effectsResolved) return;
|
|
1209
1268
|
}
|
|
1210
|
-
if (yield* append(admission.origin.source.threadId, `worker-
|
|
1269
|
+
if (yield* append(admission.origin.source.threadId, `worker-effects-resolved:${admission.messageId}`, payload, source, "completion")) return;
|
|
1211
1270
|
}
|
|
1212
1271
|
return yield* failure("inspect", "storage");
|
|
1213
1272
|
});
|
|
@@ -1244,10 +1303,10 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1244
1303
|
const findOrigin = Effect.fn("WorkerHost.findOrigin")(function* (worker, target, operation) {
|
|
1245
1304
|
yield* binding(target, operation);
|
|
1246
1305
|
if (worker.targetAgentId !== target.id) return yield* failure(operation, "worker-mismatch");
|
|
1247
|
-
const
|
|
1248
|
-
const origin =
|
|
1306
|
+
const first = Option.getOrUndefined(yield* exactRecord(context.source.threadId, firstWorkerInputRecordId(worker), operation))?.record.payload;
|
|
1307
|
+
const origin = first?._tag === "WorkerInputRequested" ? first.admission.origin : void 0;
|
|
1249
1308
|
if (origin === void 0) return yield* failure(operation, "not-found");
|
|
1250
|
-
if (origin.worker.
|
|
1309
|
+
if (!Schema.toEquivalence(WorkerRef)(origin.worker, worker) || first?._tag !== "WorkerInputRequested" || first.admission.messageId !== origin.firstMessageId || workerInputRecordId(origin.firstMessageId) !== firstWorkerInputRecordId(worker)) return yield* failure(operation, "worker-mismatch");
|
|
1251
1310
|
return origin;
|
|
1252
1311
|
});
|
|
1253
1312
|
const receiptInput = Effect.fn("WorkerHost.receiptInput")(function* (request, operation) {
|
|
@@ -1476,7 +1535,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1476
1535
|
summary: Effect.fn("WorkerHost.inspectWorker")(function* (request) {
|
|
1477
1536
|
yield* authorize("inspect", "read", request.worker);
|
|
1478
1537
|
const origin = yield* findOrigin(request.worker, request.target, "inspect");
|
|
1479
|
-
const source = yield*
|
|
1538
|
+
const source = yield* readWorkerState$1(context.source.threadId, "inspect");
|
|
1480
1539
|
return yield* summarize(origin, requests(source.records), "inspect");
|
|
1481
1540
|
}),
|
|
1482
1541
|
observe: (request) => Stream.unwrap(Effect.gen(function* () {
|
|
@@ -1516,7 +1575,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1516
1575
|
yield* authorize("list", "read");
|
|
1517
1576
|
yield* binding(request.target, "list");
|
|
1518
1577
|
if (!Number.isSafeInteger(request.limit) || request.limit < 1 || request.limit > 100) return yield* failure("list", "capacity");
|
|
1519
|
-
const source = yield*
|
|
1578
|
+
const source = yield* readWorkerState$1(context.source.threadId, "list");
|
|
1520
1579
|
const all = requests(source.records);
|
|
1521
1580
|
const origins = [...new Map(all.map((row) => [row.admission.origin.worker.threadId, row.admission.origin])).values()].filter((origin) => origin.worker.delegationId === request.delegationId && origin.worker.targetAgentId === request.target.id && (request.after === void 0 || origin.worker.threadId > request.after)).sort((left, right) => left.worker.threadId.localeCompare(right.worker.threadId));
|
|
1522
1581
|
const selected = origins.slice(0, request.limit);
|
|
@@ -1538,17 +1597,18 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1538
1597
|
};
|
|
1539
1598
|
const validateCompletion = Effect.fn("WorkerHost.validateCompletion")(function* (unvalidated, options, agentId, inputDigest) {
|
|
1540
1599
|
const message = yield* Schema.decodeEffect(FrameworkMessage)(unvalidated).pipe(Effect.mapError(() => failure("followUp", "corrupt")));
|
|
1541
|
-
const
|
|
1542
|
-
const
|
|
1600
|
+
const childThreadId = message._tag === "WorkerCompletion" ? message.report.worker.threadId : message.worker.threadId;
|
|
1601
|
+
const proofId = message._tag === "WorkerCompletion" ? workerReportRecordId(options.idempotencyKey) : yield* withCrypto(agentUpdateRecordId(message.update.threadId, message.update.runId, message.update.updateId)).pipe(Effect.mapError(storageFailure("followUp")));
|
|
1602
|
+
const proof = Option.getOrUndefined(yield* exactRecord(childThreadId, proofId, "followUp"))?.record.payload;
|
|
1603
|
+
const frozen = message._tag === "WorkerCompletion" ? proof?._tag === "WorkerReportPrepared" && proof.runId === message.report.runId && proof.messageId === options.idempotencyKey ? proof.envelope : void 0 : proof?._tag === "AgentUpdateEmitted" && Schema.toEquivalence(Update)(proof.update, message.update) ? proof.delivery?.envelope : void 0;
|
|
1543
1604
|
if (frozen === void 0) return yield* failure("followUp", "denied");
|
|
1544
1605
|
const envelope = yield* Schema.decodeUnknownEffect(PreparedInput)(frozen).pipe(Effect.mapError(() => failure("followUp", "corrupt")));
|
|
1545
1606
|
if (!Schema.is(FrameworkMessage)(envelope.messageAdmission) || !Schema.toEquivalence(FrameworkMessage)(envelope.messageAdmission, message) || envelope.threadId !== options.threadId || envelope.agentId !== agentId || envelope.inputDigest !== inputDigest || envelope.deliveryPrincipal !== options.principal || envelope.admissionKey !== options.idempotencyKey || !definitionDigestsEqual(envelope.definitions, options.definitions) || !Schema.toEquivalence(Schema.UndefinedOr(WorkerAdmission))(envelope.workerAdmission, options.workerAdmission)) return yield* failure("followUp", "denied");
|
|
1546
|
-
const recorded =
|
|
1547
|
-
if (recorded?._tag !== "WorkerOriginRecorded" || recorded.origin.reporting?.mode !== "standard") return yield* failure("followUp", "denied");
|
|
1607
|
+
const recorded = Option.getOrUndefined(yield* exactRecord(childThreadId, workerOriginRecordId(childThreadId), "followUp"))?.record.payload;
|
|
1608
|
+
if (recorded?._tag !== "WorkerOriginRecorded" || recorded.origin.worker.threadId !== childThreadId || recorded.origin.reporting?.mode !== "standard") return yield* failure("followUp", "denied");
|
|
1548
1609
|
const origin = recorded.origin;
|
|
1549
|
-
const
|
|
1550
|
-
|
|
1551
|
-
if (first === void 0 || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "denied");
|
|
1610
|
+
const first = Option.getOrUndefined(yield* exactRecord(origin.source.threadId, workerInputRecordId(origin.firstMessageId), "followUp"))?.record.payload;
|
|
1611
|
+
if (first?._tag !== "WorkerInputRequested" || first.admission.messageId !== origin.firstMessageId || !sameOrigin(first.admission.origin, origin)) return yield* failure("followUp", "denied");
|
|
1552
1612
|
const receiving = envelope.workerAdmission;
|
|
1553
1613
|
const sourceSubmissionId = receiving === void 0 ? first.admission.sourceSubmissionId : receiving.sourceSubmissionId;
|
|
1554
1614
|
if ((yield* deps.authorizer.authorize({
|
|
@@ -1573,7 +1633,7 @@ const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (options) {
|
|
|
1573
1633
|
operation: "context",
|
|
1574
1634
|
access: "context"
|
|
1575
1635
|
});
|
|
1576
|
-
const current = yield*
|
|
1636
|
+
const current = yield* readIdentity(sourceThreadId, "context");
|
|
1577
1637
|
const created = current.records[0]?.record.payload;
|
|
1578
1638
|
if (created?._tag !== "ThreadCreated") return yield* failure("context", "not-found");
|
|
1579
1639
|
const selected = request.sourceSubmissionId === void 0 ? void 0 : yield* sourceAuthority(sourceThreadId, request.sourceSubmissionId);
|
|
@@ -5937,6 +5997,11 @@ const make = Effect.fn("DurableAgentRuntime.make")(function* (bindings) {
|
|
|
5937
5997
|
operation: "recoverSubmission",
|
|
5938
5998
|
message: `Unknown Submission ${submissionId}`
|
|
5939
5999
|
});
|
|
6000
|
+
if (found.value.state === "settled") yield* workerRuntime.completeInput(found.value).pipe(Effect.mapError((cause) => LedgerError.make({
|
|
6001
|
+
operation: "recoverSubmission",
|
|
6002
|
+
message: "Worker completion repair failed",
|
|
6003
|
+
cause
|
|
6004
|
+
})));
|
|
5940
6005
|
const history = yield* readRecoveryHistory(found.value.threadId, [submissionId]);
|
|
5941
6006
|
if (history.materialized && found.value.workerAdmission?.origin.reporting?.mode === "standard") yield* updateRuntime.repair(found.value.threadId);
|
|
5942
6007
|
return yield* recoverSnapshot(found.value, history);
|
|
@@ -6604,4 +6669,4 @@ var DurableAgentRuntime = class DurableAgentRuntime extends Context.Service()("@
|
|
|
6604
6669
|
//#endregion
|
|
6605
6670
|
export { RecoveryReport as a, recoveryRepairRecordId as c, DurableRuntimeConfig as i, threadCreatedBatchId as l, DurableAgentRuntime_exports as n, childReservationIdFor as o, DurableApprovalResolver as r, recoveryRepairBatchId as s, DurableAgentRuntime as t, threadCreatedRecordId as u };
|
|
6606
6671
|
|
|
6607
|
-
//# sourceMappingURL=DurableAgentRuntime-
|
|
6672
|
+
//# sourceMappingURL=DurableAgentRuntime-HOZ3AeSi.mjs.map
|