@statelyai/agent 0.0.5 → 0.0.6

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @statelyai/agent
2
2
 
3
+ ## 0.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#16](https://github.com/statelyai/agent/pull/16) [`3ba5fb2`](https://github.com/statelyai/agent/commit/3ba5fb2392b51dee71f2585ed662b4ee9ecd6c41) Thanks [@davidkpiano](https://github.com/davidkpiano)! - Update to XState 5.8.0
8
+
3
9
  ## 0.0.5
4
10
 
5
11
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -14,36 +14,38 @@ type EventSchemas = {
14
14
  };
15
15
  };
16
16
  };
17
- interface ContextSchema {
18
- [key: string]: JSONSchema7;
19
- }
17
+ type ContextSchema = JSONSchema7 & {
18
+ type: 'object';
19
+ };
20
20
  type ConvertToJSONSchemas<T> = {
21
21
  [K in keyof T]: {
22
22
  properties: {
23
23
  type: {
24
24
  const: K;
25
25
  };
26
- };
26
+ } & Prop<T[K], 'properties'>;
27
27
  type: 'object';
28
- required: Array<keyof Prop<T[K], 'properties'> | 'type'>;
28
+ required: Array<(keyof Prop<T[K], 'properties'> & string) | 'type'>;
29
29
  additionalProperties: false;
30
- } & T[K];
30
+ };
31
31
  } & {};
32
- type ConvertContextToJSONSchema<T extends ContextSchema> = {
33
- type: 'object';
34
- properties: T;
35
- readonly required: Array<keyof T & string>;
36
- additionalProperties: false;
37
- };
38
32
 
39
- declare function createSchemas<TContextSchema extends ContextSchema, TEventSchemas extends EventSchemas>({ context, events, }: {
33
+ declare function createSchemas<const TContextSchema extends ContextSchema, const TEventSchemas extends EventSchemas>({ context, events, }: {
34
+ /**
35
+ * The JSON schema for the context object.
36
+ *
37
+ * Must be of `{ type: 'object' }`.
38
+ */
40
39
  context: TContextSchema;
40
+ /**
41
+ * An object mapping event types to each event object's JSON Schema.
42
+ */
41
43
  events: TEventSchemas;
42
44
  }): {
43
- context: ConvertContextToJSONSchema<TContextSchema>;
45
+ context: TContextSchema;
44
46
  events: ConvertToJSONSchemas<TEventSchemas>;
45
47
  types: {
46
- context: FromSchema<ConvertContextToJSONSchema<TContextSchema>>;
48
+ context: FromSchema<TContextSchema>;
47
49
  events: FromSchema<Values<ConvertToJSONSchemas<TEventSchemas>>>;
48
50
  };
49
51
  };
@@ -52,29 +54,26 @@ declare function createAgent<T extends AnyStateMachine>(...args: Parameters<type
52
54
 
53
55
  interface StatelyAgentAdapter {
54
56
  model: string;
55
- fromEvent: <TInput>(inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming, options?: {
56
- /**
57
- * Immediately execute sending the event to the parent actor.
58
- * @default true
59
- */
60
- execute?: boolean;
61
- }) => PromiseActorLogic<AnyEventObject[] | undefined, TInput>;
62
57
  /**
63
- * Creates promise actor logic that resolves with a chat completion.
58
+ * Creates actor logic that chooses an event from all of the
59
+ * possible next events of the parent state machine
60
+ * and sends it to the parent actor.
61
+ */
62
+ fromEvent: <TInput>(inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming) => PromiseActorLogic<AnyEventObject[] | undefined, TInput>;
63
+ /**
64
+ * Creates actor logic that resolves with a chat completion.
64
65
  */
65
66
  fromChat: <TInput>(inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming) => PromiseActorLogic<OpenAI.Chat.Completions.ChatCompletion, TInput>;
66
67
  /**
67
- * Creates observable actor logic that emits a chat completion stream.
68
+ * Creates actor logic that emits a chat completion stream.
68
69
  */
69
70
  fromChatStream: <TInput>(inputFn: (input: TInput) => string | ChatCompletionCreateParamsStreaming) => ObservableActorLogic<OpenAI.Chat.Completions.ChatCompletionChunk, TInput>;
71
+ /**
72
+ * Creates actor logic that chooses a tool from the provided
73
+ * tools and runs that tool.
74
+ */
70
75
  fromTool: <TInput>(inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming, tools: {
71
76
  [key: string]: Tool<any, any>;
72
- }, options?: {
73
- /**
74
- * Immediately execute sending the event to the parent actor.
75
- * @default true
76
- */
77
- execute?: boolean;
78
77
  }) => PromiseActorLogic<{
79
78
  result: any;
80
79
  tool: string;
package/dist/index.js CHANGED
@@ -57,12 +57,7 @@ function createSchemas({
57
57
  events
58
58
  }) {
59
59
  return {
60
- context: {
61
- type: "object",
62
- properties: context,
63
- additionalProperties: false,
64
- required: Object.keys(context)
65
- },
60
+ context,
66
61
  events: createEventSchemas(events),
67
62
  types: {}
68
63
  };
@@ -134,7 +129,7 @@ function fromChatStream(openai, agentSettings, inputFn) {
134
129
  }
135
130
  );
136
131
  }
137
- function fromEvent(openai, agentSettings, inputFn, options) {
132
+ function fromEvent(openai, agentSettings, inputFn) {
138
133
  return (0, import_xstate2.fromPromise)(
139
134
  async ({ input, self, system }) => {
140
135
  const parentSnapshot = self._parent?.getSnapshot();
@@ -177,26 +172,22 @@ function fromEvent(openai, agentSettings, inputFn, options) {
177
172
  tools
178
173
  });
179
174
  const toolCalls = completion.choices[0]?.message.tool_calls;
180
- if (toolCalls) {
175
+ if (toolCalls?.length) {
181
176
  const events = toolCalls.map((tc) => {
182
177
  return {
183
178
  type: functionNameMapping[tc.function.name],
184
179
  ...JSON.parse(tc.function.arguments)
185
180
  };
186
181
  });
187
- if (options?.execute) {
188
- events.forEach((event) => {
189
- system._relay(self, self._parent, event);
190
- });
191
- }
182
+ const event = events[0];
183
+ system._relay(self, self._parent, event);
192
184
  }
193
185
  return void 0;
194
186
  }
195
187
  );
196
188
  }
197
189
  function fromTool(openai, agentSettings, tools, inputFn) {
198
- return (0, import_xstate2.fromPromise)(async ({ input, self, system }) => {
199
- const functionNameMapping = {};
190
+ return (0, import_xstate2.fromPromise)(async ({ input }) => {
200
191
  const resolvedTools = Object.entries(tools).map(([key, value]) => {
201
192
  return {
202
193
  type: "function",
@@ -241,10 +232,7 @@ function fromTool(openai, agentSettings, tools, inputFn) {
241
232
  function createOpenAIAdapter(openai, settings) {
242
233
  const agentSettings = {
243
234
  model: settings.model,
244
- fromEvent: (input) => (
245
- // @ts-ignore infinitely deep
246
- fromEvent(openai, agentSettings, input, { execute: true })
247
- ),
235
+ fromEvent: (input) => fromEvent(openai, agentSettings, input),
248
236
  fromChat: (input) => fromChatCompletion(openai, agentSettings, input),
249
237
  fromChatStream: (input) => fromChatStream(openai, agentSettings, input),
250
238
  fromTool: (input, tools) => fromTool(openai, agentSettings, tools, input)
package/examples/joke.ts CHANGED
@@ -9,15 +9,19 @@ const openai = new OpenAI({
9
9
 
10
10
  const schemas = createSchemas({
11
11
  context: {
12
- topic: { type: 'string' },
13
- jokes: {
14
- type: 'array',
15
- items: {
16
- type: 'string',
12
+ type: 'object',
13
+ properties: {
14
+ topic: { type: 'string' },
15
+ jokes: {
16
+ type: 'array',
17
+ items: {
18
+ type: 'string',
19
+ },
17
20
  },
21
+ desire: { type: ['string', 'null'] },
22
+ lastRating: { type: ['string', 'null'] },
18
23
  },
19
- desire: { type: ['string', 'null'] as const },
20
- lastRating: { type: ['string', 'null'] as const },
24
+ required: ['topic', 'jokes', 'desire', 'lastRating'],
21
25
  },
22
26
  events: {
23
27
  askForTopic: {
@@ -0,0 +1,128 @@
1
+ import OpenAI from 'openai';
2
+ import { createAgent, createOpenAIAdapter, createSchemas } from '../src';
3
+ import { assign, setup } from 'xstate';
4
+ const openai = new OpenAI({
5
+ apiKey: process.env.OPENAI_API_KEY,
6
+ });
7
+
8
+ const adapter = createOpenAIAdapter(openai, {
9
+ model: 'gpt-3.5-turbo-1106',
10
+ });
11
+
12
+ const guessLogic = adapter.fromEvent(
13
+ ({
14
+ previousGuesses,
15
+ lastResult,
16
+ }: {
17
+ previousGuesses: number[];
18
+ lastResult: string;
19
+ }) => `
20
+ Guess the number between 1 and 10. The previous guesses were ${
21
+ previousGuesses.length ? previousGuesses.join(', ') : 'not made yet'
22
+ } and the last result was ${lastResult}.
23
+ `
24
+ );
25
+
26
+ const schemas = createSchemas({
27
+ context: {
28
+ type: 'object',
29
+ properties: {
30
+ lastGuess: {
31
+ type: ['number', 'null'],
32
+ description: 'The last guess',
33
+ },
34
+ previousGuesses: {
35
+ type: 'array',
36
+ items: {
37
+ type: 'number',
38
+ },
39
+ description: 'The previous guesses',
40
+ },
41
+ answer: {
42
+ type: 'number',
43
+ description: 'The answer',
44
+ },
45
+ },
46
+ },
47
+ events: {
48
+ guess: {
49
+ properties: {
50
+ number: {
51
+ // integer
52
+ type: 'number',
53
+ minimum: 1,
54
+ maximum: 10,
55
+ },
56
+ },
57
+ required: ['number'],
58
+ },
59
+ },
60
+ });
61
+
62
+ const machine = setup({
63
+ types: {
64
+ context: {} as {
65
+ previousGuesses: number[];
66
+ answer: number;
67
+ },
68
+ input: {} as { answer: number },
69
+ events: schemas.types.events,
70
+ },
71
+ schemas,
72
+ actors: {
73
+ guessLogic,
74
+ },
75
+ }).createMachine({
76
+ context: ({ input }) => ({
77
+ answer: input.answer,
78
+ previousGuesses: [],
79
+ }),
80
+ initial: 'guessing',
81
+ states: {
82
+ guessing: {
83
+ always: {
84
+ guard: ({ context }) =>
85
+ context.answer === context.previousGuesses.at(-1),
86
+ target: 'winner',
87
+ },
88
+ invoke: {
89
+ src: 'guessLogic',
90
+ input: ({ context }) => ({
91
+ previousGuesses: context.previousGuesses,
92
+ lastResult:
93
+ context.previousGuesses.length === 0
94
+ ? 'not given yet'
95
+ : context.previousGuesses.at(-1)! - context.answer > 0
96
+ ? 'too high'
97
+ : 'too low',
98
+ }),
99
+ },
100
+ on: {
101
+ guess: {
102
+ actions: assign({
103
+ previousGuesses: ({ context, event }) => [
104
+ ...context.previousGuesses,
105
+ event.number,
106
+ ],
107
+ }),
108
+ target: 'guessing',
109
+ reenter: true,
110
+ },
111
+ },
112
+ },
113
+ winner: {
114
+ type: 'final',
115
+ },
116
+ },
117
+ });
118
+
119
+ const agent = createAgent(machine, {
120
+ input: { answer: 4 },
121
+ inspect: (ev) => {
122
+ if (ev.type === '@xstate.event') {
123
+ console.log(ev.event);
124
+ }
125
+ },
126
+ });
127
+
128
+ agent.start();
@@ -10,36 +10,40 @@ type Player = 'x' | 'o';
10
10
 
11
11
  const schemas = createSchemas({
12
12
  context: {
13
- board: {
14
- type: 'array',
15
- items: {
16
- type: ['null', 'string'],
17
- enum: [null, 'x', 'o'],
13
+ type: 'object',
14
+ properties: {
15
+ board: {
16
+ type: 'array',
17
+ items: {
18
+ type: ['null', 'string'],
19
+ enum: [null, 'x', 'o'],
20
+ },
21
+ minItems: 9,
22
+ maxItems: 9,
23
+ description: 'The board of the tic-tac-toe game',
18
24
  },
19
- minItems: 9,
20
- maxItems: 9,
21
- description: 'The board of the tic-tac-toe game',
22
- },
23
- moves: {
24
- type: 'number',
25
- description: 'The number of moves that have been played',
26
- },
27
- player: {
28
- type: 'string',
29
- enum: ['x', 'o'],
30
- description: 'The player whose turn it is',
31
- },
32
- gameReport: {
33
- type: 'string',
34
- description: 'The game report',
35
- },
36
- events: {
37
- type: 'array',
38
- items: {
25
+ moves: {
26
+ type: 'number',
27
+ description: 'The number of moves that have been played',
28
+ },
29
+ player: {
39
30
  type: 'string',
31
+ enum: ['x', 'o'],
32
+ description: 'The player whose turn it is',
33
+ },
34
+ gameReport: {
35
+ type: 'string',
36
+ description: 'The game report',
37
+ },
38
+ events: {
39
+ type: 'array',
40
+ items: {
41
+ type: 'string',
42
+ },
40
43
  },
41
44
  },
42
- } as const,
45
+ required: ['board', 'moves', 'player', 'gameReport', 'events'],
46
+ },
43
47
  events: {
44
48
  'x.play': {
45
49
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statelyai/agent",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -24,13 +24,13 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "xstate": "^5.6.0"
27
+ "xstate": "^5.8.0"
28
28
  },
29
29
  "packageManager": "pnpm@8.11.0",
30
30
  "scripts": {
31
31
  "build": "tsup src/index.ts --format cjs,esm --dts",
32
32
  "lint": "tsc",
33
- "test": "vitest run",
33
+ "test": "vitest",
34
34
  "example": "ts-node examples/helpers/runner.ts",
35
35
  "changeset": "changeset",
36
36
  "release": "changeset publish",
package/readme.md CHANGED
@@ -1,13 +1,14 @@
1
1
  # Stately Agent (alpha)
2
2
 
3
- 🚧 Documentation in progress! Please see [the examples directory](https://github.com/statelyai/agent/tree/main/examples) for working examples.
3
+ - Read [the documentation](https://stately.ai/docs/agents)
4
+ - See [the examples directory](https://github.com/statelyai/agent/tree/main/examples) for working examples.
4
5
 
5
6
  ## Installation
6
7
 
7
8
  Install `openai`, and `@statelyai/agent`:
8
9
 
9
10
  ```bash
10
- npm install openai @statelyai/agent
11
+ pnpm install openai @statelyai/agent
11
12
  ```
12
13
 
13
14
  ## Usage
@@ -35,7 +36,7 @@ OPENAI_API_KEY="your-openai-api-key"
35
36
  Then, install the dependencies (`npm install`) and run the examples:
36
37
 
37
38
  ```bash
38
- npm run example joke
39
+ pnpm run example joke
39
40
  # or:
40
- # npm run example ticTacToe
41
+ # pnpm run example ticTacToe
41
42
  ```
@@ -1,9 +1,7 @@
1
1
  import type OpenAI from 'openai';
2
2
  import {
3
3
  AnyEventObject,
4
- ObservableActorLogic,
5
4
  Observer,
6
- PromiseActorLogic,
7
5
  fromObservable,
8
6
  fromPromise,
9
7
  isMachineSnapshot,
@@ -11,10 +9,7 @@ import {
11
9
  } from 'xstate';
12
10
  import { getAllTransitions } from '../utils';
13
11
  import { ChatCompletionCreateParamsNonStreaming } from 'openai/resources';
14
- import {
15
- ChatCompletionCreateParamsBase,
16
- ChatCompletionCreateParamsStreaming,
17
- } from 'openai/resources/chat/completions';
12
+ import { ChatCompletionCreateParamsBase } from 'openai/resources/chat/completions';
18
13
  import { StatelyAgentAdapter, Tool } from '../types';
19
14
 
20
15
  /**
@@ -26,7 +21,7 @@ import { StatelyAgentAdapter, Tool } from '../types';
26
21
  */
27
22
  export function fromChatCompletion<TInput>(
28
23
  openai: OpenAI,
29
- agentSettings: OpenAIAdapterOutput<any>,
24
+ agentSettings: StatelyAgentAdapter,
30
25
  inputFn: (
31
26
  input: TInput
32
27
  ) => string | OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming
@@ -61,7 +56,7 @@ export function fromChatCompletion<TInput>(
61
56
  */
62
57
  export function fromChatStream<TInput>(
63
58
  openai: OpenAI,
64
- agentSettings: OpenAIAdapterOutput<any>,
59
+ agentSettings: StatelyAgentAdapter,
65
60
  inputFn: (
66
61
  input: TInput
67
62
  ) => string | OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming
@@ -120,17 +115,10 @@ export function fromChatStream<TInput>(
120
115
  */
121
116
  export function fromEvent<TInput>(
122
117
  openai: OpenAI,
123
- agentSettings: OpenAIAdapterOutput<any>,
118
+ agentSettings: StatelyAgentAdapter,
124
119
  inputFn: (
125
120
  input: TInput
126
- ) => string | OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming,
127
- options?: {
128
- /**
129
- * Immediately execute sending the event to the parent actor.
130
- * @default false
131
- */
132
- execute?: boolean;
133
- }
121
+ ) => string | OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming
134
122
  ) {
135
123
  return fromPromise<AnyEventObject[] | undefined, TInput>(
136
124
  async ({ input, self, system }) => {
@@ -186,7 +174,7 @@ export function fromEvent<TInput>(
186
174
 
187
175
  const toolCalls = completion.choices[0]?.message.tool_calls;
188
176
 
189
- if (toolCalls) {
177
+ if (toolCalls?.length) {
190
178
  const events = toolCalls.map((tc) => {
191
179
  return {
192
180
  type: functionNameMapping[tc.function.name],
@@ -194,12 +182,10 @@ export function fromEvent<TInput>(
194
182
  };
195
183
  });
196
184
 
197
- if (options?.execute) {
198
- events.forEach((event) => {
199
- // @ts-ignore
200
- system._relay(self, self._parent, event);
201
- });
202
- }
185
+ const event = events[0]!;
186
+
187
+ // @ts-ignore
188
+ system._relay(self, self._parent, event);
203
189
  }
204
190
 
205
191
  return undefined;
@@ -243,8 +229,7 @@ export function fromTool<TInput>(
243
229
  }
244
230
  | undefined,
245
231
  TInput
246
- >(async ({ input, self, system }) => {
247
- const functionNameMapping: Record<string, string> = {};
232
+ >(async ({ input }) => {
248
233
  const resolvedTools = Object.entries(tools).map(([key, value]) => {
249
234
  return {
250
235
  type: 'function',
@@ -296,42 +281,6 @@ export function fromTool<TInput>(
296
281
  });
297
282
  }
298
283
 
299
- interface OpenAIAdapterOutput<
300
- T extends {
301
- model: ChatCompletionCreateParamsBase['model'];
302
- }
303
- > {
304
- model: T['model'];
305
- /**
306
- * Determines which event to send to the parent state machine actor based on the prompt.
307
- */
308
- fromEvent: <TInput>(
309
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming,
310
- options?: {
311
- /**
312
- * Immediately execute sending the event to the parent actor.
313
- * @default true
314
- */
315
- execute?: boolean;
316
- }
317
- ) => PromiseActorLogic<AnyEventObject[] | undefined, TInput>;
318
- /**
319
- * Creates promise actor logic that resolves with a chat completion.
320
- */
321
- fromChat: <TInput>(
322
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
323
- ) => PromiseActorLogic<OpenAI.Chat.Completions.ChatCompletion, TInput>;
324
- /**
325
- * Creates observable actor logic that emits a chat completion stream.
326
- */
327
- fromChatStream: <TInput>(
328
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsStreaming
329
- ) => ObservableActorLogic<
330
- OpenAI.Chat.Completions.ChatCompletionChunk,
331
- TInput
332
- >;
333
- }
334
-
335
284
  export function createOpenAIAdapter<
336
285
  T extends {
337
286
  model: ChatCompletionCreateParamsBase['model'];
@@ -339,9 +288,7 @@ export function createOpenAIAdapter<
339
288
  >(openai: OpenAI, settings: T): StatelyAgentAdapter {
340
289
  const agentSettings: StatelyAgentAdapter = {
341
290
  model: settings.model,
342
- fromEvent: (input) =>
343
- // @ts-ignore infinitely deep
344
- fromEvent(openai, agentSettings, input, { execute: true }) as any,
291
+ fromEvent: (input) => fromEvent(openai, agentSettings, input),
345
292
  fromChat: (input) => fromChatCompletion(openai, agentSettings, input),
346
293
  fromChatStream: (input) => fromChatStream(openai, agentSettings, input),
347
294
  fromTool: (input, tools) => fromTool(openai, agentSettings, tools, input),
package/src/schemas.ts CHANGED
@@ -2,36 +2,38 @@ import { Values } from 'xstate';
2
2
  import {
3
3
  ContextSchema,
4
4
  EventSchemas,
5
- ConvertContextToJSONSchema,
6
5
  ConvertToJSONSchemas,
7
6
  createEventSchemas,
8
7
  } from './utils';
9
8
  import { FromSchema } from 'json-schema-to-ts';
10
9
 
11
10
  export function createSchemas<
12
- TContextSchema extends ContextSchema,
13
- TEventSchemas extends EventSchemas
11
+ const TContextSchema extends ContextSchema,
12
+ const TEventSchemas extends EventSchemas
14
13
  >({
15
14
  context,
16
15
  events,
17
16
  }: {
17
+ /**
18
+ * The JSON schema for the context object.
19
+ *
20
+ * Must be of `{ type: 'object' }`.
21
+ */
18
22
  context: TContextSchema;
23
+ /**
24
+ * An object mapping event types to each event object's JSON Schema.
25
+ */
19
26
  events: TEventSchemas;
20
27
  }): {
21
- context: ConvertContextToJSONSchema<TContextSchema>;
28
+ context: TContextSchema;
22
29
  events: ConvertToJSONSchemas<TEventSchemas>;
23
30
  types: {
24
- context: FromSchema<ConvertContextToJSONSchema<TContextSchema>>;
31
+ context: FromSchema<TContextSchema>;
25
32
  events: FromSchema<Values<ConvertToJSONSchemas<TEventSchemas>>>;
26
33
  };
27
34
  } {
28
35
  return {
29
- context: {
30
- type: 'object',
31
- properties: context,
32
- additionalProperties: false,
33
- required: Object.keys(context),
34
- },
36
+ context,
35
37
  events: createEventSchemas(events),
36
38
  types: {} as any,
37
39
  };
package/src/types.ts CHANGED
@@ -4,8 +4,6 @@ import {
4
4
  ChatCompletionCreateParamsStreaming,
5
5
  } from 'openai/resources';
6
6
  import {
7
- AnyActorLogic,
8
- AnyActorRef,
9
7
  AnyEventObject,
10
8
  ObservableActorLogic,
11
9
  PromiseActorLogic,
@@ -13,24 +11,22 @@ import {
13
11
 
14
12
  export interface StatelyAgentAdapter {
15
13
  model: string;
14
+ /**
15
+ * Creates actor logic that chooses an event from all of the
16
+ * possible next events of the parent state machine
17
+ * and sends it to the parent actor.
18
+ */
16
19
  fromEvent: <TInput>(
17
- inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming,
18
- options?: {
19
- /**
20
- * Immediately execute sending the event to the parent actor.
21
- * @default true
22
- */
23
- execute?: boolean;
24
- }
20
+ inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
25
21
  ) => PromiseActorLogic<AnyEventObject[] | undefined, TInput>;
26
22
  /**
27
- * Creates promise actor logic that resolves with a chat completion.
23
+ * Creates actor logic that resolves with a chat completion.
28
24
  */
29
25
  fromChat: <TInput>(
30
26
  inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
31
27
  ) => PromiseActorLogic<OpenAI.Chat.Completions.ChatCompletion, TInput>;
32
28
  /**
33
- * Creates observable actor logic that emits a chat completion stream.
29
+ * Creates actor logic that emits a chat completion stream.
34
30
  */
35
31
  fromChatStream: <TInput>(
36
32
  inputFn: (input: TInput) => string | ChatCompletionCreateParamsStreaming
@@ -38,18 +34,14 @@ export interface StatelyAgentAdapter {
38
34
  OpenAI.Chat.Completions.ChatCompletionChunk,
39
35
  TInput
40
36
  >;
41
-
37
+ /**
38
+ * Creates actor logic that chooses a tool from the provided
39
+ * tools and runs that tool.
40
+ */
42
41
  fromTool: <TInput>(
43
42
  inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming,
44
43
  tools: {
45
44
  [key: string]: Tool<any, any>;
46
- },
47
- options?: {
48
- /**
49
- * Immediately execute sending the event to the parent actor.
50
- * @default true
51
- */
52
- execute?: boolean;
53
45
  }
54
46
  ) => PromiseActorLogic<
55
47
  | {
package/src/utils.ts CHANGED
@@ -20,26 +20,17 @@ export type EventSchemas = {
20
20
  };
21
21
  };
22
22
 
23
- export interface ContextSchema {
24
- [key: string]: JSONSchema7;
25
- }
23
+ export type ContextSchema = JSONSchema7 & { type: 'object' };
26
24
 
27
25
  export type ConvertToJSONSchemas<T> = {
28
26
  [K in keyof T]: {
29
- properties: { type: { const: K } };
27
+ properties: { type: { const: K } } & Prop<T[K], 'properties'>;
30
28
  type: 'object';
31
- required: Array<keyof Prop<T[K], 'properties'> | 'type'>;
29
+ required: Array<(keyof Prop<T[K], 'properties'> & string) | 'type'>;
32
30
  additionalProperties: false;
33
- } & T[K];
31
+ };
34
32
  } & {};
35
33
 
36
- export type ConvertContextToJSONSchema<T extends ContextSchema> = {
37
- type: 'object';
38
- properties: T;
39
- readonly required: Array<keyof T & string>;
40
- additionalProperties: false;
41
- };
42
-
43
34
  export function createEventSchemas<T extends EventSchemas>(
44
35
  eventSchemaMap: T
45
36
  ): ConvertToJSONSchemas<T> {
@@ -0,0 +1,9 @@
1
+ // vitest.config.ts
2
+ import dotenv from 'dotenv';
3
+ dotenv.config();
4
+
5
+ export default {
6
+ test: {
7
+ testTimeout: 10000, // Global timeout of 10000ms for all tests
8
+ },
9
+ };