@yielded/agent-storage-memory 0.1.0-beta.172 → 0.1.0-beta.174
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/MemoryMessageDeliveryStore.mjs +1 -1
- package/dist/MemoryMessageDeliveryStore.mjs.map +1 -1
- package/dist/MemorySubmissionLedger.mjs +1179 -1177
- package/dist/MemorySubmissionLedger.mjs.map +1 -1
- package/dist/MemoryThreadStore.mjs +14 -14
- package/dist/MemoryThreadStore.mjs.map +1 -1
- package/package.json +1 -1
- package/src/MemoryMessageDeliveryStore.ts +24 -25
- package/src/MemorySubmissionLedger.ts +49 -49
- package/src/MemoryThreadStore.ts +42 -31
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@yielded/agent-storage-memory","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@yielded/agent-storage-memory","version":"0.1.0-beta.174","dependencies":{"@yielded/agent":"0.1.0-beta.174"},"devDependencies":{"@effect/platform-node":"4.0.3","@effect/vitest":"4.0.3","effect":"4.0.3","typescript":"7.0.2","vite":"npm:@voidzero-dev/vite-plus-core@1.1.0","vite-plus":"1.1.0","vitest":"5.0.3"},"peerDependencies":{"effect":"^4.0.3"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./memory-message-delivery-store":{"types":"./dist/MemoryMessageDeliveryStore.d.mts","default":"./dist/MemoryMessageDeliveryStore.mjs"},"./memory-schedule-store":{"types":"./dist/MemoryScheduleStore.d.mts","default":"./dist/MemoryScheduleStore.mjs"},"./memory-semantic-index":{"types":"./dist/MemorySemanticIndex.d.mts","default":"./dist/MemorySemanticIndex.mjs"},"./memory-submission-ledger":{"types":"./dist/MemorySubmissionLedger.d.mts","default":"./dist/MemorySubmissionLedger.mjs"},"./memory-subscription-store":{"types":"./dist/MemorySubscriptionStore.d.mts","default":"./dist/MemorySubscriptionStore.mjs"},"./memory-thread-store":{"types":"./dist/MemoryThreadStore.d.mts","default":"./dist/MemoryThreadStore.mjs"}},"description":"In-memory Thread store and submission ledger reference adapters for Effect Agent tests and conformance suites.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/yielded-dev/agent.git","directory":"packages/storage-memory"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"}}
|
|
@@ -189,36 +189,35 @@ export const memoryMessageDeliveryStoreLayer = (
|
|
|
189
189
|
};
|
|
190
190
|
}),
|
|
191
191
|
),
|
|
192
|
-
page: (threadId, after, limit)
|
|
193
|
-
|
|
194
|
-
const current = yield* Ref.get(state);
|
|
195
|
-
|
|
196
|
-
const candidates = boundedWorkSelection<MessageDeliveryKey["messageId"]>(
|
|
197
|
-
limit + 1,
|
|
198
|
-
(id) => id,
|
|
199
|
-
after,
|
|
200
|
-
);
|
|
192
|
+
page: Effect.fnUntraced(function* (threadId, after, limit) {
|
|
193
|
+
const current = yield* Ref.get(state);
|
|
201
194
|
|
|
202
|
-
|
|
203
|
-
|
|
195
|
+
const candidates = boundedWorkSelection<MessageDeliveryKey["messageId"]>(
|
|
196
|
+
limit + 1,
|
|
197
|
+
(id) => id,
|
|
198
|
+
after,
|
|
199
|
+
);
|
|
204
200
|
|
|
205
|
-
|
|
201
|
+
for (const id of current.pending.get(threadId) ?? []) candidates.add(id);
|
|
202
|
+
const ids = candidates.values;
|
|
206
203
|
|
|
207
|
-
|
|
208
|
-
const key = messageDeliveryKeyString({ ownerThreadId: threadId, messageId });
|
|
209
|
-
const entry = current.work.get(key);
|
|
204
|
+
const entries: Array<ThreadWorkEntry> = [];
|
|
210
205
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
message: "Pending delivery index is incomplete or corrupt",
|
|
215
|
-
});
|
|
216
|
-
entries.push(entry);
|
|
217
|
-
}
|
|
218
|
-
const next = ids.length > limit ? ids[limit - 1] : undefined;
|
|
206
|
+
for (const messageId of ids.slice(0, limit)) {
|
|
207
|
+
const key = messageDeliveryKeyString({ ownerThreadId: threadId, messageId });
|
|
208
|
+
const entry = current.work.get(key);
|
|
219
209
|
|
|
220
|
-
|
|
221
|
-
|
|
210
|
+
if (entry === undefined || !current.records.has(key))
|
|
211
|
+
return yield* ThreadStoreError.make({
|
|
212
|
+
operation: "delivery work",
|
|
213
|
+
message: "Pending delivery index is incomplete or corrupt",
|
|
214
|
+
});
|
|
215
|
+
entries.push(entry);
|
|
216
|
+
}
|
|
217
|
+
const next = ids.length > limit ? ids[limit - 1] : undefined;
|
|
218
|
+
|
|
219
|
+
return { entries, ...(next === undefined ? {} : { after: next }) };
|
|
220
|
+
}),
|
|
222
221
|
});
|
|
223
222
|
|
|
224
223
|
const commitInto = (
|
|
@@ -662,19 +662,19 @@ function* threadRows(state: LedgerState, threadId: ThreadId, after = -1) {
|
|
|
662
662
|
}
|
|
663
663
|
}
|
|
664
664
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
665
|
+
const makeSubmissionLedger = Effect.fnUntraced(
|
|
666
|
+
/**
|
|
667
|
+
* Reference in-memory SubmissionLedger. Admission, ordered selection and canonical settlement
|
|
668
|
+
* share the Memory kernel's mutation gate. The kernel Scope owns local Run capabilities;
|
|
669
|
+
* selecting work does not write execution ownership into the ledger.
|
|
670
|
+
*
|
|
671
|
+
* Joining retains the contiguous ready prefix and exact host linkage. Canonical settlement
|
|
672
|
+
* authorizes finalization and child wake repair, while bound sessions reject late commands.
|
|
673
|
+
* Child wake checks read the child rows directly, without a separate notification marker.
|
|
674
|
+
* Admission resolution is strongly consistent; resolveAdmissionFault injects the
|
|
675
|
+
* Indeterminate outcome for existing caller conformance workflows.
|
|
676
|
+
*/
|
|
677
|
+
function* (options: MemorySubmissionLedgerOptions = {}) {
|
|
678
678
|
const journal = yield* MemoryThreadStoreKernel;
|
|
679
679
|
const crypto = yield* Crypto.Crypto;
|
|
680
680
|
|
|
@@ -721,47 +721,46 @@ const makeSubmissionLedger = (options: MemorySubmissionLedgerOptions = {}) =>
|
|
|
721
721
|
};
|
|
722
722
|
}),
|
|
723
723
|
),
|
|
724
|
-
page: (threadId, after, limit)
|
|
725
|
-
|
|
726
|
-
const current = yield* Ref.get(state);
|
|
724
|
+
page: Effect.fnUntraced(function* (threadId, after, limit) {
|
|
725
|
+
const current = yield* Ref.get(state);
|
|
727
726
|
|
|
728
|
-
|
|
727
|
+
const candidates = boundedWorkSelection<SubmissionId>(limit + 1, (id) => id, after);
|
|
729
728
|
|
|
730
|
-
|
|
731
|
-
|
|
729
|
+
for (const id of current.activeByThread.get(threadId) ?? []) candidates.add(id);
|
|
730
|
+
const ids = candidates.values;
|
|
732
731
|
|
|
733
|
-
|
|
732
|
+
const entries = [];
|
|
734
733
|
|
|
735
|
-
|
|
736
|
-
|
|
734
|
+
for (const id of ids.slice(0, limit)) {
|
|
735
|
+
const stored = current.submissions.get(id);
|
|
737
736
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
737
|
+
if (
|
|
738
|
+
stored === undefined ||
|
|
739
|
+
stored.row.threadId !== threadId ||
|
|
740
|
+
stored.row.state === "settled"
|
|
741
|
+
)
|
|
742
|
+
return yield* ThreadStoreError.make({
|
|
743
|
+
operation: "admission work",
|
|
744
|
+
message: "Active admission index is incomplete or corrupt",
|
|
745
|
+
});
|
|
746
|
+
const entry = admissionWork(stored.row);
|
|
747
|
+
|
|
748
|
+
entries.push(
|
|
749
|
+
stored.suspension === undefined
|
|
750
|
+
? entry
|
|
751
|
+
: {
|
|
752
|
+
...entry,
|
|
753
|
+
wait:
|
|
754
|
+
stored.suspension.reason._tag === "WaitingForChild"
|
|
755
|
+
? ("child" as const)
|
|
756
|
+
: ("approval" as const),
|
|
757
|
+
},
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
const next = ids.length > limit ? ids[limit - 1] : undefined;
|
|
762
761
|
|
|
763
|
-
|
|
764
|
-
|
|
762
|
+
return { entries, ...(next === undefined ? {} : { after: next }) };
|
|
763
|
+
}),
|
|
765
764
|
});
|
|
766
765
|
|
|
767
766
|
const admissionFence = yield* SubmissionAdmissionFence;
|
|
@@ -3521,7 +3520,8 @@ const makeSubmissionLedger = (options: MemorySubmissionLedgerOptions = {}) =>
|
|
|
3521
3520
|
return Context.make(SubmissionLedger, ledger).pipe(
|
|
3522
3521
|
Context.add(SettlementPublisher, { publish }),
|
|
3523
3522
|
);
|
|
3524
|
-
}
|
|
3523
|
+
},
|
|
3524
|
+
);
|
|
3525
3525
|
|
|
3526
3526
|
/** Construction options for the in-memory reference SubmissionLedger. */
|
|
3527
3527
|
export interface MemorySubmissionLedgerOptions {
|
package/src/MemoryThreadStore.ts
CHANGED
|
@@ -225,7 +225,11 @@ const storedBytes = (thread: StoredThread, sequence: number) =>
|
|
|
225
225
|
(sequence - 1) % RECORD_CHUNK_SIZE
|
|
226
226
|
];
|
|
227
227
|
|
|
228
|
-
const storedPage = (
|
|
228
|
+
const storedPage = Effect.fnUntraced(function* (
|
|
229
|
+
thread: StoredThread,
|
|
230
|
+
after: number,
|
|
231
|
+
limit: number,
|
|
232
|
+
) {
|
|
229
233
|
const page: Array<CanonicalRecordEnvelope> = [];
|
|
230
234
|
let bytes = 0;
|
|
231
235
|
|
|
@@ -236,7 +240,7 @@ const storedPage = (thread: StoredThread, after: number, limit: number) => {
|
|
|
236
240
|
) {
|
|
237
241
|
const record = storedRecord(thread, sequence);
|
|
238
242
|
|
|
239
|
-
if (record === undefined)
|
|
243
|
+
if (record === undefined) return yield* storeError("read", "Incomplete canonical chunk table");
|
|
240
244
|
const size = storedBytes(thread, sequence) ?? 0;
|
|
241
245
|
|
|
242
246
|
if (bytes + size > 32 * 1024 * 1024) break;
|
|
@@ -245,7 +249,7 @@ const storedPage = (thread: StoredThread, after: number, limit: number) => {
|
|
|
245
249
|
}
|
|
246
250
|
|
|
247
251
|
return page;
|
|
248
|
-
};
|
|
252
|
+
});
|
|
249
253
|
|
|
250
254
|
const retainRecords = (thread: StoredThread, records: ReadonlyArray<CanonicalRecordEnvelope>) => {
|
|
251
255
|
for (const entry of records) {
|
|
@@ -1533,7 +1537,7 @@ const makeThreadStore = Effect.gen(function* () {
|
|
|
1533
1537
|
) =>
|
|
1534
1538
|
Ref.get(state).pipe(
|
|
1535
1539
|
Effect.flatMap((current) => findThread(current, threadId)),
|
|
1536
|
-
Effect.
|
|
1540
|
+
Effect.flatMap((thread) => {
|
|
1537
1541
|
// Append assigns gap-free sequences starting at 1, so the exclusive cursor is an index.
|
|
1538
1542
|
const start = afterSequence ?? ZERO_CANONICAL_SEQUENCE;
|
|
1539
1543
|
|
|
@@ -1598,7 +1602,7 @@ const makeThreadStore = Effect.gen(function* () {
|
|
|
1598
1602
|
{ after: request.afterSequence ?? ZERO_CANONICAL_SEQUENCE, count: 0 },
|
|
1599
1603
|
(cursor) =>
|
|
1600
1604
|
Effect.gen(function* () {
|
|
1601
|
-
const page = storedPage(
|
|
1605
|
+
const page = yield* storedPage(
|
|
1602
1606
|
thread,
|
|
1603
1607
|
cursor.after,
|
|
1604
1608
|
Math.min(READ_PAGE_SIZE, request.limit - cursor.count),
|
|
@@ -2038,26 +2042,25 @@ const makeThreadStore = Effect.gen(function* () {
|
|
|
2038
2042
|
const verificationPage: ThreadStore["Service"]["export"] = (request) =>
|
|
2039
2043
|
exportThreadPage(request).pipe(Effect.provideService(ThreadExporterReader, verificationReader));
|
|
2040
2044
|
|
|
2041
|
-
const exactRunRecords = (thread: StoredThread, runId: RunId)
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
const facts = thread.runRecords.get(runId) ?? [];
|
|
2045
|
+
const exactRunRecords = Effect.fnUntraced(function* (thread: StoredThread, runId: RunId) {
|
|
2046
|
+
const records: Array<CanonicalRecordEnvelope> = [];
|
|
2047
|
+
let bytes = 0;
|
|
2048
|
+
const facts = thread.runRecords.get(runId) ?? [];
|
|
2046
2049
|
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2050
|
+
if (
|
|
2051
|
+
facts.length >
|
|
2052
|
+
MAX_RUN_EVIDENCE_RECORDS + RUN_TERMINAL_RESERVE_RECORDS + MAX_RUN_RECOVERY_SUFFIX_RECORDS
|
|
2053
|
+
)
|
|
2054
|
+
return yield* storeError("Run evidence", "Run record bounds exceeded");
|
|
2055
|
+
for (const entry of facts) {
|
|
2056
|
+
bytes += canonicalRecordBytes(entry.record);
|
|
2057
|
+
if (bytes > MAX_RUN_EVIDENCE_BYTES + MAX_RUN_TERMINAL_BYTES + MAX_RUN_RECOVERY_SUFFIX_BYTES)
|
|
2058
|
+
return yield* storeError("Run evidence", "Run byte bounds exceeded");
|
|
2059
|
+
records.push(entry);
|
|
2060
|
+
}
|
|
2058
2061
|
|
|
2059
|
-
|
|
2060
|
-
|
|
2062
|
+
return records.sort((a, b) => a.sequence - b.sequence);
|
|
2063
|
+
});
|
|
2061
2064
|
|
|
2062
2065
|
const exactRecordReader = (
|
|
2063
2066
|
threadId: ThreadId,
|
|
@@ -2853,33 +2856,41 @@ const makeThreadStore = Effect.gen(function* () {
|
|
|
2853
2856
|
},
|
|
2854
2857
|
registerWorkOwner: (kind, owner) =>
|
|
2855
2858
|
withMutation(
|
|
2856
|
-
Effect.
|
|
2859
|
+
Effect.gen(function* () {
|
|
2857
2860
|
if (workOwners.has(kind))
|
|
2858
|
-
|
|
2861
|
+
return yield* Effect.die(
|
|
2862
|
+
storeError("initialize", `MemoryThreadStore already has a ${kind} work owner`),
|
|
2863
|
+
);
|
|
2859
2864
|
workOwners.set(kind, owner);
|
|
2860
2865
|
}),
|
|
2861
2866
|
),
|
|
2862
2867
|
registerDeliveryLookup: (lookup) =>
|
|
2863
2868
|
withMutation(
|
|
2864
|
-
Effect.
|
|
2869
|
+
Effect.gen(function* () {
|
|
2865
2870
|
if (deliveryLookup !== undefined)
|
|
2866
|
-
|
|
2871
|
+
return yield* Effect.die(
|
|
2872
|
+
storeError("initialize", "MemoryThreadStore already has a delivery lookup"),
|
|
2873
|
+
);
|
|
2867
2874
|
deliveryLookup = lookup;
|
|
2868
2875
|
}),
|
|
2869
2876
|
),
|
|
2870
2877
|
registerLedgerTransfer: (transfer) =>
|
|
2871
2878
|
withMutation(
|
|
2872
|
-
Effect.
|
|
2879
|
+
Effect.gen(function* () {
|
|
2873
2880
|
if (ledgerTransfer !== undefined)
|
|
2874
|
-
|
|
2881
|
+
return yield* Effect.die(
|
|
2882
|
+
storeError("initialize", "MemoryThreadStore already has a paired SubmissionLedger"),
|
|
2883
|
+
);
|
|
2875
2884
|
ledgerTransfer = transfer;
|
|
2876
2885
|
}),
|
|
2877
2886
|
),
|
|
2878
2887
|
registerDeliveryTransfer: (transfer) =>
|
|
2879
2888
|
withMutation(
|
|
2880
|
-
Effect.
|
|
2889
|
+
Effect.gen(function* () {
|
|
2881
2890
|
if (deliveryTransfer !== undefined)
|
|
2882
|
-
|
|
2891
|
+
return yield* Effect.die(
|
|
2892
|
+
storeError("initialize", "MemoryThreadStore already has a paired delivery store"),
|
|
2893
|
+
);
|
|
2883
2894
|
deliveryTransfer = transfer;
|
|
2884
2895
|
}),
|
|
2885
2896
|
),
|