@statelyai/agent 2.0.0-alpha.14 → 2.0.0-alpha.16

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.
Files changed (35) hide show
  1. package/dist/ai-sdk.cjs +1 -1
  2. package/dist/ai-sdk.d.cts +2 -2
  3. package/dist/ai-sdk.d.mts +2 -2
  4. package/dist/ai-sdk.mjs +1 -1
  5. package/dist/{decision-C0cUKvNt.cjs → decision-Ba8qrT8r.cjs} +42 -28
  6. package/dist/{decision-D9Zi7Xi5.mjs → decision-Bt2HYYRo.mjs} +31 -23
  7. package/dist/{event-log-store-D7pWtIhb.mjs → event-log-store-B-1fcfkT.mjs} +149 -141
  8. package/dist/{event-log-store-BkUNtyOF.d.mts → event-log-store-BrC9Q1xW.d.mts} +14 -12
  9. package/dist/{event-log-store-CVd2eyRy.d.cts → event-log-store-CQJq8_v4.d.cts} +14 -12
  10. package/dist/{event-log-store-CNT_7F0V.cjs → event-log-store-yquOV1TX.cjs} +148 -140
  11. package/dist/index.cjs +520 -521
  12. package/dist/index.d.cts +128 -106
  13. package/dist/index.d.mts +128 -106
  14. package/dist/index.mjs +519 -520
  15. package/dist/machines.cjs +1 -1
  16. package/dist/machines.d.cts +1 -1
  17. package/dist/machines.d.mts +1 -1
  18. package/dist/machines.mjs +1 -1
  19. package/dist/otel.d.cts +1 -1
  20. package/dist/otel.d.mts +1 -1
  21. package/dist/{run-agent-BlqKwHIF.d.cts → run-agent-BxjGaVpL.d.cts} +72 -111
  22. package/dist/{run-agent-2MnlQTkB.d.mts → run-agent-COHoCgQd.d.mts} +72 -111
  23. package/dist/{setup-agent-CpK0ZRWV.cjs → setup-agent-BLU77gqr.cjs} +141 -172
  24. package/dist/{setup-agent-DeHRW-qX.mjs → setup-agent-SbiiSbAU.mjs} +136 -167
  25. package/dist/sqlite.cjs +1 -1
  26. package/dist/sqlite.d.cts +2 -2
  27. package/dist/sqlite.d.mts +2 -2
  28. package/dist/sqlite.mjs +1 -1
  29. package/dist/{text-logic-Jkilp1Ie.d.cts → text-logic-BFX5q7fM.d.cts} +26 -3
  30. package/dist/{text-logic-C5kbjaDz.d.mts → text-logic-DQW8_DWW.d.mts} +26 -3
  31. package/dist/{types-rMe7x6NR.d.cts → types-DYpK3QF4.d.mts} +35 -7
  32. package/dist/{types-9Bqg5rZB.d.mts → types-pJ5Hn8fv.d.cts} +35 -7
  33. package/package.json +28 -28
  34. package/readme.md +6 -19
  35. package/schemas/agent-workflow.json +1 -4
@@ -1,6 +1,19 @@
1
1
  import { t as AgentError } from "./errors-BQRk9eiZ.cjs";
2
2
  import { EventObject } from "xstate";
3
3
 
4
+ //#region src/event-log-store-conformance.d.ts
5
+ /** Produces a fresh, empty store for one assertion. */
6
+ type CreateStore = () => Promise<AgentEventLogStore> | AgentEventLogStore;
7
+ /**
8
+ * Validates a store against the reference's semantics: empty read + zero length
9
+ * for unknown threads; single and multi-entry append; contiguity misuse guard;
10
+ * stale-`expectedIndex` conflict with correct fields; an interleaved concurrent
11
+ * append race (exactly one winner); event-id uniqueness; `read({ from })`
12
+ * incremental correctness; thread isolation; metadata round-trip; deep-copy
13
+ * isolation on append and read; and the full fork contract.
14
+ */
15
+ declare function assertEventLogStoreConformance(create: CreateStore): Promise<void>;
16
+ //#endregion
4
17
  //#region src/event-log-store.d.ts
5
18
  /** The durable replay-entry envelope version. */
6
19
  declare const AGENT_EVENT_SCHEMA_VERSION: 1;
@@ -129,16 +142,5 @@ declare class AgentEventLogConflictError extends AgentError {
129
142
  * value it appended nor through a value it read.
130
143
  */
131
144
  declare function createInMemoryEventLogStore(): AgentEventLogStore;
132
- /** Produces a fresh, empty store for one assertion. */
133
- type CreateStore = () => Promise<AgentEventLogStore> | AgentEventLogStore;
134
- /**
135
- * Validates a store against the reference's semantics: empty read + zero length
136
- * for unknown threads; single and multi-entry append; contiguity misuse guard;
137
- * stale-`expectedIndex` conflict with correct fields; an interleaved concurrent
138
- * append race (exactly one winner); event-id uniqueness; `read({ from })`
139
- * incremental correctness; thread isolation; metadata round-trip; deep-copy
140
- * isolation on append and read; and the full fork contract.
141
- */
142
- declare function assertEventLogStoreConformance(create: CreateStore): Promise<void>;
143
145
  //#endregion
144
- export { AgentLogVerification as a, assertAgentLogEntry as c, createInMemoryEventLogStore as d, AgentLogEntry as i, assertEventLogStoreConformance as l, AgentEventLogConflictError as n, JsonValue as o, AgentEventLogStore as r, NonSerializableAgentEventError as s, AGENT_EVENT_SCHEMA_VERSION as t, assertJsonSerializable as u };
146
+ export { AgentLogVerification as a, assertAgentLogEntry as c, assertEventLogStoreConformance as d, AgentLogEntry as i, assertJsonSerializable as l, AgentEventLogConflictError as n, JsonValue as o, AgentEventLogStore as r, NonSerializableAgentEventError as s, AGENT_EVENT_SCHEMA_VERSION as t, createInMemoryEventLogStore as u };
@@ -1,146 +1,12 @@
1
1
  const require_errors = require("./errors-DUBBzRLP.cjs");
2
- //#region src/event-log-store.ts
3
- /** The durable replay-entry envelope version. */
4
- const AGENT_EVENT_SCHEMA_VERSION = 1;
5
- /** A precise failure when an entry would not survive a JSON round-trip. */
6
- var NonSerializableAgentEventError = class extends require_errors.AgentError {
7
- path;
8
- valueType;
9
- constructor(path, valueType) {
10
- super("non-serializable-event", `Agent event field '${path}' is not JSON-serializable (${valueType}).`);
11
- this.name = "NonSerializableAgentEventError";
12
- this.path = path;
13
- this.valueType = valueType;
14
- }
15
- };
16
- /**
17
- * Rejects values JSON would drop or coerce. Unlike `JSON.stringify`, this does
18
- * not silently erase `undefined`/functions or turn non-finite numbers into
19
- * `null`; durable entries contain only plain JSON values.
20
- */
21
- function assertJsonSerializable(value, path = "entry", ancestors = /* @__PURE__ */ new WeakSet()) {
22
- if (value === null || typeof value === "string" || typeof value === "boolean") return;
23
- if (typeof value === "number") {
24
- if (!Number.isFinite(value) || Object.is(value, -0)) throw new NonSerializableAgentEventError(path, Object.is(value, -0) ? "-0" : String(value));
25
- return;
26
- }
27
- if (typeof value !== "object") throw new NonSerializableAgentEventError(path, typeof value);
28
- if (ancestors.has(value)) throw new NonSerializableAgentEventError(path, "circular reference");
29
- ancestors.add(value);
30
- if (Array.isArray(value)) {
31
- for (let index = 0; index < value.length; index++) {
32
- if (!Object.hasOwn(value, index)) throw new NonSerializableAgentEventError(`${path}[${index}]`, "array hole");
33
- assertJsonSerializable(value[index], `${path}[${index}]`, ancestors);
34
- }
35
- const extraKey = Object.keys(value).find((key) => !/^(?:0|[1-9]\d*)$/.test(key) || Number(key) >= value.length);
36
- if (extraKey !== void 0) throw new NonSerializableAgentEventError(`${path}.${extraKey}`, "array property");
37
- const symbols = Object.getOwnPropertySymbols(value);
38
- if (symbols.length > 0) throw new NonSerializableAgentEventError(`${path}.[${String(symbols[0])}]`, "symbol key");
39
- const hiddenKey = Object.getOwnPropertyNames(value).find((key) => key !== "length" && !/^(?:0|[1-9]\d*)$/.test(key) && !Object.getOwnPropertyDescriptor(value, key)?.enumerable);
40
- if (hiddenKey !== void 0) throw new NonSerializableAgentEventError(`${path}.${hiddenKey}`, "non-enumerable property");
41
- ancestors.delete(value);
42
- return;
43
- }
44
- const prototype = Object.getPrototypeOf(value);
45
- if (prototype !== Object.prototype && prototype !== null) {
46
- const type = value.constructor?.name ?? "object";
47
- ancestors.delete(value);
48
- throw new NonSerializableAgentEventError(path, type);
49
- }
50
- const symbols = Object.getOwnPropertySymbols(value);
51
- if (symbols.length > 0) {
52
- ancestors.delete(value);
53
- throw new NonSerializableAgentEventError(`${path}.[${String(symbols[0])}]`, "symbol key");
54
- }
55
- const hiddenKey = Object.getOwnPropertyNames(value).find((key) => !Object.getOwnPropertyDescriptor(value, key)?.enumerable);
56
- if (hiddenKey !== void 0) {
57
- ancestors.delete(value);
58
- throw new NonSerializableAgentEventError(`${path}.${hiddenKey}`, "non-enumerable property");
59
- }
60
- for (const [key, child] of Object.entries(value)) assertJsonSerializable(child, `${path}.${key}`, ancestors);
61
- ancestors.delete(value);
62
- }
63
- /** Validates the complete durable envelope before append/export/replay. */
64
- function assertAgentLogEntry(entry) {
65
- if (entry === null || typeof entry !== "object" || Array.isArray(entry)) throw new Error("Agent event entry must be an object.");
66
- assertJsonSerializable(entry);
67
- const candidate = entry;
68
- if (candidate.schemaVersion !== 1) throw new Error(`Unsupported agent event schema version '${String(candidate.schemaVersion)}'; expected '1'.`);
69
- if (!Number.isInteger(candidate.index) || candidate.index < 0) throw new Error(`Agent event entry.index must be a non-negative integer; got ${String(candidate.index)}.`);
70
- if (typeof candidate.id !== "string" || !candidate.id || typeof candidate.machineId !== "string" || !candidate.machineId || typeof candidate.machineVersion !== "string" || !candidate.machineVersion) throw new Error("Agent event entry requires non-empty id, machineId, and machineVersion.");
71
- if (typeof candidate.recordedAt !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(candidate.recordedAt) || Number.isNaN(Date.parse(candidate.recordedAt))) throw new Error(`Agent event entry.recordedAt is not RFC 3339: '${String(candidate.recordedAt)}'.`);
72
- if (candidate.event === null || typeof candidate.event !== "object" || Array.isArray(candidate.event) || typeof candidate.event.type !== "string" || !candidate.event.type) throw new Error("Agent event entry.event requires a non-empty string type.");
73
- if (candidate.causationId !== void 0 && (typeof candidate.causationId !== "string" || !candidate.causationId)) throw new Error("Agent event entry.causationId must be a non-empty string when present.");
74
- if (candidate.correlationId !== void 0 && (typeof candidate.correlationId !== "string" || !candidate.correlationId)) throw new Error("Agent event entry.correlationId must be a non-empty string when present.");
75
- if (candidate.metadata !== void 0 && (candidate.metadata === null || typeof candidate.metadata !== "object" || Array.isArray(candidate.metadata))) throw new Error("Agent event entry.metadata must be an object when present.");
76
- if (candidate.verification !== void 0 && (candidate.verification === null || typeof candidate.verification !== "object" || typeof candidate.verification.stateHash !== "string" || !candidate.verification.stateHash || typeof candidate.verification.effectsHash !== "string" || !candidate.verification.effectsHash)) throw new Error("Agent event entry.verification requires non-empty stateHash and effectsHash strings.");
77
- }
78
- /**
79
- * Rejection from {@link AgentEventLogStore.append} when the thread's stored
80
- * length is not the `expectedIndex` the writer held — a concurrent writer
81
- * appended first. `actualLength` is the length core found.
82
- */
83
- var AgentEventLogConflictError = class extends require_errors.AgentError {
84
- threadId;
85
- expectedIndex;
86
- actualLength;
87
- constructor(threadId, expectedIndex, actualLength) {
88
- super("event-log-conflict", `AgentEventLogStore.append: length conflict on thread "${threadId}": expected length ${expectedIndex} but found ${actualLength} — a concurrent writer won.`);
89
- this.name = "AgentEventLogConflictError";
90
- this.threadId = threadId;
91
- this.expectedIndex = expectedIndex;
92
- this.actualLength = actualLength;
93
- }
94
- };
2
+ //#region src/event-log-store-conformance.ts
95
3
  /**
96
- * In-memory reference store, and the baseline the conformance suite runs
97
- * against. Per-thread entries are held in a contiguous, index-ordered list;
98
- * append's check-and-push runs synchronously (no `await` between reading the
99
- * length and writing), so two appends racing on the same `expectedIndex`
100
- * resolve to exactly one winner. Every stored and returned entry is
101
- * `structuredClone`d, so a caller can neither mutate stored state through a
102
- * value it appended nor through a value it read.
4
+ * The runner-agnostic conformance suite for {@link AgentEventLogStore}
5
+ * implementations. Split out of `event-log-store.ts` so the store contract and
6
+ * the reference implementation stay readable; re-exported from there (and from
7
+ * the package root) so the public surface is unchanged.
8
+ * @module
103
9
  */
104
- function createInMemoryEventLogStore() {
105
- const threads = /* @__PURE__ */ new Map();
106
- const clone = (value) => structuredClone(value);
107
- return {
108
- async append({ threadId, expectedIndex, entries }) {
109
- for (const entry of entries) assertAgentLogEntry(entry);
110
- for (let i = 0; i < entries.length; i++) if (entries[i].index !== expectedIndex + i) throw new Error(`AgentEventLogStore.append: entry.index (${entries[i].index}) must be contiguous from expectedIndex (${expectedIndex}); expected ${expectedIndex + i} at position ${i} on thread "${threadId}".`);
111
- const list = threads.get(threadId);
112
- const length = list ? list.length : 0;
113
- if (length !== expectedIndex) throw new AgentEventLogConflictError(threadId, expectedIndex, length);
114
- const ids = new Set((list ?? []).map((entry) => entry.id));
115
- for (const entry of entries) {
116
- if (ids.has(entry.id)) throw new Error(`AgentEventLogStore.append: duplicate event id "${entry.id}" in thread "${threadId}".`);
117
- ids.add(entry.id);
118
- }
119
- const cloned = entries.map((entry) => clone(entry));
120
- if (list) for (const entry of cloned) list.push(entry);
121
- else threads.set(threadId, cloned);
122
- },
123
- async read(threadId, options) {
124
- const list = threads.get(threadId) ?? [];
125
- const from = options?.from ?? 0;
126
- return list.slice(from).map((entry) => clone(entry));
127
- },
128
- async length(threadId) {
129
- return threads.get(threadId)?.length ?? 0;
130
- },
131
- async fork({ threadId, newThreadId, upToIndex, atEventId }) {
132
- if ((threads.get(newThreadId)?.length ?? 0) > 0) throw new Error(`AgentEventLogStore.fork: newThreadId "${newThreadId}" already has entries.`);
133
- const source = threads.get(threadId);
134
- if (!source) throw new Error(`AgentEventLogStore.fork: unknown source thread "${threadId}".`);
135
- if (upToIndex !== void 0 && atEventId !== void 0) throw new Error("AgentEventLogStore.fork: pass either upToIndex or atEventId, not both.");
136
- const eventIndex = atEventId === void 0 ? void 0 : source.findIndex((entry) => entry.id === atEventId);
137
- if (atEventId !== void 0 && eventIndex === -1) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" has no event id "${atEventId}".`);
138
- const upTo = eventIndex === void 0 ? upToIndex ?? source.length : eventIndex + 1;
139
- if (upTo < 0 || upTo > source.length) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" (length ${source.length}) has no index ${upTo} to fork up to.`);
140
- threads.set(newThreadId, source.slice(0, upTo).map((entry) => clone(entry)));
141
- }
142
- };
143
- }
144
10
  function fail(message) {
145
11
  throw new Error(`event-log-store conformance: ${message}`);
146
12
  }
@@ -408,6 +274,148 @@ async function assertEventLogStoreConformance(create) {
408
274
  }
409
275
  }
410
276
  //#endregion
277
+ //#region src/event-log-store.ts
278
+ /** The durable replay-entry envelope version. */
279
+ const AGENT_EVENT_SCHEMA_VERSION = 1;
280
+ /** A precise failure when an entry would not survive a JSON round-trip. */
281
+ var NonSerializableAgentEventError = class extends require_errors.AgentError {
282
+ path;
283
+ valueType;
284
+ constructor(path, valueType) {
285
+ super("non-serializable-event", `Agent event field '${path}' is not JSON-serializable (${valueType}).`);
286
+ this.name = "NonSerializableAgentEventError";
287
+ this.path = path;
288
+ this.valueType = valueType;
289
+ }
290
+ };
291
+ function assertNoHiddenKeys(value, path, isOwnKey) {
292
+ const symbols = Object.getOwnPropertySymbols(value);
293
+ if (symbols.length > 0) throw new NonSerializableAgentEventError(`${path}.[${String(symbols[0])}]`, "symbol key");
294
+ const hiddenKey = Object.getOwnPropertyNames(value).find((key) => !isOwnKey?.(key) && !Object.getOwnPropertyDescriptor(value, key)?.enumerable);
295
+ if (hiddenKey !== void 0) throw new NonSerializableAgentEventError(`${path}.${hiddenKey}`, "non-enumerable property");
296
+ }
297
+ const arrayIndexPattern = /^(?:0|[1-9]\d*)$/;
298
+ /**
299
+ * Rejects values JSON would drop or coerce. Unlike `JSON.stringify`, this does
300
+ * not silently erase `undefined`/functions or turn non-finite numbers into
301
+ * `null`; durable entries contain only plain JSON values.
302
+ */
303
+ function assertJsonSerializable(value, path = "entry", ancestors = /* @__PURE__ */ new WeakSet()) {
304
+ if (value === null || typeof value === "string" || typeof value === "boolean") return;
305
+ if (typeof value === "number") {
306
+ if (!Number.isFinite(value) || Object.is(value, -0)) throw new NonSerializableAgentEventError(path, Object.is(value, -0) ? "-0" : String(value));
307
+ return;
308
+ }
309
+ if (typeof value !== "object") throw new NonSerializableAgentEventError(path, typeof value);
310
+ if (ancestors.has(value)) throw new NonSerializableAgentEventError(path, "circular reference");
311
+ ancestors.add(value);
312
+ try {
313
+ if (Array.isArray(value)) {
314
+ for (let index = 0; index < value.length; index++) {
315
+ if (!Object.hasOwn(value, index)) throw new NonSerializableAgentEventError(`${path}[${index}]`, "array hole");
316
+ assertJsonSerializable(value[index], `${path}[${index}]`, ancestors);
317
+ }
318
+ const extraKey = Object.keys(value).find((key) => !arrayIndexPattern.test(key) || Number(key) >= value.length);
319
+ if (extraKey !== void 0) throw new NonSerializableAgentEventError(`${path}.${extraKey}`, "array property");
320
+ assertNoHiddenKeys(value, path, (key) => key === "length" || arrayIndexPattern.test(key));
321
+ return;
322
+ }
323
+ const prototype = Object.getPrototypeOf(value);
324
+ if (prototype !== Object.prototype && prototype !== null) throw new NonSerializableAgentEventError(path, value.constructor?.name ?? "object");
325
+ assertNoHiddenKeys(value, path);
326
+ for (const [key, child] of Object.entries(value)) assertJsonSerializable(child, `${path}.${key}`, ancestors);
327
+ } finally {
328
+ ancestors.delete(value);
329
+ }
330
+ }
331
+ function requireNonEmptyString(value, label, qualifier = "") {
332
+ if (typeof value !== "string" || !value) throw new Error(`Agent event ${label} must be a non-empty string${qualifier}.`);
333
+ }
334
+ /** Validates the complete durable envelope before append/export/replay. */
335
+ function assertAgentLogEntry(entry) {
336
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) throw new Error("Agent event entry must be an object.");
337
+ assertJsonSerializable(entry);
338
+ const candidate = entry;
339
+ if (candidate.schemaVersion !== 1) throw new Error(`Unsupported agent event schema version '${String(candidate.schemaVersion)}'; expected '1'.`);
340
+ if (!Number.isInteger(candidate.index) || candidate.index < 0) throw new Error(`Agent event entry.index must be a non-negative integer; got ${String(candidate.index)}.`);
341
+ for (const field of [
342
+ "id",
343
+ "machineId",
344
+ "machineVersion"
345
+ ]) requireNonEmptyString(candidate[field], `entry.${field}`);
346
+ if (typeof candidate.recordedAt !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(candidate.recordedAt) || Number.isNaN(Date.parse(candidate.recordedAt))) throw new Error(`Agent event entry.recordedAt is not RFC 3339: '${String(candidate.recordedAt)}'.`);
347
+ if (candidate.event === null || typeof candidate.event !== "object" || Array.isArray(candidate.event) || typeof candidate.event.type !== "string" || !candidate.event.type) throw new Error("Agent event entry.event requires a non-empty string type.");
348
+ for (const field of ["causationId", "correlationId"]) if (candidate[field] !== void 0) requireNonEmptyString(candidate[field], `entry.${field}`, " when present");
349
+ if (candidate.metadata !== void 0 && (candidate.metadata === null || typeof candidate.metadata !== "object" || Array.isArray(candidate.metadata))) throw new Error("Agent event entry.metadata must be an object when present.");
350
+ if (candidate.verification !== void 0 && (candidate.verification === null || typeof candidate.verification !== "object" || typeof candidate.verification.stateHash !== "string" || !candidate.verification.stateHash || typeof candidate.verification.effectsHash !== "string" || !candidate.verification.effectsHash)) throw new Error("Agent event entry.verification requires non-empty stateHash and effectsHash strings.");
351
+ }
352
+ /**
353
+ * Rejection from {@link AgentEventLogStore.append} when the thread's stored
354
+ * length is not the `expectedIndex` the writer held — a concurrent writer
355
+ * appended first. `actualLength` is the length core found.
356
+ */
357
+ var AgentEventLogConflictError = class extends require_errors.AgentError {
358
+ threadId;
359
+ expectedIndex;
360
+ actualLength;
361
+ constructor(threadId, expectedIndex, actualLength) {
362
+ super("event-log-conflict", `AgentEventLogStore.append: length conflict on thread "${threadId}": expected length ${expectedIndex} but found ${actualLength} — a concurrent writer won.`);
363
+ this.name = "AgentEventLogConflictError";
364
+ this.threadId = threadId;
365
+ this.expectedIndex = expectedIndex;
366
+ this.actualLength = actualLength;
367
+ }
368
+ };
369
+ /**
370
+ * In-memory reference store, and the baseline the conformance suite runs
371
+ * against. Per-thread entries are held in a contiguous, index-ordered list;
372
+ * append's check-and-push runs synchronously (no `await` between reading the
373
+ * length and writing), so two appends racing on the same `expectedIndex`
374
+ * resolve to exactly one winner. Every stored and returned entry is
375
+ * `structuredClone`d, so a caller can neither mutate stored state through a
376
+ * value it appended nor through a value it read.
377
+ */
378
+ function createInMemoryEventLogStore() {
379
+ const threads = /* @__PURE__ */ new Map();
380
+ const clone = (value) => structuredClone(value);
381
+ return {
382
+ async append({ threadId, expectedIndex, entries }) {
383
+ for (const entry of entries) assertAgentLogEntry(entry);
384
+ for (let i = 0; i < entries.length; i++) if (entries[i].index !== expectedIndex + i) throw new Error(`AgentEventLogStore.append: entry.index (${entries[i].index}) must be contiguous from expectedIndex (${expectedIndex}); expected ${expectedIndex + i} at position ${i} on thread "${threadId}".`);
385
+ const list = threads.get(threadId);
386
+ const length = list ? list.length : 0;
387
+ if (length !== expectedIndex) throw new AgentEventLogConflictError(threadId, expectedIndex, length);
388
+ const ids = new Set((list ?? []).map((entry) => entry.id));
389
+ for (const entry of entries) {
390
+ if (ids.has(entry.id)) throw new Error(`AgentEventLogStore.append: duplicate event id "${entry.id}" in thread "${threadId}".`);
391
+ ids.add(entry.id);
392
+ }
393
+ const cloned = entries.map((entry) => clone(entry));
394
+ if (list) for (const entry of cloned) list.push(entry);
395
+ else threads.set(threadId, cloned);
396
+ },
397
+ async read(threadId, options) {
398
+ const list = threads.get(threadId) ?? [];
399
+ const from = options?.from ?? 0;
400
+ return list.slice(from).map((entry) => clone(entry));
401
+ },
402
+ async length(threadId) {
403
+ return threads.get(threadId)?.length ?? 0;
404
+ },
405
+ async fork({ threadId, newThreadId, upToIndex, atEventId }) {
406
+ if ((threads.get(newThreadId)?.length ?? 0) > 0) throw new Error(`AgentEventLogStore.fork: newThreadId "${newThreadId}" already has entries.`);
407
+ const source = threads.get(threadId);
408
+ if (!source) throw new Error(`AgentEventLogStore.fork: unknown source thread "${threadId}".`);
409
+ if (upToIndex !== void 0 && atEventId !== void 0) throw new Error("AgentEventLogStore.fork: pass either upToIndex or atEventId, not both.");
410
+ const eventIndex = atEventId === void 0 ? void 0 : source.findIndex((entry) => entry.id === atEventId);
411
+ if (atEventId !== void 0 && eventIndex === -1) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" has no event id "${atEventId}".`);
412
+ const upTo = eventIndex === void 0 ? upToIndex ?? source.length : eventIndex + 1;
413
+ if (upTo < 0 || upTo > source.length) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" (length ${source.length}) has no index ${upTo} to fork up to.`);
414
+ threads.set(newThreadId, source.slice(0, upTo).map((entry) => clone(entry)));
415
+ }
416
+ };
417
+ }
418
+ //#endregion
411
419
  Object.defineProperty(exports, "AGENT_EVENT_SCHEMA_VERSION", {
412
420
  enumerable: true,
413
421
  get: function() {