@statelyai/agent 2.0.0-alpha.30 → 2.0.0-alpha.31
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/CHANGELOG.md +1733 -0
- package/dist/ai-sdk.cjs +8 -8
- package/dist/ai-sdk.d.cts +1 -1
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +3 -3
- package/dist/{decision-BHkvuImD.mjs → decision-DqO018Tp.mjs} +22 -9
- package/dist/{decision-CIb7ddIv.cjs → decision-Iys2hzg3.cjs} +30 -17
- package/dist/{event-log-BZRfBRd7.cjs → event-log-Bdww2l1D.cjs} +103 -24
- package/dist/{event-log-DJCMHek_.mjs → event-log-DE430ZCa.mjs} +86 -25
- package/dist/{event-log-store-DZR4IIWe.cjs → event-log-store-BWMLi6oh.cjs} +1 -1
- package/dist/{event-log-store-DsP6GCRh.mjs → event-log-store-CCWdTPEP.mjs} +1 -1
- package/dist/{event-log-store-CIIJohjj.d.mts → event-log-store-DTf_OzB-.d.cts} +1 -1
- package/dist/{event-log-store-CLAC9q2Y.d.cts → event-log-store-RziIobdW.d.mts} +1 -1
- package/dist/index.cjs +129 -21
- package/dist/index.d.cts +58 -11
- package/dist/index.d.mts +58 -11
- package/dist/index.mjs +126 -19
- package/dist/log.cjs +2 -2
- package/dist/log.d.cts +1 -1
- package/dist/log.d.mts +1 -1
- package/dist/log.mjs +2 -2
- package/dist/machines.cjs +1 -1
- package/dist/machines.mjs +1 -1
- package/dist/{model-source-BaHwJ1wK.mjs → model-source-CXsSZPq0.mjs} +1 -2
- package/dist/{model-source-BCKg4qJ1.cjs → model-source-DQ7KgJaT.cjs} +4 -5
- package/dist/openai.cjs +2 -2
- package/dist/openai.d.cts +1 -1
- package/dist/openai.d.mts +1 -1
- package/dist/openai.mjs +2 -2
- package/dist/otel.d.cts +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/{run-agent-CTlMc3Jb.d.cts → run-agent-B5opVUxx.d.cts} +17 -6
- package/dist/{run-agent-CAVt5R-r.d.mts → run-agent-D4MwS5GY.d.mts} +17 -6
- package/dist/{run-agent-BpHqkaZw.mjs → run-agent-DWZ1uyBJ.mjs} +89 -35
- package/dist/{run-agent-ctLCvNgL.cjs → run-agent-tmk58M0x.cjs} +89 -35
- package/dist/{setup-agent-7rV_cujV.mjs → setup-agent-BaffhCcM.mjs} +38 -3
- package/dist/{setup-agent-CGELn1qZ.d.mts → setup-agent-CPyg2ic7.d.mts} +11 -3
- package/dist/{setup-agent-DoUk7EdC.cjs → setup-agent-D0L8Anl_.cjs} +38 -3
- package/dist/{setup-agent-CLPCkXsu.d.cts → setup-agent-yFFVXf5s.d.cts} +11 -3
- package/dist/tanstack-ai.cjs +3 -3
- package/dist/tanstack-ai.d.cts +1 -1
- package/dist/tanstack-ai.d.mts +1 -1
- package/dist/tanstack-ai.mjs +3 -3
- package/dist/testing.cjs +73 -29
- package/dist/testing.d.cts +47 -10
- package/dist/testing.d.mts +47 -10
- package/dist/testing.mjs +65 -22
- package/dist/{text-logic-BRYOPWvY.d.mts → text-logic-BwdrDpO9.d.mts} +4 -0
- package/dist/{text-logic-DmciuVUQ.d.cts → text-logic-j9hShB7d.d.cts} +4 -0
- package/dist/{usage-BkM3z02Y.d.mts → usage-BYqv7VBw.d.cts} +1 -1
- package/dist/{usage-Cm_ovz9V.d.cts → usage-Bl4nK8D-.d.mts} +1 -1
- package/dist/validate.cjs +3 -3
- package/dist/validate.d.cts +2 -2
- package/dist/validate.d.mts +2 -2
- package/dist/validate.mjs +3 -3
- package/dist/{verify-COFWyprJ.mjs → verify-BH5e0XLK.mjs} +55 -5
- package/dist/{verify-Dzwd4Mvk.d.cts → verify-CPKDPMwY.d.cts} +14 -6
- package/dist/{verify-CVlsTZ-V.cjs → verify-CS_xxvVU.cjs} +57 -7
- package/dist/{verify-Cn86rT8l.d.mts → verify-tkymWz6X.d.mts} +14 -6
- package/package.json +34 -4
- package/readme.md +70 -40
- package/skills/add-evals/SKILL.md +23 -8
- package/skills/add-traces/SKILL.md +23 -11
- package/skills/generate-machine/SKILL.md +2 -2
- package/skills/graph-engineering/SKILL.md +1 -1
- package/skills/improve-machine/SKILL.md +7 -6
- package/skills/loop-to-machine/SKILL.md +34 -7
- package/skills/loop-to-machine/policy.md +14 -18
package/dist/ai-sdk.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_event_log = require("./event-log-
|
|
3
|
-
const require_decision = require("./decision-
|
|
4
|
-
const require_model_source = require("./model-source-
|
|
2
|
+
const require_event_log = require("./event-log-Bdww2l1D.cjs");
|
|
3
|
+
const require_decision = require("./decision-Iys2hzg3.cjs");
|
|
4
|
+
const require_model_source = require("./model-source-DQ7KgJaT.cjs");
|
|
5
5
|
let ai = require("ai");
|
|
6
6
|
//#region src/ai-sdk/mappers.ts
|
|
7
7
|
/**
|
|
@@ -209,7 +209,7 @@ function toAiSdkOptionTool(options) {
|
|
|
209
209
|
*/
|
|
210
210
|
function fromAiSdkOptionCall(toolCall, options, ids) {
|
|
211
211
|
if (toolCall.toolName !== OPTION_TOOL_NAME) return unofferedOption(`tool '${toolCall.toolName}'`, ids);
|
|
212
|
-
const id =
|
|
212
|
+
const id = require_event_log.isRecord(toolCall.input) ? toolCall.input.option : void 0;
|
|
213
213
|
const option = typeof id === "string" ? options[ids.indexOf(id)] : void 0;
|
|
214
214
|
return option ? option.event : unofferedOption(`option ${JSON.stringify(id)}`, ids);
|
|
215
215
|
}
|
|
@@ -246,7 +246,7 @@ function maxStepsSetting(request) {
|
|
|
246
246
|
return typeof maxSteps === "number" ? { stopWhen: (0, ai.stepCountIs)(maxSteps) } : {};
|
|
247
247
|
}
|
|
248
248
|
function isDecisionModel(model) {
|
|
249
|
-
return
|
|
249
|
+
return require_event_log.isRecord(model) && (typeof model.doDecide === "function" || typeof model.doEvaluate === "function");
|
|
250
250
|
}
|
|
251
251
|
/**
|
|
252
252
|
* Splits a portable `"provider/model-id"` model ref (the convention JSON
|
|
@@ -498,16 +498,16 @@ function decisionResult(event, usage = {}, confidence) {
|
|
|
498
498
|
};
|
|
499
499
|
}
|
|
500
500
|
function unofferedChoice(error, ids) {
|
|
501
|
-
if (!ai.InvalidResponseDataError.isInstance(error) || !
|
|
501
|
+
if (!ai.InvalidResponseDataError.isInstance(error) || !require_event_log.isRecord(error.data)) return void 0;
|
|
502
502
|
const answer = error.data[DECISION_QUESTION_ID];
|
|
503
|
-
const choice =
|
|
503
|
+
const choice = require_event_log.isRecord(answer) ? answer.choice : void 0;
|
|
504
504
|
return typeof choice === "string" && !ids.includes(choice) ? choice : void 0;
|
|
505
505
|
}
|
|
506
506
|
function toDecisionState(value) {
|
|
507
507
|
if (typeof value === "string") return value;
|
|
508
508
|
try {
|
|
509
509
|
const json = JSON.parse(JSON.stringify(value ?? {}));
|
|
510
|
-
return
|
|
510
|
+
return require_event_log.isRecord(json) ? json : { value: json };
|
|
511
511
|
} catch {
|
|
512
512
|
return String(value);
|
|
513
513
|
}
|
package/dist/ai-sdk.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { s as AgentTools, u as ChosenEvent } from "./types-Dp5_Ru4R.cjs";
|
|
2
|
-
import { N as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-
|
|
2
|
+
import { N as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-j9hShB7d.cjs";
|
|
3
3
|
import { Experimental_DecisionModel, FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, ToolSet, TypedToolCall, TypedToolResult, generateText } from "ai";
|
|
4
4
|
import { AnyStateMachine } from "xstate";
|
|
5
5
|
//#region src/ai-sdk/mappers.d.ts
|
package/dist/ai-sdk.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { s as AgentTools, u as ChosenEvent } from "./types-Dp5_Ru4R.mjs";
|
|
2
|
-
import { N as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-
|
|
2
|
+
import { N as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-BwdrDpO9.mjs";
|
|
3
3
|
import { AnyStateMachine } from "xstate";
|
|
4
4
|
import { Experimental_DecisionModel, FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, ToolSet, TypedToolCall, TypedToolResult, generateText } from "ai";
|
|
5
5
|
//#region src/ai-sdk/mappers.d.ts
|
package/dist/ai-sdk.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { R as providerOutputSchema,
|
|
2
|
-
import { c as renderDecisionAttempts,
|
|
3
|
-
import { t as resolveModelSource } from "./model-source-
|
|
1
|
+
import { R as providerOutputSchema, dt as AgentTruncatedError, j as getAgentOutputMode, lt as isRecord, tt as isStandardSchema } from "./event-log-DE430ZCa.mjs";
|
|
2
|
+
import { c as renderDecisionAttempts, o as decisionOptionIds } from "./decision-DqO018Tp.mjs";
|
|
3
|
+
import { t as resolveModelSource } from "./model-source-CXsSZPq0.mjs";
|
|
4
4
|
import { InvalidResponseDataError, NoObjectGeneratedError, Output, experimental_decide, generateText, jsonSchema, stepCountIs, streamText, tool } from "ai";
|
|
5
5
|
//#region src/ai-sdk/mappers.ts
|
|
6
6
|
/**
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import { H as getAgentExecutionOptions, T as DECIDE_ACTOR, V as executorBoundLogics, at as userMessage,
|
|
1
|
+
import { H as getAgentExecutionOptions, T as DECIDE_ACTOR, V as executorBoundLogics, at as userMessage, lt as isRecord, ot as validateSchemaSync, u as canonicalEventJson, ut as AgentError, z as resolveTextLogicValue } from "./event-log-DE430ZCa.mjs";
|
|
2
2
|
import { createAsyncLogic, getNextTransitions } from "xstate";
|
|
3
|
-
//#region src/internal/is-record.ts
|
|
4
|
-
/** True for a plain object-like value (arrays excluded). @internal */
|
|
5
|
-
function isRecord(value) {
|
|
6
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
3
|
//#region src/events.ts
|
|
10
4
|
/**
|
|
11
5
|
* Thrown by {@link parseAgentEvent} (and {@link eventFromInteraction}) when a
|
|
@@ -135,14 +129,18 @@ function parseAgentEvent(source, payload, options = {}) {
|
|
|
135
129
|
* ({@link RESERVED_AGENT_EVENT_PREFIX}) event types are always excluded, before
|
|
136
130
|
* any `allowedEvents` matching — a machine that handles `'@agent.usage'` still
|
|
137
131
|
* never offers it to a model.
|
|
132
|
+
*
|
|
133
|
+
* Pass `actor: "agent"` for the list a model may choose from: it also drops an
|
|
134
|
+
* event the state handles through a transition tagged `meta: { actor: "human" }`.
|
|
138
135
|
*/
|
|
139
136
|
function getAcceptedEvents(snapshot, options = {}) {
|
|
140
137
|
const eventTypes = options.eventTypes;
|
|
138
|
+
const humanEventTypes = options.actor === "agent" ? getHumanEventTypes(snapshot) : /* @__PURE__ */ new Set();
|
|
141
139
|
const seen = /* @__PURE__ */ new Set();
|
|
142
140
|
const usedToolNames = /* @__PURE__ */ new Set();
|
|
143
141
|
return getNextTransitions(snapshot).flatMap((transitionDefinition) => {
|
|
144
142
|
const eventType = transitionDefinition.eventType;
|
|
145
|
-
if (!eventType || eventType === "*" || eventType.startsWith("xstate.") || isReservedAgentEvent(eventType) || eventTypes && !eventTypes.some((pattern) => matchesEventPattern(eventType, pattern)) || seen.has(eventType)) return [];
|
|
143
|
+
if (!eventType || eventType === "*" || eventType.startsWith("xstate.") || isReservedAgentEvent(eventType) || humanEventTypes.has(eventType) || eventTypes && !eventTypes.some((pattern) => matchesEventPattern(eventType, pattern)) || seen.has(eventType)) return [];
|
|
146
144
|
seen.add(eventType);
|
|
147
145
|
const toolName = disambiguateEventToolName(sanitizeEventToolName(eventType), eventType, usedToolNames);
|
|
148
146
|
const inputSchema = (options.events ?? options.schemas?.events)?.[eventType];
|
|
@@ -153,6 +151,21 @@ function getAcceptedEvents(snapshot, options = {}) {
|
|
|
153
151
|
}];
|
|
154
152
|
});
|
|
155
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* The event types a snapshot handles through a transition tagged
|
|
156
|
+
* `meta: { actor: "human" }`: a person sends them, so no model is offered them.
|
|
157
|
+
* @internal
|
|
158
|
+
*/
|
|
159
|
+
function getHumanEventTypes(snapshot) {
|
|
160
|
+
let types = humanEventTypesBySnapshot.get(snapshot);
|
|
161
|
+
if (!types) {
|
|
162
|
+
types = /* @__PURE__ */ new Set();
|
|
163
|
+
for (const transition of getNextTransitions(snapshot)) if (transition.meta?.actor === "human") types.add(transition.eventType);
|
|
164
|
+
humanEventTypesBySnapshot.set(snapshot, types);
|
|
165
|
+
}
|
|
166
|
+
return types;
|
|
167
|
+
}
|
|
168
|
+
const humanEventTypesBySnapshot = /* @__PURE__ */ new WeakMap();
|
|
156
169
|
//#endregion
|
|
157
170
|
//#region src/decision.ts
|
|
158
171
|
function optionsFromPayloads(eventTypes, payloads) {
|
|
@@ -517,4 +530,4 @@ async function resolveDecision(request, executors, options = {}) {
|
|
|
517
530
|
throw new AgentDecisionExhaustedError(attempts);
|
|
518
531
|
}
|
|
519
532
|
//#endregion
|
|
520
|
-
export { createDecisionRequest as a, renderDecisionAttempts as c, getAcceptedEvents as d,
|
|
533
|
+
export { createDecisionRequest as a, renderDecisionAttempts as c, getAcceptedEvents as d, getHumanEventTypes as f, createDecisionLogic as i, resolveDecision as l, parseAgentEvent as m, acceptedDecisionOptions as n, decisionOptionIds as o, isEventPattern as p, createDecideActor as r, isDecisionLogic as s, AgentDecisionExhaustedError as t, AgentInvalidEventPayloadError as u };
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
const require_event_log = require("./event-log-
|
|
1
|
+
const require_event_log = require("./event-log-Bdww2l1D.cjs");
|
|
2
2
|
let xstate = require("xstate");
|
|
3
|
-
//#region src/internal/is-record.ts
|
|
4
|
-
/** True for a plain object-like value (arrays excluded). @internal */
|
|
5
|
-
function isRecord(value) {
|
|
6
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
3
|
//#region src/events.ts
|
|
10
4
|
/**
|
|
11
5
|
* Thrown by {@link parseAgentEvent} (and {@link eventFromInteraction}) when a
|
|
@@ -103,7 +97,7 @@ function isEventPattern(entry) {
|
|
|
103
97
|
* ```
|
|
104
98
|
*/
|
|
105
99
|
function parseAgentEvent(source, payload, options = {}) {
|
|
106
|
-
if (!isRecord(payload) || typeof payload.type !== "string") throw new AgentInvalidEventPayloadError("(unknown)", "expected an object with a string `type`.");
|
|
100
|
+
if (!require_event_log.isRecord(payload) || typeof payload.type !== "string") throw new AgentInvalidEventPayloadError("(unknown)", "expected an object with a string `type`.");
|
|
107
101
|
const event = payload;
|
|
108
102
|
if (isReservedAgentEvent(event.type)) throw new AgentInvalidEventPayloadError(event.type, "this event type is reserved for the library and cannot be sent from outside.");
|
|
109
103
|
const machine = typeof source.provide === "function" ? source : source.machine;
|
|
@@ -135,14 +129,18 @@ function parseAgentEvent(source, payload, options = {}) {
|
|
|
135
129
|
* ({@link RESERVED_AGENT_EVENT_PREFIX}) event types are always excluded, before
|
|
136
130
|
* any `allowedEvents` matching — a machine that handles `'@agent.usage'` still
|
|
137
131
|
* never offers it to a model.
|
|
132
|
+
*
|
|
133
|
+
* Pass `actor: "agent"` for the list a model may choose from: it also drops an
|
|
134
|
+
* event the state handles through a transition tagged `meta: { actor: "human" }`.
|
|
138
135
|
*/
|
|
139
136
|
function getAcceptedEvents(snapshot, options = {}) {
|
|
140
137
|
const eventTypes = options.eventTypes;
|
|
138
|
+
const humanEventTypes = options.actor === "agent" ? getHumanEventTypes(snapshot) : /* @__PURE__ */ new Set();
|
|
141
139
|
const seen = /* @__PURE__ */ new Set();
|
|
142
140
|
const usedToolNames = /* @__PURE__ */ new Set();
|
|
143
141
|
return (0, xstate.getNextTransitions)(snapshot).flatMap((transitionDefinition) => {
|
|
144
142
|
const eventType = transitionDefinition.eventType;
|
|
145
|
-
if (!eventType || eventType === "*" || eventType.startsWith("xstate.") || isReservedAgentEvent(eventType) || eventTypes && !eventTypes.some((pattern) => matchesEventPattern(eventType, pattern)) || seen.has(eventType)) return [];
|
|
143
|
+
if (!eventType || eventType === "*" || eventType.startsWith("xstate.") || isReservedAgentEvent(eventType) || humanEventTypes.has(eventType) || eventTypes && !eventTypes.some((pattern) => matchesEventPattern(eventType, pattern)) || seen.has(eventType)) return [];
|
|
146
144
|
seen.add(eventType);
|
|
147
145
|
const toolName = disambiguateEventToolName(sanitizeEventToolName(eventType), eventType, usedToolNames);
|
|
148
146
|
const inputSchema = (options.events ?? options.schemas?.events)?.[eventType];
|
|
@@ -153,6 +151,21 @@ function getAcceptedEvents(snapshot, options = {}) {
|
|
|
153
151
|
}];
|
|
154
152
|
});
|
|
155
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* The event types a snapshot handles through a transition tagged
|
|
156
|
+
* `meta: { actor: "human" }`: a person sends them, so no model is offered them.
|
|
157
|
+
* @internal
|
|
158
|
+
*/
|
|
159
|
+
function getHumanEventTypes(snapshot) {
|
|
160
|
+
let types = humanEventTypesBySnapshot.get(snapshot);
|
|
161
|
+
if (!types) {
|
|
162
|
+
types = /* @__PURE__ */ new Set();
|
|
163
|
+
for (const transition of (0, xstate.getNextTransitions)(snapshot)) if (transition.meta?.actor === "human") types.add(transition.eventType);
|
|
164
|
+
humanEventTypesBySnapshot.set(snapshot, types);
|
|
165
|
+
}
|
|
166
|
+
return types;
|
|
167
|
+
}
|
|
168
|
+
const humanEventTypesBySnapshot = /* @__PURE__ */ new WeakMap();
|
|
156
169
|
//#endregion
|
|
157
170
|
//#region src/decision.ts
|
|
158
171
|
function optionsFromPayloads(eventTypes, payloads) {
|
|
@@ -172,8 +185,8 @@ function optionsFromPayloads(eventTypes, payloads) {
|
|
|
172
185
|
*/
|
|
173
186
|
function acceptedDecisionOptions(request, can) {
|
|
174
187
|
if (!request.options) return void 0;
|
|
175
|
-
const payloads = isRecord(request.input) ? request.input.payloads : void 0;
|
|
176
|
-
return (isRecord(payloads) ? optionsFromPayloads(request.events.map((event) => event.type), payloads) : request.options).filter((option) => {
|
|
188
|
+
const payloads = require_event_log.isRecord(request.input) ? request.input.payloads : void 0;
|
|
189
|
+
return (require_event_log.isRecord(payloads) ? optionsFromPayloads(request.events.map((event) => event.type), payloads) : request.options).filter((option) => {
|
|
177
190
|
try {
|
|
178
191
|
return can(option.event);
|
|
179
192
|
} catch {
|
|
@@ -565,22 +578,22 @@ Object.defineProperty(exports, "getAcceptedEvents", {
|
|
|
565
578
|
return getAcceptedEvents;
|
|
566
579
|
}
|
|
567
580
|
});
|
|
568
|
-
Object.defineProperty(exports, "
|
|
581
|
+
Object.defineProperty(exports, "getHumanEventTypes", {
|
|
569
582
|
enumerable: true,
|
|
570
583
|
get: function() {
|
|
571
|
-
return
|
|
584
|
+
return getHumanEventTypes;
|
|
572
585
|
}
|
|
573
586
|
});
|
|
574
|
-
Object.defineProperty(exports, "
|
|
587
|
+
Object.defineProperty(exports, "isDecisionLogic", {
|
|
575
588
|
enumerable: true,
|
|
576
589
|
get: function() {
|
|
577
|
-
return
|
|
590
|
+
return isDecisionLogic;
|
|
578
591
|
}
|
|
579
592
|
});
|
|
580
|
-
Object.defineProperty(exports, "
|
|
593
|
+
Object.defineProperty(exports, "isEventPattern", {
|
|
581
594
|
enumerable: true,
|
|
582
595
|
get: function() {
|
|
583
|
-
return
|
|
596
|
+
return isEventPattern;
|
|
584
597
|
}
|
|
585
598
|
});
|
|
586
599
|
Object.defineProperty(exports, "parseAgentEvent", {
|
|
@@ -54,6 +54,31 @@ var AgentTruncatedError = class extends AgentError {
|
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
//#endregion
|
|
57
|
+
//#region src/internal/is-record.ts
|
|
58
|
+
/** True for a plain object-like value (arrays excluded). @internal */
|
|
59
|
+
function isRecord(value) {
|
|
60
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* True for an object whose prototype is `null` or some realm's
|
|
64
|
+
* `Object.prototype`. Comparing against this realm's `Object.prototype` alone
|
|
65
|
+
* rejects plain objects built in another realm: a jest test file's vm
|
|
66
|
+
* context, or `structuredClone`'s output inside one. @internal
|
|
67
|
+
*/
|
|
68
|
+
function isPlainObject(value) {
|
|
69
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
70
|
+
const prototype = Object.getPrototypeOf(value);
|
|
71
|
+
return prototype === null || Object.getPrototypeOf(prototype) === null;
|
|
72
|
+
}
|
|
73
|
+
/** True for an `Error` from any realm, where `instanceof Error` sees only this one. @internal */
|
|
74
|
+
function isError(value) {
|
|
75
|
+
return value instanceof Error || Object.prototype.toString.call(value) === "[object Error]";
|
|
76
|
+
}
|
|
77
|
+
/** JSON text with object keys sorted and `undefined` fields dropped, for comparing JSON-like values. @internal */
|
|
78
|
+
function canonicalJson(value) {
|
|
79
|
+
return JSON.stringify(value, (_key, item) => isPlainObject(item) ? Object.fromEntries(Object.keys(item).sort().map((key) => [key, item[key]])) : item) ?? "undefined";
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
57
82
|
//#region src/utils.ts
|
|
58
83
|
/** Returns the human-readable text carried by a message, ignoring non-text parts. */
|
|
59
84
|
function getMessageText(message) {
|
|
@@ -103,8 +128,7 @@ function findNonSerializableContextPaths(context, limit = 5) {
|
|
|
103
128
|
seen.delete(obj);
|
|
104
129
|
return;
|
|
105
130
|
}
|
|
106
|
-
|
|
107
|
-
if (proto === Object.prototype || proto === null) {
|
|
131
|
+
if (isPlainObject(value)) {
|
|
108
132
|
seen.add(obj);
|
|
109
133
|
for (const [key, item] of Object.entries(value)) walk(item, `${path}.${key}`);
|
|
110
134
|
seen.delete(obj);
|
|
@@ -456,7 +480,7 @@ function responseMessagesOf(raw) {
|
|
|
456
480
|
}
|
|
457
481
|
function dropUndefined(value) {
|
|
458
482
|
if (Array.isArray(value)) return value.map(dropUndefined);
|
|
459
|
-
if (
|
|
483
|
+
if (isPlainObject(value)) {
|
|
460
484
|
const out = {};
|
|
461
485
|
for (const [key, entry] of Object.entries(value)) if (entry !== void 0) out[key] = dropUndefined(entry);
|
|
462
486
|
return out;
|
|
@@ -932,8 +956,7 @@ function assertJsonSerializable(value, path = "entry", ancestors = /* @__PURE__
|
|
|
932
956
|
assertNoHiddenKeys(value, path, (key) => key === "length" || arrayIndexPattern.test(key));
|
|
933
957
|
return;
|
|
934
958
|
}
|
|
935
|
-
|
|
936
|
-
if (prototype !== Object.prototype && prototype !== null) throw new NonSerializableAgentEventError(path, value.constructor?.name ?? "object");
|
|
959
|
+
if (!isPlainObject(value)) throw new NonSerializableAgentEventError(path, value.constructor?.name ?? "object");
|
|
937
960
|
assertNoHiddenKeys(value, path);
|
|
938
961
|
for (const [key, child] of Object.entries(value)) assertJsonSerializable(child, `${path}.${key}`, ancestors);
|
|
939
962
|
} finally {
|
|
@@ -990,22 +1013,32 @@ function exhaustedAttemptsOf(error) {
|
|
|
990
1013
|
return Array.isArray(attempts) && isJsonSerializable(attempts) ? attempts : void 0;
|
|
991
1014
|
}
|
|
992
1015
|
/**
|
|
993
|
-
*
|
|
994
|
-
*
|
|
995
|
-
*
|
|
1016
|
+
* Marks an object {@link normalizeEventErrors} made from an `Error`, so replay
|
|
1017
|
+
* restores that object, and only that one, as an `Error`: a thrown plain
|
|
1018
|
+
* `{ name, message }` stays a plain object.
|
|
1019
|
+
*/
|
|
1020
|
+
const NORMALIZED_ERROR_KEY = "@error";
|
|
1021
|
+
/**
|
|
1022
|
+
* Replaces `Error` instances with plain `{ name, message, code?, cause?,
|
|
1023
|
+
* "@error": true }` objects so an `xstate.error.actor` payload survives the
|
|
1024
|
+
* log's JSON round-trip. `code` is kept when it is a string or a number; a
|
|
1025
|
+
* decision-exhausted error also keeps its `attempts`. Replay turns the
|
|
1026
|
+
* object back into an `Error` (see `restoreJournaledEvent`). Cycles
|
|
996
1027
|
* are preserved by identity; non-plain objects are left alone (and are then
|
|
997
1028
|
* rejected by {@link assertJsonSerializable}).
|
|
998
1029
|
*/
|
|
999
1030
|
function normalizeEventErrors(value, seen = /* @__PURE__ */ new WeakMap()) {
|
|
1000
|
-
if (value
|
|
1031
|
+
if (isError(value)) {
|
|
1001
1032
|
const normalized = {
|
|
1002
1033
|
name: value.name,
|
|
1003
|
-
message: value.message
|
|
1034
|
+
message: value.message,
|
|
1035
|
+
[NORMALIZED_ERROR_KEY]: true
|
|
1004
1036
|
};
|
|
1005
1037
|
seen.set(value, normalized);
|
|
1006
1038
|
if (value.cause !== void 0) normalized.cause = normalizeEventErrors(value.cause, seen);
|
|
1007
|
-
|
|
1008
|
-
|
|
1039
|
+
const code = value.code;
|
|
1040
|
+
if (typeof code === "string" || typeof code === "number" && Number.isFinite(code)) normalized.code = code;
|
|
1041
|
+
if (code === DECISION_EXHAUSTED_CODE) {
|
|
1009
1042
|
const attempts = exhaustedAttemptsOf(value);
|
|
1010
1043
|
if (attempts !== void 0) normalized.attempts = structuredClone(attempts);
|
|
1011
1044
|
}
|
|
@@ -1020,8 +1053,7 @@ function normalizeEventErrors(value, seen = /* @__PURE__ */ new WeakMap()) {
|
|
|
1020
1053
|
for (const item of value) result.push(normalizeEventErrors(item, seen));
|
|
1021
1054
|
return result;
|
|
1022
1055
|
}
|
|
1023
|
-
|
|
1024
|
-
if (prototype !== Object.prototype && prototype !== null) return value;
|
|
1056
|
+
if (!isPlainObject(value)) return value;
|
|
1025
1057
|
const result = {};
|
|
1026
1058
|
seen.set(value, result);
|
|
1027
1059
|
for (const [key, item] of Object.entries(value)) result[key] = normalizeEventErrors(item, seen);
|
|
@@ -1046,7 +1078,7 @@ function canonicalizeForHash(value, seen = /* @__PURE__ */ new WeakSet(), positi
|
|
|
1046
1078
|
if (typeof value === "symbol") return `[symbol:${String(value)}]`;
|
|
1047
1079
|
if (value === null || typeof value !== "object") return value;
|
|
1048
1080
|
if (value instanceof Date) return `[Date:${value.toISOString()}]`;
|
|
1049
|
-
if (value
|
|
1081
|
+
if (isError(value)) {
|
|
1050
1082
|
if (seen.has(value)) return "[circular]";
|
|
1051
1083
|
seen.add(value);
|
|
1052
1084
|
try {
|
|
@@ -1141,7 +1173,7 @@ function createReplayEntry(machine, entries, event, options = {}) {
|
|
|
1141
1173
|
recordedAt: options.recordedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1142
1174
|
machineId: machineIdOf(machine),
|
|
1143
1175
|
machineVersion,
|
|
1144
|
-
event: normalizeDoneActorEvent(normalizeEventErrors(event)),
|
|
1176
|
+
event: normalizeDoneActorEvent(pruneUndefined(normalizeEventErrors(event))),
|
|
1145
1177
|
...options.causationId !== void 0 ? { causationId: options.causationId } : {},
|
|
1146
1178
|
...options.metadata !== void 0 ? { metadata: options.metadata } : {},
|
|
1147
1179
|
...options.attempts !== void 0 && options.attempts.length > 0 ? { attempts: options.attempts } : {}
|
|
@@ -1154,15 +1186,23 @@ function createReplayEntry(machine, entries, event, options = {}) {
|
|
|
1154
1186
|
}).persistedSnapshot) };
|
|
1155
1187
|
return entry;
|
|
1156
1188
|
}
|
|
1157
|
-
function pruneUndefined(value) {
|
|
1158
|
-
if (Array.isArray(value)) return value.map(pruneUndefined);
|
|
1189
|
+
function pruneUndefined(value, ancestors = /* @__PURE__ */ new WeakSet()) {
|
|
1159
1190
|
if (value === null || typeof value !== "object") return value;
|
|
1160
|
-
if (
|
|
1191
|
+
if (ancestors.has(value)) return value;
|
|
1192
|
+
if (Array.isArray(value)) {
|
|
1193
|
+
ancestors.add(value);
|
|
1194
|
+
const result = value.map((item) => pruneUndefined(item, ancestors));
|
|
1195
|
+
ancestors.delete(value);
|
|
1196
|
+
return result;
|
|
1197
|
+
}
|
|
1198
|
+
if (!isPlainObject(value)) return value;
|
|
1199
|
+
ancestors.add(value);
|
|
1161
1200
|
const result = {};
|
|
1162
1201
|
for (const [key, child] of Object.entries(value)) {
|
|
1163
1202
|
if (child === void 0) continue;
|
|
1164
|
-
result[key] = pruneUndefined(child);
|
|
1203
|
+
result[key] = pruneUndefined(child, ancestors);
|
|
1165
1204
|
}
|
|
1205
|
+
ancestors.delete(value);
|
|
1166
1206
|
return result;
|
|
1167
1207
|
}
|
|
1168
1208
|
/**
|
|
@@ -1359,12 +1399,33 @@ function rebindActorSession(event, snapshot, sessions) {
|
|
|
1359
1399
|
sessionId
|
|
1360
1400
|
};
|
|
1361
1401
|
}
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1402
|
+
/**
|
|
1403
|
+
* The event as the machine received it live: a done event's dropped
|
|
1404
|
+
* `undefined` output restored, and an error event's normalized error turned
|
|
1405
|
+
* back into an `Error`, so `error instanceof Error` holds on replay too.
|
|
1406
|
+
*/
|
|
1407
|
+
function restoreJournaledEvent(event) {
|
|
1408
|
+
if (event.type === DONE_ACTOR_EVENT_TYPE && !Object.hasOwn(event, "output")) return {
|
|
1365
1409
|
...event,
|
|
1366
1410
|
output: void 0
|
|
1367
1411
|
};
|
|
1412
|
+
if (event.type.startsWith(ERROR_ACTOR_EVENT_TYPE)) {
|
|
1413
|
+
const error = event.error;
|
|
1414
|
+
if (isNormalizedError(error)) return {
|
|
1415
|
+
...event,
|
|
1416
|
+
error: toError(error)
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
return event;
|
|
1420
|
+
}
|
|
1421
|
+
function isNormalizedError(value) {
|
|
1422
|
+
return isPlainObject(value) && value[NORMALIZED_ERROR_KEY] === true && typeof value.name === "string" && typeof value.message === "string";
|
|
1423
|
+
}
|
|
1424
|
+
function toError(normalized) {
|
|
1425
|
+
const { name, message, cause, [NORMALIZED_ERROR_KEY]: _marker, ...rest } = normalized;
|
|
1426
|
+
const error = new Error(message, cause === void 0 ? void 0 : { cause: isNormalizedError(cause) ? toError(cause) : cause });
|
|
1427
|
+
error.name = name;
|
|
1428
|
+
return Object.assign(error, rest);
|
|
1368
1429
|
}
|
|
1369
1430
|
function verifyEntry(entry, persisted, mode) {
|
|
1370
1431
|
if (mode === false) return;
|
|
@@ -1412,7 +1473,7 @@ function foldLog(machine, entries, options = {}) {
|
|
|
1412
1473
|
verifyEntry(entries[0], persisted, options.verify);
|
|
1413
1474
|
const sessions = /* @__PURE__ */ new Map();
|
|
1414
1475
|
const apply = (entry) => {
|
|
1415
|
-
const event =
|
|
1476
|
+
const event = restoreJournaledEvent(rebindActorSession(entry.event, snapshot, sessions));
|
|
1416
1477
|
[snapshot] = (0, xstate.transition)(machine, snapshot, event);
|
|
1417
1478
|
persisted = machine.getPersistedSnapshot(snapshot);
|
|
1418
1479
|
return persisted;
|
|
@@ -1610,6 +1671,12 @@ Object.defineProperty(exports, "canonicalEventJson", {
|
|
|
1610
1671
|
return canonicalEventJson;
|
|
1611
1672
|
}
|
|
1612
1673
|
});
|
|
1674
|
+
Object.defineProperty(exports, "canonicalJson", {
|
|
1675
|
+
enumerable: true,
|
|
1676
|
+
get: function() {
|
|
1677
|
+
return canonicalJson;
|
|
1678
|
+
}
|
|
1679
|
+
});
|
|
1613
1680
|
Object.defineProperty(exports, "createReplayEntry", {
|
|
1614
1681
|
enumerable: true,
|
|
1615
1682
|
get: function() {
|
|
@@ -1742,6 +1809,18 @@ Object.defineProperty(exports, "initEntry", {
|
|
|
1742
1809
|
return initEntry;
|
|
1743
1810
|
}
|
|
1744
1811
|
});
|
|
1812
|
+
Object.defineProperty(exports, "isPlainObject", {
|
|
1813
|
+
enumerable: true,
|
|
1814
|
+
get: function() {
|
|
1815
|
+
return isPlainObject;
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
Object.defineProperty(exports, "isRecord", {
|
|
1819
|
+
enumerable: true,
|
|
1820
|
+
get: function() {
|
|
1821
|
+
return isRecord;
|
|
1822
|
+
}
|
|
1823
|
+
});
|
|
1745
1824
|
Object.defineProperty(exports, "isStandardSchema", {
|
|
1746
1825
|
enumerable: true,
|
|
1747
1826
|
get: function() {
|