@statelyai/agent 2.0.0-alpha.21 → 2.0.0-alpha.22
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 +1 -1
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +1 -1
- package/dist/{decision-BnTCsuJv.cjs → decision-1o45_ZrS.cjs} +105 -6
- package/dist/{decision-JWx6n3xR.mjs → decision-DxSTqzgZ.mjs} +100 -7
- package/dist/index.cjs +3 -2
- package/dist/index.d.cts +6 -5
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +3 -3
- package/dist/machines.cjs +1 -1
- package/dist/machines.d.cts +150 -53
- package/dist/machines.d.mts +150 -53
- package/dist/machines.mjs +1 -1
- package/dist/otel.d.cts +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/{run-agent-DBNI8ETM.d.mts → run-agent-0fpEZ1wJ.d.mts} +1 -1
- package/dist/{run-agent-Do094mGu.d.cts → run-agent-Zbkx7XP8.d.cts} +1 -1
- package/dist/{setup-agent-91FSuZbB.cjs → setup-agent-DkCTy5Eu.cjs} +75 -9
- package/dist/{setup-agent-DqqdcdNh.mjs → setup-agent-nSFYrNTP.mjs} +75 -9
- package/dist/{text-logic-Mmbgb2jy.d.cts → text-logic-BaxPrcLk.d.cts} +44 -1
- package/dist/{text-logic-BR5twXCv.d.mts → text-logic-DhfFWzu9.d.mts} +44 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { T as WithAgentInputSchema, c as AgentTools, d as ChosenEvent, h as InferInput, n as AgentMessage, v as StandardSchemaV1 } from "./types-CvWRGFxP.mjs";
|
|
2
2
|
import { t as AgentError } from "./errors-C9rxnWbX.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { N as AgentDecisionRequest, U as AgentRequestOptions, V as AgentEventDescriptor, W as AgentRequestSource, d as AgentTextRequest, f as AgentUsage, l as AgentRequestExecutors, p as AgentUserInput, t as AgentCallUsage, u as AgentRequestMode } from "./text-logic-DhfFWzu9.mjs";
|
|
4
4
|
import { i as AgentLogEntry, o as JsonValue } from "./event-log-store-hrA1vqtN.mjs";
|
|
5
5
|
import { AnyActorLogic, AnyActorRef, AnyMachineSnapshot, AnyStateMachine, AsyncActorLogic, EmittedFrom, EventFromLogic, EventObject, ExecutableActionObject, InputFrom, InspectionEvent, OutputFrom, Snapshot, SnapshotFrom, createActor } from "xstate";
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { T as WithAgentInputSchema, c as AgentTools, d as ChosenEvent, h as InferInput, n as AgentMessage, v as StandardSchemaV1 } from "./types-DSdj2tGs.cjs";
|
|
2
2
|
import { t as AgentError } from "./errors-BQRk9eiZ.cjs";
|
|
3
|
-
import {
|
|
3
|
+
import { N as AgentDecisionRequest, U as AgentRequestOptions, V as AgentEventDescriptor, W as AgentRequestSource, d as AgentTextRequest, f as AgentUsage, l as AgentRequestExecutors, p as AgentUserInput, t as AgentCallUsage, u as AgentRequestMode } from "./text-logic-BaxPrcLk.cjs";
|
|
4
4
|
import { i as AgentLogEntry, o as JsonValue } from "./event-log-store-Bz7HDBkE.cjs";
|
|
5
5
|
import { AnyActorLogic, AnyActorRef, AnyMachineSnapshot, AnyStateMachine, AsyncActorLogic, EmittedFrom, EventFromLogic, EventObject, ExecutableActionObject, InputFrom, InspectionEvent, OutputFrom, Snapshot, SnapshotFrom, createActor } from "xstate";
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_errors = require("./errors-DUBBzRLP.cjs");
|
|
2
|
-
const require_decision = require("./decision-
|
|
2
|
+
const require_decision = require("./decision-1o45_ZrS.cjs");
|
|
3
3
|
const require_event_log_store = require("./event-log-store-a_TKy1gk.cjs");
|
|
4
4
|
require("./validate.cjs");
|
|
5
5
|
let xstate = require("xstate");
|
|
@@ -37,22 +37,88 @@ const KNOWN_PART_TYPES = new Set([
|
|
|
37
37
|
"tool-call",
|
|
38
38
|
"tool-result"
|
|
39
39
|
]);
|
|
40
|
+
const USER_PART_TYPES = new Set([
|
|
41
|
+
"text",
|
|
42
|
+
"image",
|
|
43
|
+
"file"
|
|
44
|
+
]);
|
|
45
|
+
const ASSISTANT_PART_TYPES = new Set([
|
|
46
|
+
"text",
|
|
47
|
+
"file",
|
|
48
|
+
"tool-call",
|
|
49
|
+
"tool-result"
|
|
50
|
+
]);
|
|
51
|
+
const TOOL_PART_TYPES = new Set(["tool-result"]);
|
|
52
|
+
const TOOL_RESULT_CONTENT_PART_TYPES = new Set(["text", "image"]);
|
|
40
53
|
function isKnownPart(part) {
|
|
41
|
-
|
|
54
|
+
const type = part && typeof part === "object" ? part.type : void 0;
|
|
55
|
+
return typeof type === "string" && KNOWN_PART_TYPES.has(type);
|
|
42
56
|
}
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
function requireString(part, type, field) {
|
|
58
|
+
return typeof part[field] === "string" ? void 0 : `${type} part requires a string "${field}"`;
|
|
59
|
+
}
|
|
60
|
+
function isMediaData(value) {
|
|
61
|
+
return typeof value === "string" || value instanceof Uint8Array || value instanceof ArrayBuffer || value instanceof URL;
|
|
62
|
+
}
|
|
63
|
+
function requireMediaData(part, type, field) {
|
|
64
|
+
return isMediaData(part[field]) ? void 0 : `${type} part requires "${field}" to be a string, Uint8Array, ArrayBuffer, or URL`;
|
|
65
|
+
}
|
|
66
|
+
const TOOL_RESULT_OUTPUT_TYPES = new Set([
|
|
67
|
+
"text",
|
|
68
|
+
"json",
|
|
69
|
+
"error-text",
|
|
70
|
+
"error-json",
|
|
71
|
+
"content"
|
|
72
|
+
]);
|
|
73
|
+
function validateToolResultOutput(output) {
|
|
74
|
+
if (!output || typeof output !== "object" || Array.isArray(output)) return "tool-result part requires an \"output\" object";
|
|
75
|
+
const record = output;
|
|
76
|
+
const outputType = record.type;
|
|
77
|
+
if (typeof outputType !== "string" || !TOOL_RESULT_OUTPUT_TYPES.has(outputType)) return `Unknown tool-result output type: ${JSON.stringify(outputType)}`;
|
|
78
|
+
if (outputType === "text" || outputType === "error-text") {
|
|
79
|
+
if (typeof record.value !== "string") return `tool-result output of type "${outputType}" requires a string "value"`;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (outputType === "content") {
|
|
83
|
+
if (!Array.isArray(record.value)) return "tool-result output of type \"content\" requires an array \"value\"";
|
|
84
|
+
for (const contentPart of record.value) {
|
|
85
|
+
const error = validatePart(contentPart, TOOL_RESULT_CONTENT_PART_TYPES, "tool-result output content");
|
|
86
|
+
if (error) return error;
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
return record.value !== void 0 ? void 0 : `tool-result output of type "${outputType}" requires a "value"`;
|
|
91
|
+
}
|
|
92
|
+
function validatePart(part, allowedTypes, location) {
|
|
93
|
+
if (!isKnownPart(part)) {
|
|
46
94
|
const type = part && typeof part === "object" ? part.type : void 0;
|
|
47
95
|
return `Unknown message part type: ${JSON.stringify(type)}`;
|
|
48
96
|
}
|
|
97
|
+
if (!allowedTypes.has(part.type)) return `${location} does not allow "${part.type}" parts`;
|
|
98
|
+
const record = part;
|
|
99
|
+
switch (record.type) {
|
|
100
|
+
case "text": return requireString(record, "text", "text");
|
|
101
|
+
case "image": return requireMediaData(record, "image", "image");
|
|
102
|
+
case "file": return requireMediaData(record, "file", "data") ?? requireString(record, "file", "mediaType");
|
|
103
|
+
case "tool-call": return requireString(record, "tool-call", "toolCallId") ?? requireString(record, "tool-call", "toolName") ?? ("input" in record ? void 0 : "tool-call part requires an \"input\" value");
|
|
104
|
+
case "tool-result": return requireString(record, "tool-result", "toolCallId") ?? requireString(record, "tool-result", "toolName") ?? validateToolResultOutput(record.output);
|
|
105
|
+
default: return;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function validatePartsArray(content, allowedTypes, location) {
|
|
109
|
+
if (!Array.isArray(content)) return "Expected content to be a string or an array of parts";
|
|
110
|
+
for (const part of content) {
|
|
111
|
+
const error = validatePart(part, allowedTypes, location);
|
|
112
|
+
if (error) return error;
|
|
113
|
+
}
|
|
49
114
|
}
|
|
50
115
|
/**
|
|
51
116
|
* A {@link StandardSchemaV1} validating an `AgentMessage[]` context field —
|
|
52
117
|
* checks that every message has a known `role` (`system`/`user`/`assistant`/
|
|
53
118
|
* `tool`) and that `content` is either a string (where the role allows it) or
|
|
54
|
-
* an array of parts
|
|
55
|
-
*
|
|
119
|
+
* an array of role-appropriate parts whose required fields and media payloads
|
|
120
|
+
* have the right runtime types (extra fields are allowed). Use it directly as
|
|
121
|
+
* a context schema's `messages` field when authoring with `createAgentSchemas`.
|
|
56
122
|
*/
|
|
57
123
|
const messagesSchema = { "~standard": {
|
|
58
124
|
version: 1,
|
|
@@ -69,12 +135,12 @@ const messagesSchema = { "~standard": {
|
|
|
69
135
|
continue;
|
|
70
136
|
}
|
|
71
137
|
if (role === "tool") {
|
|
72
|
-
const error = validatePartsArray(content
|
|
138
|
+
const error = validatePartsArray(content, TOOL_PART_TYPES, "tool message content");
|
|
73
139
|
if (error) return { issues: [{ message: error }] };
|
|
74
140
|
continue;
|
|
75
141
|
}
|
|
76
142
|
if (typeof content === "string") continue;
|
|
77
|
-
const error = validatePartsArray(content);
|
|
143
|
+
const error = validatePartsArray(content, role === "user" ? USER_PART_TYPES : ASSISTANT_PART_TYPES, `${role} message content`);
|
|
78
144
|
if (error) return { issues: [{ message: error }] };
|
|
79
145
|
}
|
|
80
146
|
return { value };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as AgentError } from "./errors-CeSXQx0v.mjs";
|
|
2
|
-
import { D as
|
|
2
|
+
import { D as userInputActor, F as machineStaticTransitionTargets, I as missingActor, K as resolveMachineVersion, M as getRegisteredAgentExecutionOptions, O as agentExecutionOptions, P as machineIdlePredicates, R as djb2Hex, S as isTextLogic, X as validateSchemaSync, _ as builtinTextActors, i as isDecisionLogic, m as USER_INPUT_ACTOR, n as createDecideActor, s as getAcceptedEvents, u as DECIDE_ACTOR, v as createTextLogic, y as executeAgentTextRequest } from "./decision-DxSTqzgZ.mjs";
|
|
3
3
|
import { a as assertJsonSerializable, i as assertAgentLogEntry } from "./event-log-store-DmIDosD6.mjs";
|
|
4
4
|
import { createMachineFromConfig, initialTransition, setup, transition } from "xstate";
|
|
5
5
|
//#region src/messages.ts
|
|
@@ -36,22 +36,88 @@ const KNOWN_PART_TYPES = new Set([
|
|
|
36
36
|
"tool-call",
|
|
37
37
|
"tool-result"
|
|
38
38
|
]);
|
|
39
|
+
const USER_PART_TYPES = new Set([
|
|
40
|
+
"text",
|
|
41
|
+
"image",
|
|
42
|
+
"file"
|
|
43
|
+
]);
|
|
44
|
+
const ASSISTANT_PART_TYPES = new Set([
|
|
45
|
+
"text",
|
|
46
|
+
"file",
|
|
47
|
+
"tool-call",
|
|
48
|
+
"tool-result"
|
|
49
|
+
]);
|
|
50
|
+
const TOOL_PART_TYPES = new Set(["tool-result"]);
|
|
51
|
+
const TOOL_RESULT_CONTENT_PART_TYPES = new Set(["text", "image"]);
|
|
39
52
|
function isKnownPart(part) {
|
|
40
|
-
|
|
53
|
+
const type = part && typeof part === "object" ? part.type : void 0;
|
|
54
|
+
return typeof type === "string" && KNOWN_PART_TYPES.has(type);
|
|
41
55
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
function requireString(part, type, field) {
|
|
57
|
+
return typeof part[field] === "string" ? void 0 : `${type} part requires a string "${field}"`;
|
|
58
|
+
}
|
|
59
|
+
function isMediaData(value) {
|
|
60
|
+
return typeof value === "string" || value instanceof Uint8Array || value instanceof ArrayBuffer || value instanceof URL;
|
|
61
|
+
}
|
|
62
|
+
function requireMediaData(part, type, field) {
|
|
63
|
+
return isMediaData(part[field]) ? void 0 : `${type} part requires "${field}" to be a string, Uint8Array, ArrayBuffer, or URL`;
|
|
64
|
+
}
|
|
65
|
+
const TOOL_RESULT_OUTPUT_TYPES = new Set([
|
|
66
|
+
"text",
|
|
67
|
+
"json",
|
|
68
|
+
"error-text",
|
|
69
|
+
"error-json",
|
|
70
|
+
"content"
|
|
71
|
+
]);
|
|
72
|
+
function validateToolResultOutput(output) {
|
|
73
|
+
if (!output || typeof output !== "object" || Array.isArray(output)) return "tool-result part requires an \"output\" object";
|
|
74
|
+
const record = output;
|
|
75
|
+
const outputType = record.type;
|
|
76
|
+
if (typeof outputType !== "string" || !TOOL_RESULT_OUTPUT_TYPES.has(outputType)) return `Unknown tool-result output type: ${JSON.stringify(outputType)}`;
|
|
77
|
+
if (outputType === "text" || outputType === "error-text") {
|
|
78
|
+
if (typeof record.value !== "string") return `tool-result output of type "${outputType}" requires a string "value"`;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (outputType === "content") {
|
|
82
|
+
if (!Array.isArray(record.value)) return "tool-result output of type \"content\" requires an array \"value\"";
|
|
83
|
+
for (const contentPart of record.value) {
|
|
84
|
+
const error = validatePart(contentPart, TOOL_RESULT_CONTENT_PART_TYPES, "tool-result output content");
|
|
85
|
+
if (error) return error;
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
return record.value !== void 0 ? void 0 : `tool-result output of type "${outputType}" requires a "value"`;
|
|
90
|
+
}
|
|
91
|
+
function validatePart(part, allowedTypes, location) {
|
|
92
|
+
if (!isKnownPart(part)) {
|
|
45
93
|
const type = part && typeof part === "object" ? part.type : void 0;
|
|
46
94
|
return `Unknown message part type: ${JSON.stringify(type)}`;
|
|
47
95
|
}
|
|
96
|
+
if (!allowedTypes.has(part.type)) return `${location} does not allow "${part.type}" parts`;
|
|
97
|
+
const record = part;
|
|
98
|
+
switch (record.type) {
|
|
99
|
+
case "text": return requireString(record, "text", "text");
|
|
100
|
+
case "image": return requireMediaData(record, "image", "image");
|
|
101
|
+
case "file": return requireMediaData(record, "file", "data") ?? requireString(record, "file", "mediaType");
|
|
102
|
+
case "tool-call": return requireString(record, "tool-call", "toolCallId") ?? requireString(record, "tool-call", "toolName") ?? ("input" in record ? void 0 : "tool-call part requires an \"input\" value");
|
|
103
|
+
case "tool-result": return requireString(record, "tool-result", "toolCallId") ?? requireString(record, "tool-result", "toolName") ?? validateToolResultOutput(record.output);
|
|
104
|
+
default: return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function validatePartsArray(content, allowedTypes, location) {
|
|
108
|
+
if (!Array.isArray(content)) return "Expected content to be a string or an array of parts";
|
|
109
|
+
for (const part of content) {
|
|
110
|
+
const error = validatePart(part, allowedTypes, location);
|
|
111
|
+
if (error) return error;
|
|
112
|
+
}
|
|
48
113
|
}
|
|
49
114
|
/**
|
|
50
115
|
* A {@link StandardSchemaV1} validating an `AgentMessage[]` context field —
|
|
51
116
|
* checks that every message has a known `role` (`system`/`user`/`assistant`/
|
|
52
117
|
* `tool`) and that `content` is either a string (where the role allows it) or
|
|
53
|
-
* an array of parts
|
|
54
|
-
*
|
|
118
|
+
* an array of role-appropriate parts whose required fields and media payloads
|
|
119
|
+
* have the right runtime types (extra fields are allowed). Use it directly as
|
|
120
|
+
* a context schema's `messages` field when authoring with `createAgentSchemas`.
|
|
55
121
|
*/
|
|
56
122
|
const messagesSchema = { "~standard": {
|
|
57
123
|
version: 1,
|
|
@@ -68,12 +134,12 @@ const messagesSchema = { "~standard": {
|
|
|
68
134
|
continue;
|
|
69
135
|
}
|
|
70
136
|
if (role === "tool") {
|
|
71
|
-
const error = validatePartsArray(content
|
|
137
|
+
const error = validatePartsArray(content, TOOL_PART_TYPES, "tool message content");
|
|
72
138
|
if (error) return { issues: [{ message: error }] };
|
|
73
139
|
continue;
|
|
74
140
|
}
|
|
75
141
|
if (typeof content === "string") continue;
|
|
76
|
-
const error = validatePartsArray(content);
|
|
142
|
+
const error = validatePartsArray(content, role === "user" ? USER_PART_TYPES : ASSISTANT_PART_TYPES, `${role} message content`);
|
|
77
143
|
if (error) return { issues: [{ message: error }] };
|
|
78
144
|
}
|
|
79
145
|
return { value };
|
|
@@ -124,6 +124,49 @@ interface DecisionLogicConfig<TInputSchema extends StandardSchemaV1 = StandardSc
|
|
|
124
124
|
stopSequences?: ResolveTextLogicValue<string[] | undefined, InferOutput<TInputSchema>>;
|
|
125
125
|
metadata?: ResolveTextLogicValue<TMetadata | undefined, InferOutput<TInputSchema>>;
|
|
126
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Actor logic for a decision: an async effect that resolves to exactly one
|
|
129
|
+
* currently-legal {@link ChosenEvent} (never a plain value). Under `runAgent`
|
|
130
|
+
* the chosen event is delivered to the invoking actor automatically — the
|
|
131
|
+
* transition it triggers usually exits the invoking state and ends the invoke.
|
|
132
|
+
* Built by {@link createDecisionLogic}. Register it under `actors:` to reuse/export/
|
|
133
|
+
* test it standalone; for a state-local, zero-config decision, use the
|
|
134
|
+
* `agent.decide` builtin invoke instead.
|
|
135
|
+
*/
|
|
136
|
+
interface DecisionLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TMetadata extends Record<string, unknown> = Record<string, unknown>> extends AsyncActorLogic<ChosenEvent, InferOutput<TInputSchema>> {
|
|
137
|
+
readonly kind: "statelyai.decisionLogic";
|
|
138
|
+
readonly maxRetries: number;
|
|
139
|
+
request(input: InferOutput<TInputSchema>): AgentDecisionRequest;
|
|
140
|
+
withExecutor(execute: AgentDecisionExecutor): DecisionLogic<TInputSchema, TMetadata>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Creates reusable, standalone {@link DecisionLogic}: an actor that, when
|
|
144
|
+
* run, resolves to exactly one currently-legal {@link ChosenEvent} by
|
|
145
|
+
* calling the host `decide` executor (passed here as `execute`, or supplied
|
|
146
|
+
* later via {@link DecisionLogic.withExecutor}, `machine.provide(...)`, or
|
|
147
|
+
* `runAgent`'s `decide` option). Register the result under `actors:` and
|
|
148
|
+
* invoke it by name; for a one-off, state-local decision, prefer the
|
|
149
|
+
* `agent.decide` builtin invoke instead — it needs no separate declaration
|
|
150
|
+
* and types `allowedEvents` against the machine's own event schemas.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* import { createDecisionLogic } from '@statelyai/agent';
|
|
155
|
+
* import { z } from 'zod';
|
|
156
|
+
*
|
|
157
|
+
* export const chooseMove = createDecisionLogic({
|
|
158
|
+
* schemas: { input: z.object({ playerHp: z.number(), enemyHp: z.number() }) },
|
|
159
|
+
* model: 'openai/gpt-5.4-mini',
|
|
160
|
+
* system: 'You are playing a turn-based game. Choose exactly one legal move.',
|
|
161
|
+
* prompt: ({ input }) => `Player HP: ${input.playerHp}\nEnemy HP: ${input.enemyHp}`,
|
|
162
|
+
* allowedEvents: ({ input }) =>
|
|
163
|
+
* input.playerHp <= 6
|
|
164
|
+
* ? ['ATTACK', 'DEFEND', 'HEAL', 'FLEE']
|
|
165
|
+
* : ['ATTACK', 'DEFEND', 'FLEE'],
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
declare function createDecisionLogic<TInputSchema extends StandardSchemaV1, TEvent extends string = string, TMetadata extends Record<string, unknown> = Record<string, unknown>, TModel extends string = string>(config: DecisionLogicConfig<TInputSchema, TEvent, TMetadata, TModel>, execute?: AgentDecisionExecutor): DecisionLogic<TInputSchema, TMetadata>;
|
|
127
170
|
/**
|
|
128
171
|
* A decision request: resolves to exactly one currently-legal event. See
|
|
129
172
|
* `resolveDecision`.
|
|
@@ -744,4 +787,4 @@ declare function buildEnvelopeSchema(inner: StandardSchemaV1, options?: {
|
|
|
744
787
|
*/
|
|
745
788
|
declare function parseStructuredEnvelope(request: Pick<AgentTextRequest, "outputSchema" | "includeReasoning">, value: unknown): StructuredOutputEnvelope;
|
|
746
789
|
//#endregion
|
|
747
|
-
export { AgentDecisionExecutor as A,
|
|
790
|
+
export { AgentDecisionExecutor as A, resolveDecision as B, buildEnvelopeSchema as C, parseModelRef as D, getCallUsage as E, DecisionLogic as F, AgentSchemas as G, AgentEventToolNameResolver as H, DecisionLogicConfig as I, getAcceptedEvents as K, ResolveDecisionOptions as L, AgentDecisionInput as M, AgentDecisionRequest as N, parseOutput as O, DecisionAttempt as P, createDecisionLogic as R, bindRequestExecutor as S, getAgentOutputMode as T, AgentRequestOptions as U, AgentEventDescriptor as V, AgentRequestSource as W, StructuredOutputEnvelope as _, AgentOutputMode as a, TextLogicExecuteArgs as b, AgentRequestExecutorResult as c, AgentTextRequest as d, AgentUsage as f, BuiltinAgentActors as g, AiSdkShapedTextResult as h, AgentModelRef as i, AgentDecisionExhaustedError as j, parseStructuredEnvelope as k, AgentRequestExecutors as l, AiSdkShapedStreamResult as m, AgentExecutorTextRequest as n, AgentRequestExecutor as o, AgentUserInput as p, parseAgentEvent as q, AgentModelMap as r, AgentRequestExecutorInfo as s, AgentCallUsage as t, AgentRequestMode as u, TextLogic as v, createTextLogic as w, TextLogicExecutor as x, TextLogicConfig as y, renderDecisionAttempts as z };
|
|
@@ -124,6 +124,49 @@ interface DecisionLogicConfig<TInputSchema extends StandardSchemaV1 = StandardSc
|
|
|
124
124
|
stopSequences?: ResolveTextLogicValue<string[] | undefined, InferOutput<TInputSchema>>;
|
|
125
125
|
metadata?: ResolveTextLogicValue<TMetadata | undefined, InferOutput<TInputSchema>>;
|
|
126
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Actor logic for a decision: an async effect that resolves to exactly one
|
|
129
|
+
* currently-legal {@link ChosenEvent} (never a plain value). Under `runAgent`
|
|
130
|
+
* the chosen event is delivered to the invoking actor automatically — the
|
|
131
|
+
* transition it triggers usually exits the invoking state and ends the invoke.
|
|
132
|
+
* Built by {@link createDecisionLogic}. Register it under `actors:` to reuse/export/
|
|
133
|
+
* test it standalone; for a state-local, zero-config decision, use the
|
|
134
|
+
* `agent.decide` builtin invoke instead.
|
|
135
|
+
*/
|
|
136
|
+
interface DecisionLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TMetadata extends Record<string, unknown> = Record<string, unknown>> extends AsyncActorLogic<ChosenEvent, InferOutput<TInputSchema>> {
|
|
137
|
+
readonly kind: "statelyai.decisionLogic";
|
|
138
|
+
readonly maxRetries: number;
|
|
139
|
+
request(input: InferOutput<TInputSchema>): AgentDecisionRequest;
|
|
140
|
+
withExecutor(execute: AgentDecisionExecutor): DecisionLogic<TInputSchema, TMetadata>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Creates reusable, standalone {@link DecisionLogic}: an actor that, when
|
|
144
|
+
* run, resolves to exactly one currently-legal {@link ChosenEvent} by
|
|
145
|
+
* calling the host `decide` executor (passed here as `execute`, or supplied
|
|
146
|
+
* later via {@link DecisionLogic.withExecutor}, `machine.provide(...)`, or
|
|
147
|
+
* `runAgent`'s `decide` option). Register the result under `actors:` and
|
|
148
|
+
* invoke it by name; for a one-off, state-local decision, prefer the
|
|
149
|
+
* `agent.decide` builtin invoke instead — it needs no separate declaration
|
|
150
|
+
* and types `allowedEvents` against the machine's own event schemas.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* import { createDecisionLogic } from '@statelyai/agent';
|
|
155
|
+
* import { z } from 'zod';
|
|
156
|
+
*
|
|
157
|
+
* export const chooseMove = createDecisionLogic({
|
|
158
|
+
* schemas: { input: z.object({ playerHp: z.number(), enemyHp: z.number() }) },
|
|
159
|
+
* model: 'openai/gpt-5.4-mini',
|
|
160
|
+
* system: 'You are playing a turn-based game. Choose exactly one legal move.',
|
|
161
|
+
* prompt: ({ input }) => `Player HP: ${input.playerHp}\nEnemy HP: ${input.enemyHp}`,
|
|
162
|
+
* allowedEvents: ({ input }) =>
|
|
163
|
+
* input.playerHp <= 6
|
|
164
|
+
* ? ['ATTACK', 'DEFEND', 'HEAL', 'FLEE']
|
|
165
|
+
* : ['ATTACK', 'DEFEND', 'FLEE'],
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
declare function createDecisionLogic<TInputSchema extends StandardSchemaV1, TEvent extends string = string, TMetadata extends Record<string, unknown> = Record<string, unknown>, TModel extends string = string>(config: DecisionLogicConfig<TInputSchema, TEvent, TMetadata, TModel>, execute?: AgentDecisionExecutor): DecisionLogic<TInputSchema, TMetadata>;
|
|
127
170
|
/**
|
|
128
171
|
* A decision request: resolves to exactly one currently-legal event. See
|
|
129
172
|
* `resolveDecision`.
|
|
@@ -744,4 +787,4 @@ declare function buildEnvelopeSchema(inner: StandardSchemaV1, options?: {
|
|
|
744
787
|
*/
|
|
745
788
|
declare function parseStructuredEnvelope(request: Pick<AgentTextRequest, "outputSchema" | "includeReasoning">, value: unknown): StructuredOutputEnvelope;
|
|
746
789
|
//#endregion
|
|
747
|
-
export { AgentDecisionExecutor as A,
|
|
790
|
+
export { AgentDecisionExecutor as A, resolveDecision as B, buildEnvelopeSchema as C, parseModelRef as D, getCallUsage as E, DecisionLogic as F, AgentSchemas as G, AgentEventToolNameResolver as H, DecisionLogicConfig as I, getAcceptedEvents as K, ResolveDecisionOptions as L, AgentDecisionInput as M, AgentDecisionRequest as N, parseOutput as O, DecisionAttempt as P, createDecisionLogic as R, bindRequestExecutor as S, getAgentOutputMode as T, AgentRequestOptions as U, AgentEventDescriptor as V, AgentRequestSource as W, StructuredOutputEnvelope as _, AgentOutputMode as a, TextLogicExecuteArgs as b, AgentRequestExecutorResult as c, AgentTextRequest as d, AgentUsage as f, BuiltinAgentActors as g, AiSdkShapedTextResult as h, AgentModelRef as i, AgentDecisionExhaustedError as j, parseStructuredEnvelope as k, AgentRequestExecutors as l, AiSdkShapedStreamResult as m, AgentExecutorTextRequest as n, AgentRequestExecutor as o, AgentUserInput as p, parseAgentEvent as q, AgentModelMap as r, AgentRequestExecutorInfo as s, AgentCallUsage as t, AgentRequestMode as u, TextLogic as v, createTextLogic as w, TextLogicExecutor as x, TextLogicConfig as y, renderDecisionAttempts as z };
|
package/package.json
CHANGED