@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.
- package/dist/ai-sdk.cjs +1 -1
- package/dist/ai-sdk.d.cts +2 -2
- package/dist/ai-sdk.d.mts +2 -2
- package/dist/ai-sdk.mjs +1 -1
- package/dist/{decision-C0cUKvNt.cjs → decision-Ba8qrT8r.cjs} +42 -28
- package/dist/{decision-D9Zi7Xi5.mjs → decision-Bt2HYYRo.mjs} +31 -23
- package/dist/{event-log-store-D7pWtIhb.mjs → event-log-store-B-1fcfkT.mjs} +149 -141
- package/dist/{event-log-store-BkUNtyOF.d.mts → event-log-store-BrC9Q1xW.d.mts} +14 -12
- package/dist/{event-log-store-CVd2eyRy.d.cts → event-log-store-CQJq8_v4.d.cts} +14 -12
- package/dist/{event-log-store-CNT_7F0V.cjs → event-log-store-yquOV1TX.cjs} +148 -140
- package/dist/index.cjs +520 -521
- package/dist/index.d.cts +128 -106
- package/dist/index.d.mts +128 -106
- package/dist/index.mjs +519 -520
- package/dist/machines.cjs +1 -1
- package/dist/machines.d.cts +1 -1
- package/dist/machines.d.mts +1 -1
- package/dist/machines.mjs +1 -1
- package/dist/otel.d.cts +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/{run-agent-BlqKwHIF.d.cts → run-agent-BxjGaVpL.d.cts} +72 -111
- package/dist/{run-agent-2MnlQTkB.d.mts → run-agent-COHoCgQd.d.mts} +72 -111
- package/dist/{setup-agent-CpK0ZRWV.cjs → setup-agent-BLU77gqr.cjs} +141 -172
- package/dist/{setup-agent-DeHRW-qX.mjs → setup-agent-SbiiSbAU.mjs} +136 -167
- package/dist/sqlite.cjs +1 -1
- package/dist/sqlite.d.cts +2 -2
- package/dist/sqlite.d.mts +2 -2
- package/dist/sqlite.mjs +1 -1
- package/dist/{text-logic-Jkilp1Ie.d.cts → text-logic-BFX5q7fM.d.cts} +26 -3
- package/dist/{text-logic-C5kbjaDz.d.mts → text-logic-DQW8_DWW.d.mts} +26 -3
- package/dist/{types-rMe7x6NR.d.cts → types-DYpK3QF4.d.mts} +35 -7
- package/dist/{types-9Bqg5rZB.d.mts → types-pJ5Hn8fv.d.cts} +35 -7
- package/package.json +28 -28
- package/readme.md +6 -19
- package/schemas/agent-workflow.json +1 -4
package/dist/ai-sdk.cjs
CHANGED
package/dist/ai-sdk.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as ChosenEvent } from "./types-
|
|
2
|
-
import {
|
|
1
|
+
import { d as ChosenEvent } from "./types-pJ5Hn8fv.cjs";
|
|
2
|
+
import { A as AgentDecisionExecutor, l as AgentRequestExecutors, o as AgentRequestExecutor } from "./text-logic-BFX5q7fM.cjs";
|
|
3
3
|
import { FinishReason, LanguageModel, LanguageModelUsage, ToolSet, TypedToolCall, TypedToolResult } from "ai";
|
|
4
4
|
|
|
5
5
|
//#region src/ai-sdk/index.d.ts
|
package/dist/ai-sdk.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as ChosenEvent } from "./types-
|
|
2
|
-
import {
|
|
1
|
+
import { d as ChosenEvent } from "./types-DYpK3QF4.mjs";
|
|
2
|
+
import { A as AgentDecisionExecutor, l as AgentRequestExecutors, o as AgentRequestExecutor } from "./text-logic-DQW8_DWW.mjs";
|
|
3
3
|
import { FinishReason, LanguageModel, LanguageModelUsage, ToolSet, TypedToolCall, TypedToolResult } from "ai";
|
|
4
4
|
|
|
5
5
|
//#region src/ai-sdk/index.d.ts
|
package/dist/ai-sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { H as isStandardSchema, _ as getAgentOutputMode, i as renderDecisionAttempts, p as buildEnvelopeSchema } from "./decision-Bt2HYYRo.mjs";
|
|
2
2
|
import { NoObjectGeneratedError, Output, generateText, stepCountIs, streamText, tool } from "ai";
|
|
3
3
|
//#region src/ai-sdk/mappers.ts
|
|
4
4
|
/**
|
|
@@ -98,6 +98,12 @@ function stableStructuralString(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
98
98
|
seen.delete(obj);
|
|
99
99
|
return out;
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* djb2 → unsigned 32-bit → 8-char hex. No dependencies. A change detector, not
|
|
103
|
+
* a cryptographic digest.
|
|
104
|
+
*
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
101
107
|
function djb2Hex(input) {
|
|
102
108
|
let hash = 5381;
|
|
103
109
|
for (let i = 0; i < input.length; i++) hash = (hash << 5) + hash + input.charCodeAt(i) | 0;
|
|
@@ -313,15 +319,26 @@ const AGENT_USAGE_TOKEN_FIELDS = [
|
|
|
313
319
|
"cachedInputTokens"
|
|
314
320
|
];
|
|
315
321
|
/**
|
|
316
|
-
* Reads a per-call {@link AgentCallUsage} off a
|
|
317
|
-
* field, keeping only finite numbers
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
322
|
+
* Reads a settled call's per-call {@link AgentCallUsage} off a RAW executor
|
|
323
|
+
* result's `usage` field, keeping only finite numbers — the same normalization
|
|
324
|
+
* `runAgent` applies before it delivers `'@agent.usage'`. Returns `undefined`
|
|
325
|
+
* when the result reports no usage at all. Works for our `{ output, usage }`
|
|
326
|
+
* envelope, for a raw Vercel AI SDK result (its `LanguageModelUsage` carries
|
|
327
|
+
* the same flat field names), and for any custom executor that follows the
|
|
328
|
+
* shape.
|
|
321
329
|
*
|
|
322
|
-
*
|
|
330
|
+
* The seam for the step-loop path, where the host holds the raw result itself:
|
|
331
|
+
*
|
|
332
|
+
* ```ts
|
|
333
|
+
* const { output, raw } = await executeAgentRequest(effect, executors);
|
|
334
|
+
* const usage = getCallUsage(raw);
|
|
335
|
+
* if (usage) append({ type: AGENT_USAGE_EVENT_TYPE, usage }); // journal + transition, like any event
|
|
336
|
+
* append(effect.toDoneEvent(output));
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
339
|
+
* See "Token usage on this path" in docs/steps.md for the full loop.
|
|
323
340
|
*/
|
|
324
|
-
function
|
|
341
|
+
function getCallUsage(raw) {
|
|
325
342
|
const usage = raw?.usage;
|
|
326
343
|
if (!usage || typeof usage !== "object") return;
|
|
327
344
|
let out;
|
|
@@ -344,13 +361,14 @@ const agentTextInputSchema = { "~standard": {
|
|
|
344
361
|
return { value: request };
|
|
345
362
|
}
|
|
346
363
|
} };
|
|
347
|
-
const
|
|
364
|
+
const passthroughSchema = { "~standard": {
|
|
348
365
|
version: 1,
|
|
349
366
|
vendor: "statelyai-agent",
|
|
350
367
|
validate(value) {
|
|
351
368
|
return { value };
|
|
352
369
|
}
|
|
353
370
|
} };
|
|
371
|
+
const unknownOutputSchema = passthroughSchema;
|
|
354
372
|
const stringOutputSchema = { "~standard": {
|
|
355
373
|
version: 1,
|
|
356
374
|
vendor: "statelyai-agent",
|
|
@@ -358,13 +376,7 @@ const stringOutputSchema = { "~standard": {
|
|
|
358
376
|
return typeof value === "string" ? { value } : { issues: [{ message: "Expected string output" }] };
|
|
359
377
|
}
|
|
360
378
|
} };
|
|
361
|
-
const noInputSchema =
|
|
362
|
-
version: 1,
|
|
363
|
-
vendor: "statelyai-agent",
|
|
364
|
-
validate(value) {
|
|
365
|
-
return { value };
|
|
366
|
-
}
|
|
367
|
-
} };
|
|
379
|
+
const noInputSchema = passthroughSchema;
|
|
368
380
|
function createBuiltinTextActor(src, mode, outputSchema) {
|
|
369
381
|
const logic = (0, xstate.createAsyncLogic)({ run: async () => {
|
|
370
382
|
throw new Error(`'${src}' has no host execution. Provide an implementation with machine.provide({ actors: { '${src}': ... } }) or execute the returned agent request with executeAgentRequest(...).`);
|
|
@@ -384,7 +396,7 @@ function createBuiltinTextActor(src, mode, outputSchema) {
|
|
|
384
396
|
return validateSchemaSync(outputSchema, output);
|
|
385
397
|
},
|
|
386
398
|
withExecutor(execute) {
|
|
387
|
-
return
|
|
399
|
+
return createTextLogic({
|
|
388
400
|
mode,
|
|
389
401
|
schemas: {
|
|
390
402
|
input: agentTextInputSchema,
|
|
@@ -405,7 +417,7 @@ function createBuiltinTextActor(src, mode, outputSchema) {
|
|
|
405
417
|
seed: ({ input }) => input.seed,
|
|
406
418
|
stopSequences: ({ input }) => input.stopSequences,
|
|
407
419
|
metadata: ({ input }) => input.metadata
|
|
408
|
-
}, execute)
|
|
420
|
+
}, execute);
|
|
409
421
|
}
|
|
410
422
|
});
|
|
411
423
|
}
|
|
@@ -552,7 +564,7 @@ function isTextLogic(value) {
|
|
|
552
564
|
* as `'text'`.
|
|
553
565
|
*/
|
|
554
566
|
function getAgentOutputMode(schema) {
|
|
555
|
-
const jsonSchema =
|
|
567
|
+
const jsonSchema = getJsonSchemaSync(schema);
|
|
556
568
|
if (!jsonSchema) return "text";
|
|
557
569
|
if (jsonSchema.type === "object" || jsonSchema.type === "array") return "structured";
|
|
558
570
|
if (jsonSchema.type === void 0 && ("anyOf" in jsonSchema || "oneOf" in jsonSchema || "allOf" in jsonSchema)) return "structured";
|
|
@@ -616,10 +628,6 @@ function parseStructuredEnvelope(request, value) {
|
|
|
616
628
|
if (!request.outputSchema) throw new Error("parseStructuredEnvelope: the request declares no outputSchema.");
|
|
617
629
|
return validateSchemaSync(buildEnvelopeSchema(request.outputSchema, { reasoning: request.reasoning }), value);
|
|
618
630
|
}
|
|
619
|
-
function getStandardSchemaJson(schema) {
|
|
620
|
-
const jsonSchema = (schema?.["~standard"])?.jsonSchema?.input?.();
|
|
621
|
-
return jsonSchema && !(jsonSchema instanceof Promise) ? jsonSchema : void 0;
|
|
622
|
-
}
|
|
623
631
|
/**
|
|
624
632
|
* Merges request-declared and call-site `tools`, dispatches to the
|
|
625
633
|
* `mode`-appropriate executor (`generateText`/`streamText`), and normalizes
|
|
@@ -1072,22 +1080,22 @@ Object.defineProperty(exports, "createTextLogic", {
|
|
|
1072
1080
|
return createTextLogic;
|
|
1073
1081
|
}
|
|
1074
1082
|
});
|
|
1075
|
-
Object.defineProperty(exports, "
|
|
1083
|
+
Object.defineProperty(exports, "djb2Hex", {
|
|
1076
1084
|
enumerable: true,
|
|
1077
1085
|
get: function() {
|
|
1078
|
-
return
|
|
1086
|
+
return djb2Hex;
|
|
1079
1087
|
}
|
|
1080
1088
|
});
|
|
1081
|
-
Object.defineProperty(exports, "
|
|
1089
|
+
Object.defineProperty(exports, "executeAgentTextRequest", {
|
|
1082
1090
|
enumerable: true,
|
|
1083
1091
|
get: function() {
|
|
1084
|
-
return
|
|
1092
|
+
return executeAgentTextRequest;
|
|
1085
1093
|
}
|
|
1086
1094
|
});
|
|
1087
|
-
Object.defineProperty(exports, "
|
|
1095
|
+
Object.defineProperty(exports, "executorBoundLogics", {
|
|
1088
1096
|
enumerable: true,
|
|
1089
1097
|
get: function() {
|
|
1090
|
-
return
|
|
1098
|
+
return executorBoundLogics;
|
|
1091
1099
|
}
|
|
1092
1100
|
});
|
|
1093
1101
|
Object.defineProperty(exports, "findNonSerializableContextPaths", {
|
|
@@ -1114,6 +1122,12 @@ Object.defineProperty(exports, "getAgentOutputMode", {
|
|
|
1114
1122
|
return getAgentOutputMode;
|
|
1115
1123
|
}
|
|
1116
1124
|
});
|
|
1125
|
+
Object.defineProperty(exports, "getCallUsage", {
|
|
1126
|
+
enumerable: true,
|
|
1127
|
+
get: function() {
|
|
1128
|
+
return getCallUsage;
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1117
1131
|
Object.defineProperty(exports, "getJsonSchema", {
|
|
1118
1132
|
enumerable: true,
|
|
1119
1133
|
get: function() {
|
|
@@ -98,6 +98,12 @@ function stableStructuralString(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
|
98
98
|
seen.delete(obj);
|
|
99
99
|
return out;
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* djb2 → unsigned 32-bit → 8-char hex. No dependencies. A change detector, not
|
|
103
|
+
* a cryptographic digest.
|
|
104
|
+
*
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
101
107
|
function djb2Hex(input) {
|
|
102
108
|
let hash = 5381;
|
|
103
109
|
for (let i = 0; i < input.length; i++) hash = (hash << 5) + hash + input.charCodeAt(i) | 0;
|
|
@@ -313,15 +319,26 @@ const AGENT_USAGE_TOKEN_FIELDS = [
|
|
|
313
319
|
"cachedInputTokens"
|
|
314
320
|
];
|
|
315
321
|
/**
|
|
316
|
-
* Reads a per-call {@link AgentCallUsage} off a
|
|
317
|
-
* field, keeping only finite numbers
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
322
|
+
* Reads a settled call's per-call {@link AgentCallUsage} off a RAW executor
|
|
323
|
+
* result's `usage` field, keeping only finite numbers — the same normalization
|
|
324
|
+
* `runAgent` applies before it delivers `'@agent.usage'`. Returns `undefined`
|
|
325
|
+
* when the result reports no usage at all. Works for our `{ output, usage }`
|
|
326
|
+
* envelope, for a raw Vercel AI SDK result (its `LanguageModelUsage` carries
|
|
327
|
+
* the same flat field names), and for any custom executor that follows the
|
|
328
|
+
* shape.
|
|
321
329
|
*
|
|
322
|
-
*
|
|
330
|
+
* The seam for the step-loop path, where the host holds the raw result itself:
|
|
331
|
+
*
|
|
332
|
+
* ```ts
|
|
333
|
+
* const { output, raw } = await executeAgentRequest(effect, executors);
|
|
334
|
+
* const usage = getCallUsage(raw);
|
|
335
|
+
* if (usage) append({ type: AGENT_USAGE_EVENT_TYPE, usage }); // journal + transition, like any event
|
|
336
|
+
* append(effect.toDoneEvent(output));
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
339
|
+
* See "Token usage on this path" in docs/steps.md for the full loop.
|
|
323
340
|
*/
|
|
324
|
-
function
|
|
341
|
+
function getCallUsage(raw) {
|
|
325
342
|
const usage = raw?.usage;
|
|
326
343
|
if (!usage || typeof usage !== "object") return;
|
|
327
344
|
let out;
|
|
@@ -344,13 +361,14 @@ const agentTextInputSchema = { "~standard": {
|
|
|
344
361
|
return { value: request };
|
|
345
362
|
}
|
|
346
363
|
} };
|
|
347
|
-
const
|
|
364
|
+
const passthroughSchema = { "~standard": {
|
|
348
365
|
version: 1,
|
|
349
366
|
vendor: "statelyai-agent",
|
|
350
367
|
validate(value) {
|
|
351
368
|
return { value };
|
|
352
369
|
}
|
|
353
370
|
} };
|
|
371
|
+
const unknownOutputSchema = passthroughSchema;
|
|
354
372
|
const stringOutputSchema = { "~standard": {
|
|
355
373
|
version: 1,
|
|
356
374
|
vendor: "statelyai-agent",
|
|
@@ -358,13 +376,7 @@ const stringOutputSchema = { "~standard": {
|
|
|
358
376
|
return typeof value === "string" ? { value } : { issues: [{ message: "Expected string output" }] };
|
|
359
377
|
}
|
|
360
378
|
} };
|
|
361
|
-
const noInputSchema =
|
|
362
|
-
version: 1,
|
|
363
|
-
vendor: "statelyai-agent",
|
|
364
|
-
validate(value) {
|
|
365
|
-
return { value };
|
|
366
|
-
}
|
|
367
|
-
} };
|
|
379
|
+
const noInputSchema = passthroughSchema;
|
|
368
380
|
function createBuiltinTextActor(src, mode, outputSchema) {
|
|
369
381
|
const logic = createAsyncLogic({ run: async () => {
|
|
370
382
|
throw new Error(`'${src}' has no host execution. Provide an implementation with machine.provide({ actors: { '${src}': ... } }) or execute the returned agent request with executeAgentRequest(...).`);
|
|
@@ -384,7 +396,7 @@ function createBuiltinTextActor(src, mode, outputSchema) {
|
|
|
384
396
|
return validateSchemaSync(outputSchema, output);
|
|
385
397
|
},
|
|
386
398
|
withExecutor(execute) {
|
|
387
|
-
return
|
|
399
|
+
return createTextLogic({
|
|
388
400
|
mode,
|
|
389
401
|
schemas: {
|
|
390
402
|
input: agentTextInputSchema,
|
|
@@ -405,7 +417,7 @@ function createBuiltinTextActor(src, mode, outputSchema) {
|
|
|
405
417
|
seed: ({ input }) => input.seed,
|
|
406
418
|
stopSequences: ({ input }) => input.stopSequences,
|
|
407
419
|
metadata: ({ input }) => input.metadata
|
|
408
|
-
}, execute)
|
|
420
|
+
}, execute);
|
|
409
421
|
}
|
|
410
422
|
});
|
|
411
423
|
}
|
|
@@ -552,7 +564,7 @@ function isTextLogic(value) {
|
|
|
552
564
|
* as `'text'`.
|
|
553
565
|
*/
|
|
554
566
|
function getAgentOutputMode(schema) {
|
|
555
|
-
const jsonSchema =
|
|
567
|
+
const jsonSchema = getJsonSchemaSync(schema);
|
|
556
568
|
if (!jsonSchema) return "text";
|
|
557
569
|
if (jsonSchema.type === "object" || jsonSchema.type === "array") return "structured";
|
|
558
570
|
if (jsonSchema.type === void 0 && ("anyOf" in jsonSchema || "oneOf" in jsonSchema || "allOf" in jsonSchema)) return "structured";
|
|
@@ -616,10 +628,6 @@ function parseStructuredEnvelope(request, value) {
|
|
|
616
628
|
if (!request.outputSchema) throw new Error("parseStructuredEnvelope: the request declares no outputSchema.");
|
|
617
629
|
return validateSchemaSync(buildEnvelopeSchema(request.outputSchema, { reasoning: request.reasoning }), value);
|
|
618
630
|
}
|
|
619
|
-
function getStandardSchemaJson(schema) {
|
|
620
|
-
const jsonSchema = (schema?.["~standard"])?.jsonSchema?.input?.();
|
|
621
|
-
return jsonSchema && !(jsonSchema instanceof Promise) ? jsonSchema : void 0;
|
|
622
|
-
}
|
|
623
631
|
/**
|
|
624
632
|
* Merges request-declared and call-site `tools`, dispatches to the
|
|
625
633
|
* `mode`-appropriate executor (`generateText`/`streamText`), and normalizes
|
|
@@ -1000,4 +1008,4 @@ async function resolveDecision(request, executor, options = {}) {
|
|
|
1000
1008
|
throw new AgentDecisionExhaustedError(attempts);
|
|
1001
1009
|
}
|
|
1002
1010
|
//#endregion
|
|
1003
|
-
export { isUnboundPlaceholder as A,
|
|
1011
|
+
export { isUnboundPlaceholder as A, getMachineStructuralHash as B, parseStructuredEnvelope as C, getMachineStaticTransitionTargets as D, executorBoundLogics as E, djb2Hex as F, toolMessage as G, isStandardSchema as H, findNonSerializableContextPaths as I, userMessage as K, getAgentMessages as L, machineSuspensionPredicates as M, missingActor as N, getMachineSuspensionPredicate as O, assistantMessage as P, getJsonSchema as R, parseOutput as S, agentExecutionOptions as T, persistSnapshot as U, getStateMeta as V, systemMessage as W, getAgentOutputMode as _, resolveDecision as a, normalizeGeneratorResult as b, AGENT_USAGE_TOKEN_FIELDS as c, USER_INPUT_ACTOR as d, bindRequestExecutor as f, executeAgentTextRequest as g, createTextLogic as h, renderDecisionAttempts as i, machineStaticTransitionTargets as j, getRegisteredAgentExecutionOptions as k, DECIDE_ACTOR as l, builtinTextActors as m, createDecideActor as n, getAcceptedEvents as o, buildEnvelopeSchema as p, validateSchemaSync as q, isDecisionLogic as r, parseAgentEvent as s, AgentDecisionExhaustedError as t, INTERPRET_SOURCE as u, getCallUsage as v, userInputActor as w, parseModelRef as x, isTextLogic as y, getJsonSchemaSync as z };
|
|
@@ -1,146 +1,12 @@
|
|
|
1
1
|
import { t as AgentError } from "./errors-CeSXQx0v.mjs";
|
|
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 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 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
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
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,4 +274,146 @@ async function assertEventLogStoreConformance(create) {
|
|
|
408
274
|
}
|
|
409
275
|
}
|
|
410
276
|
//#endregion
|
|
411
|
-
|
|
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 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 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
|
|
419
|
+
export { assertJsonSerializable as a, assertAgentLogEntry as i, AgentEventLogConflictError as n, createInMemoryEventLogStore as o, NonSerializableAgentEventError as r, assertEventLogStoreConformance as s, AGENT_EVENT_SCHEMA_VERSION as t };
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { t as AgentError } from "./errors-C9rxnWbX.mjs";
|
|
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,
|
|
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 };
|