effect-agent 0.1.0-beta.159 → 0.1.0-beta.160
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-DWDYlvvZ.d.mts → Admin-Dirux8PR.d.mts} +9 -2
- package/dist/{DurableAgentRuntime-C7A5guvq.mjs → DurableAgentRuntime-pr7cCaZw.mjs} +216 -55
- package/dist/DurableAgentRuntime-pr7cCaZw.mjs.map +1 -0
- package/dist/{EventSource-BfNZBG4A.d.mts → EventSource-DOXB0RJR.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-VStpn8u2.d.mts → PreparedInputAdmission-B7r401xJ.d.mts} +3 -3
- package/dist/{RunJournal-ixFRCyW3.mjs → RunJournal-CA2bsvHn.mjs} +8 -5
- package/dist/RunJournal-CA2bsvHn.mjs.map +1 -0
- package/dist/{Subscription-Bx1ZRRVS.d.mts → Subscription-B3ScCBaN.d.mts} +2 -2
- package/dist/{SubscriptionInput-B5k5vb1S.d.mts → SubscriptionInput-BP5WVsX_.d.mts} +2 -2
- package/dist/{WorkerAdmission-N9hZV85Q.mjs → WorkerAdmission-Cmcxd6nS.mjs} +2 -2
- package/dist/{WorkerAdmission-N9hZV85Q.mjs.map → WorkerAdmission-Cmcxd6nS.mjs.map} +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/Certification.d.mts +1 -1
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +2 -2
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/LifecyclePublication.d.mts +1 -1
- package/dist/durable/MessageDelivery.d.mts +3 -3
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +1 -1
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PersistentHistory.mjs +1 -1
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/RunJournal.mjs +1 -1
- package/dist/durable/Scheduling.d.mts +1 -1
- package/dist/durable/SqlMemoryStore.d.mts +3 -0
- package/dist/durable/SqlMemoryStore.mjs +3 -2
- package/dist/durable/SqlMemoryStore.mjs.map +1 -1
- package/dist/durable/SubmissionLedger.d.mts +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/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionTools.d.mts +2 -2
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadInvariants.d.mts +1 -1
- package/dist/durable/ThreadInvariants.mjs +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +1 -1
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/ThreadStoreConformance.mjs +1 -1
- package/dist/durable/WorkerAdmission.d.mts +1 -1
- package/dist/durable/WorkerAdmission.mjs +1 -1
- package/dist/durable/WorkerHost.d.mts +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
- package/src/durable/DurableAgentRuntime.ts +371 -84
- package/src/durable/RunJournal.ts +16 -4
- package/src/durable/SqlMemoryStore.ts +7 -3
- package/src/durable/internal/journal-checkpoint.ts +57 -3
- package/dist/DurableAgentRuntime-C7A5guvq.mjs.map +0 -1
- package/dist/RunJournal-ixFRCyW3.mjs.map +0 -1
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
contextWindowMessage,
|
|
16
16
|
} from "../engine/Compaction.ts";
|
|
17
17
|
import { digestJson, type DigestError } from "./Digest.ts";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
type JournalCheckpointSeed,
|
|
20
|
+
type ThreadContextCheckpoint,
|
|
21
|
+
} from "./internal/journal-checkpoint.ts";
|
|
19
22
|
import {
|
|
20
23
|
makeJournalMetadata,
|
|
21
24
|
toolExecutionKey,
|
|
@@ -610,13 +613,19 @@ export const projectRunJournalStream = Effect.fn("RunJournal.projectRunJournalSt
|
|
|
610
613
|
onBoundary?: (boundary: JournalBoundary) => void,
|
|
611
614
|
seed?: JournalCheckpointSeed,
|
|
612
615
|
preparedMetadata?: JournalMetadata,
|
|
616
|
+
priorContext?: ThreadContextCheckpoint,
|
|
613
617
|
): Effect.fn.Return<RunJournalProjection, RunJournalError | E, R> {
|
|
614
618
|
if (seed !== undefined && seed.runId !== ownerRunId)
|
|
615
619
|
return yield* journalError("Recovery checkpoint belongs to another Run");
|
|
620
|
+
if (seed !== undefined && priorContext !== undefined)
|
|
621
|
+
return yield* journalError("Run recovery and prior Thread context cannot seed the same replay");
|
|
622
|
+
|
|
623
|
+
const historical =
|
|
624
|
+
priorContext === undefined ? [] : (yield* decodePromptMessages(priorContext.prompt)).content;
|
|
616
625
|
|
|
617
626
|
let state: FoldState = {
|
|
618
|
-
all: [],
|
|
619
|
-
before: [],
|
|
627
|
+
all: [...historical],
|
|
628
|
+
before: [...historical],
|
|
620
629
|
pendingTools: [],
|
|
621
630
|
pendingToolsForRun: false,
|
|
622
631
|
committedTurns: seed?.committedTurns ?? 0,
|
|
@@ -679,6 +688,9 @@ export const projectRunJournalStream = Effect.fn("RunJournal.projectRunJournalSt
|
|
|
679
688
|
isInRunView(sequence, payload, ownerRunId),
|
|
680
689
|
);
|
|
681
690
|
|
|
691
|
+
if (priorContext !== undefined && compactions.length > 0)
|
|
692
|
+
return yield* journalError("New compaction requires the complete canonical context mapping");
|
|
693
|
+
|
|
682
694
|
const recordsForRun = records.pipe(
|
|
683
695
|
Stream.filter(({ sequence, record: { payload } }) =>
|
|
684
696
|
isInRunView(sequence, payload, ownerRunId),
|
|
@@ -827,7 +839,7 @@ export const projectRunJournalStream = Effect.fn("RunJournal.projectRunJournalSt
|
|
|
827
839
|
];
|
|
828
840
|
};
|
|
829
841
|
|
|
830
|
-
let latestWindowId: string | undefined = seed?.contextWindowId;
|
|
842
|
+
let latestWindowId: string | undefined = seed?.contextWindowId ?? priorContext?.contextWindowId;
|
|
831
843
|
let latestWindowSequence = seed?.throughSequence ?? -1;
|
|
832
844
|
let rolloverCoveredThrough = 0;
|
|
833
845
|
|
|
@@ -63,6 +63,9 @@ export class SqlMemoryBatchWriter extends Context.Service<
|
|
|
63
63
|
* releasing readers. Hosts with independent database writers must leave this unset.
|
|
64
64
|
*/
|
|
65
65
|
export interface SqlStorageOwner {
|
|
66
|
+
/** Cache identity for transaction decorators; omission uses the owner itself.
|
|
67
|
+
* Shared identities must name the same database, reader gate and invalidator set. */
|
|
68
|
+
readonly identity?: object;
|
|
66
69
|
readonly read: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
67
70
|
readonly transaction: <A, E, R>(
|
|
68
71
|
effect: Effect.Effect<A, E, R>,
|
|
@@ -172,17 +175,18 @@ class MemoryViews {
|
|
|
172
175
|
}
|
|
173
176
|
}
|
|
174
177
|
|
|
175
|
-
const ownedViews = new WeakMap<
|
|
178
|
+
const ownedViews = new WeakMap<object, MemoryViews>();
|
|
176
179
|
|
|
177
180
|
const memoryViews = Effect.fn("SqliteMemoryStore.memoryViews")(function* () {
|
|
178
181
|
const owner = yield* SqlStorageOwner;
|
|
179
182
|
|
|
180
183
|
if (owner === undefined) return undefined;
|
|
181
|
-
|
|
184
|
+
const identity = owner.identity ?? owner;
|
|
185
|
+
let views = ownedViews.get(identity);
|
|
182
186
|
|
|
183
187
|
if (views === undefined) {
|
|
184
188
|
views = new MemoryViews();
|
|
185
|
-
ownedViews.set(
|
|
189
|
+
ownedViews.set(identity, views);
|
|
186
190
|
owner.invalidators.add(views.clear);
|
|
187
191
|
}
|
|
188
192
|
|
|
@@ -37,15 +37,25 @@ export class JournalCheckpointSeed extends Schema.Class<JournalCheckpointSeed>(
|
|
|
37
37
|
compaction: CanonicalRecordEnvelope,
|
|
38
38
|
}) {}
|
|
39
39
|
|
|
40
|
+
/** Canonical historical context for a later Run, without the previous Run's authority or usage. */
|
|
41
|
+
export class ThreadContextCheckpoint extends Schema.Class<ThreadContextCheckpoint>(
|
|
42
|
+
"@effect-agent/thread/internal/ThreadContextCheckpoint",
|
|
43
|
+
)({
|
|
44
|
+
throughSequence: CanonicalSequence,
|
|
45
|
+
prompt: PersistedJson,
|
|
46
|
+
contextWindowId: Schema.optionalKey(Schema.String),
|
|
47
|
+
}) {}
|
|
48
|
+
|
|
40
49
|
/** A bounded sparse projection, never a canonical log or a submission-ownership record. */
|
|
41
50
|
export class RecoveryCheckpointState extends Schema.Class<RecoveryCheckpointState>(
|
|
42
51
|
"@effect-agent/thread/internal/RecoveryCheckpointState",
|
|
43
52
|
)({
|
|
44
|
-
schemaVersion: Schema.Literal(
|
|
53
|
+
schemaVersion: Schema.Literal(2),
|
|
45
54
|
policyAccountingVersion: Schema.Literal(1),
|
|
46
55
|
submissionId: SubmissionId,
|
|
47
56
|
submissionIds: Schema.Array(SubmissionId).check(Schema.isMaxLength(4_096)),
|
|
48
|
-
seed: JournalCheckpointSeed,
|
|
57
|
+
seed: Schema.optionalKey(JournalCheckpointSeed),
|
|
58
|
+
context: Schema.optionalKey(ThreadContextCheckpoint),
|
|
49
59
|
records: Schema.Array(CanonicalRecordEnvelope).check(Schema.isMaxLength(4_096)),
|
|
50
60
|
}) {}
|
|
51
61
|
|
|
@@ -56,7 +66,51 @@ export class RecoveryCheckpointContents extends Schema.Class<RecoveryCheckpointC
|
|
|
56
66
|
digest: Digest,
|
|
57
67
|
}) {}
|
|
58
68
|
|
|
59
|
-
export const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@
|
|
69
|
+
export const RECOVERY_ENGINE_VERSION = "effect-agent/recovery@3";
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Prove that indexed original-input absence also means absent prefix Run/control evidence.
|
|
73
|
+
* Only cache consumers with colon-free Submission IDs use this certificate. For those IDs,
|
|
74
|
+
* every possible control marker is exactly :run:<submission-id>:. Parsing here can only decline
|
|
75
|
+
* caching; it never supplies an execution identity. Separator-bearing identities use full replay.
|
|
76
|
+
* The temporary anchor set is discarded after certification, not persisted with the context.
|
|
77
|
+
*/
|
|
78
|
+
export const makeThreadContextCertificate = () => {
|
|
79
|
+
const anchored = new Set<string>();
|
|
80
|
+
let valid = true;
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
add: ({ record }: CanonicalRecordEnvelope): void => {
|
|
84
|
+
if (!valid) return;
|
|
85
|
+
const payload = record.payload;
|
|
86
|
+
|
|
87
|
+
if ("runId" in payload && payload.runId !== undefined) {
|
|
88
|
+
const originalInput = payload._tag === "UserInputRecorded" && payload.kind === "user";
|
|
89
|
+
|
|
90
|
+
if (originalInput ? anchored.has(payload.runId) : !anchored.has(payload.runId)) {
|
|
91
|
+
valid = false;
|
|
92
|
+
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (originalInput) anchored.add(payload.runId);
|
|
96
|
+
}
|
|
97
|
+
for (
|
|
98
|
+
let start = record.recordId.indexOf(":run:");
|
|
99
|
+
start !== -1;
|
|
100
|
+
start = record.recordId.indexOf(":run:", start + 1)
|
|
101
|
+
) {
|
|
102
|
+
const end = record.recordId.indexOf(":", start + 5);
|
|
103
|
+
|
|
104
|
+
if (end !== -1 && !anchored.has(record.recordId.slice(start + 1, end))) {
|
|
105
|
+
valid = false;
|
|
106
|
+
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
isValid: (): boolean => valid,
|
|
112
|
+
};
|
|
113
|
+
};
|
|
60
114
|
|
|
61
115
|
/**
|
|
62
116
|
* Late evidence can invalidate an old compaction. Such histories use full canonical replay;
|