@statelyai/agent 0.0.1 → 0.0.3
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.env.template +6 -0
- package/.github/actions/ci-setup/action.yml +24 -0
- package/.github/workflows/release.yml +35 -0
- package/.vscode/launch.json +17 -0
- package/CHANGELOG.md +13 -0
- package/dist/index.d.ts +66 -6
- package/dist/index.js +86 -11
- package/examples/helpers/helpers.ts +17 -0
- package/examples/helpers/loader.ts +32 -0
- package/examples/helpers/runner.ts +27 -0
- package/examples/joke.ts +181 -152
- package/examples/ticTacToe.ts +133 -121
- package/examples/weather.ts +147 -0
- package/package.json +22 -10
- package/readme.md +41 -0
- package/src/index.ts +1 -0
- package/src/openai.ts +154 -12
- package/src/utils.ts +59 -1
- package/dist/index.d.mts +0 -3
- package/dist/index.mjs +0 -7
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { createAgent, fromEventChoice } from '../src';
|
|
3
|
+
import { assign, createActor, fromPromise, log, setup } from 'xstate';
|
|
4
|
+
import { getFromTerminal } from './helpers/helpers';
|
|
5
|
+
|
|
6
|
+
async function searchTavily(
|
|
7
|
+
input: string,
|
|
8
|
+
options: {
|
|
9
|
+
maxResults?: number;
|
|
10
|
+
apiKey: string;
|
|
11
|
+
}
|
|
12
|
+
) {
|
|
13
|
+
const body: Record<string, unknown> = {
|
|
14
|
+
query: input,
|
|
15
|
+
max_results: options.maxResults,
|
|
16
|
+
api_key: options.apiKey,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const response = await fetch('https://api.tavily.com/search', {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
headers: {
|
|
22
|
+
'content-type': 'application/json',
|
|
23
|
+
},
|
|
24
|
+
body: JSON.stringify(body),
|
|
25
|
+
});
|
|
26
|
+
const json = await response.json();
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Request failed with status code ${response.status}: ${json.error}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
if (!Array.isArray(json.results)) {
|
|
33
|
+
throw new Error(`Could not parse Tavily results. Please try again.`);
|
|
34
|
+
}
|
|
35
|
+
return JSON.stringify(json.results);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const openai = new OpenAI({
|
|
39
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const agent = createAgent(openai, {
|
|
43
|
+
model: 'gpt-4-1106-preview',
|
|
44
|
+
context: {
|
|
45
|
+
location: { type: 'string' },
|
|
46
|
+
history: { type: 'array', items: { type: 'string' } },
|
|
47
|
+
count: { type: 'number' },
|
|
48
|
+
},
|
|
49
|
+
events: {
|
|
50
|
+
getWeather: {
|
|
51
|
+
description: 'Get the weather for a location',
|
|
52
|
+
properties: {
|
|
53
|
+
location: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description: 'The location to get the weather for',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
doSomethingElse: {
|
|
60
|
+
description:
|
|
61
|
+
'Do something else, because the user did not provide a location',
|
|
62
|
+
properties: {},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const machine = setup({
|
|
68
|
+
types: agent.types,
|
|
69
|
+
actors: {
|
|
70
|
+
searchTavily: fromPromise(async ({ input }: { input: string }) => {
|
|
71
|
+
const results = await searchTavily(input, {
|
|
72
|
+
maxResults: 5,
|
|
73
|
+
apiKey: process.env.TAVILY_API_KEY!,
|
|
74
|
+
});
|
|
75
|
+
return results;
|
|
76
|
+
}),
|
|
77
|
+
decide: agent.fromEvent(
|
|
78
|
+
(input: string) =>
|
|
79
|
+
`Decide what to do based on the given input, which may or may not be a location: ${input}`
|
|
80
|
+
),
|
|
81
|
+
getFromTerminal,
|
|
82
|
+
},
|
|
83
|
+
}).createMachine({
|
|
84
|
+
initial: 'getLocation',
|
|
85
|
+
context: {
|
|
86
|
+
location: '',
|
|
87
|
+
count: 0,
|
|
88
|
+
history: [],
|
|
89
|
+
},
|
|
90
|
+
states: {
|
|
91
|
+
getLocation: {
|
|
92
|
+
invoke: {
|
|
93
|
+
src: 'getFromTerminal',
|
|
94
|
+
input: 'Location?',
|
|
95
|
+
onDone: {
|
|
96
|
+
actions: assign({
|
|
97
|
+
location: ({ event }) => event.output,
|
|
98
|
+
}),
|
|
99
|
+
target: 'decide',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
always: {
|
|
103
|
+
guard: ({ context }) => context.count >= 3,
|
|
104
|
+
target: 'stopped',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
decide: {
|
|
108
|
+
entry: log('Deciding...'),
|
|
109
|
+
invoke: {
|
|
110
|
+
src: 'decide',
|
|
111
|
+
input: ({ context }) => context.location,
|
|
112
|
+
},
|
|
113
|
+
on: {
|
|
114
|
+
getWeather: {
|
|
115
|
+
actions: log(({ event }) => event),
|
|
116
|
+
target: 'gettingWeather',
|
|
117
|
+
},
|
|
118
|
+
doSomethingElse: 'getLocation',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
gettingWeather: {
|
|
122
|
+
entry: log('Getting weather...'),
|
|
123
|
+
invoke: {
|
|
124
|
+
src: 'searchTavily',
|
|
125
|
+
input: ({ context }) =>
|
|
126
|
+
`Get the weather for this location: ${context.location}`,
|
|
127
|
+
onDone: {
|
|
128
|
+
actions: [
|
|
129
|
+
log(({ event }) => event.output),
|
|
130
|
+
assign({
|
|
131
|
+
count: ({ context }) => context.count + 1,
|
|
132
|
+
}),
|
|
133
|
+
],
|
|
134
|
+
target: 'getLocation',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
stopped: {
|
|
139
|
+
entry: log('You have used up your search quota. Goodbye!'),
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
exit: () => {
|
|
143
|
+
process.exit();
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
createActor(machine).start();
|
package/package.json
CHANGED
|
@@ -1,26 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/agent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
10
|
-
"lint": "tsc",
|
|
11
|
-
"test": "vitest run",
|
|
12
|
-
"prepublishOnly": "tsup src/index.ts --dts"
|
|
13
|
-
},
|
|
14
8
|
"keywords": [],
|
|
15
9
|
"author": "",
|
|
16
10
|
"license": "MIT",
|
|
17
11
|
"devDependencies": {
|
|
12
|
+
"@changesets/changelog-github": "^0.5.0",
|
|
13
|
+
"@changesets/cli": "^2.27.1",
|
|
18
14
|
"@types/node": "^20.10.6",
|
|
15
|
+
"dotenv": "^16.3.1",
|
|
16
|
+
"json-schema-to-ts": "^3.0.0",
|
|
17
|
+
"openai": "^4.24.1",
|
|
18
|
+
"ts-node": "^10.9.2",
|
|
19
19
|
"tsup": "^8.0.1",
|
|
20
20
|
"typescript": "^5.3.3"
|
|
21
21
|
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
22
25
|
"dependencies": {
|
|
23
|
-
"
|
|
24
|
-
|
|
26
|
+
"xstate": "^5.5.1"
|
|
27
|
+
},
|
|
28
|
+
"packageManager": "pnpm@8.11.0",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
31
|
+
"lint": "tsc",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"example": "ts-node examples/helpers/runner.ts",
|
|
34
|
+
"changeset": "changeset",
|
|
35
|
+
"release": "changeset publish",
|
|
36
|
+
"version": "changeset version"
|
|
25
37
|
}
|
|
26
|
-
}
|
|
38
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Stately Agent (alpha)
|
|
2
|
+
|
|
3
|
+
🚧 Documentation in progress! Please see [the examples directory](https://github.com/statelyai/agent/tree/main/examples) for working examples.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install `openai`, and `@statelyai/agent`:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install openai @statelyai/agent
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Work in progress. For now, see the examples:
|
|
16
|
+
|
|
17
|
+
- [Joke generator](https://github.com/statelyai/agent/tree/main/examples/joke.ts)
|
|
18
|
+
- Demonstrates `agent.fromChatCompletion(...)` to generate a joke and provide a joke rating
|
|
19
|
+
- Demonstrates `agent.fromEvent(...)` to choose whether to keep generating jokes or stop
|
|
20
|
+
- [Tic-tac-toe](https://github.com/statelyai/agent/tree/main/examples/ticTacToe.ts)
|
|
21
|
+
- Demonstrates `agent.fromEvent(...)` to have an agent play itself in a game of tic-tac-toe with precise events
|
|
22
|
+
- Demonstrates `agent.fromChatCompletionStream(...)` to produce a game report at the end of the game
|
|
23
|
+
- [Weather](https://github.com/statelyai/agent/tree/main/examples/weather.ts)
|
|
24
|
+
- Demonstrates using [Tavily](https://tavily.com/) as an external API
|
|
25
|
+
- Demonstrates `agent.fromEvent(...)` to only use Tavily to get the weather if the user provides a valid location
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
First, clone this repo locally. To run the examples in this repo, create a `.env` file at the root of the repo with the following contents:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
OPENAI_API_KEY="your-openai-api-key"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Then, install the dependencies (`npm install`) and run the examples:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm run example joke
|
|
39
|
+
# or:
|
|
40
|
+
# npm run example ticTacToe
|
|
41
|
+
```
|
package/src/index.ts
CHANGED
package/src/openai.ts
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
|
-
import OpenAI from 'openai';
|
|
1
|
+
import type OpenAI from 'openai';
|
|
2
2
|
import {
|
|
3
3
|
AnyEventObject,
|
|
4
|
+
ObservableActorLogic,
|
|
4
5
|
Observer,
|
|
6
|
+
PromiseActorLogic,
|
|
7
|
+
Values,
|
|
5
8
|
fromObservable,
|
|
6
9
|
fromPromise,
|
|
10
|
+
setup,
|
|
7
11
|
toObserver,
|
|
8
12
|
} from 'xstate';
|
|
9
13
|
import { getAllTransitions } from './utils';
|
|
14
|
+
import {
|
|
15
|
+
ContextSchema,
|
|
16
|
+
EventSchemas,
|
|
17
|
+
ConvertContextToJSONSchema,
|
|
18
|
+
ConvertToJSONSchemas,
|
|
19
|
+
createEventSchemas,
|
|
20
|
+
} from './utils';
|
|
21
|
+
import { FromSchema } from 'json-schema-to-ts';
|
|
22
|
+
import { ChatCompletionCreateParamsNonStreaming } from 'openai/resources';
|
|
23
|
+
import {
|
|
24
|
+
ChatCompletionCreateParamsBase,
|
|
25
|
+
ChatCompletionCreateParamsStreaming,
|
|
26
|
+
} from 'openai/resources/chat/completions';
|
|
10
27
|
|
|
11
28
|
/**
|
|
12
29
|
* Creates [promise actor logic](https://stately.ai/docs/promise-actors) that uses the OpenAI API to generate a completion.
|
|
@@ -17,14 +34,27 @@ import { getAllTransitions } from './utils';
|
|
|
17
34
|
*/
|
|
18
35
|
export function fromChatCompletion<TInput>(
|
|
19
36
|
openai: OpenAI,
|
|
37
|
+
agentSettings: CreateAgentOutput<any>,
|
|
20
38
|
inputFn: (
|
|
21
39
|
input: TInput
|
|
22
|
-
) => OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming
|
|
40
|
+
) => string | OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming
|
|
23
41
|
) {
|
|
24
42
|
return fromPromise<OpenAI.Chat.Completions.ChatCompletion, TInput>(
|
|
25
43
|
async ({ input }) => {
|
|
26
44
|
const openAiInput = inputFn(input);
|
|
27
|
-
const
|
|
45
|
+
const params: ChatCompletionCreateParamsNonStreaming =
|
|
46
|
+
typeof openAiInput === 'string'
|
|
47
|
+
? {
|
|
48
|
+
model: agentSettings.model,
|
|
49
|
+
messages: [
|
|
50
|
+
{
|
|
51
|
+
role: 'user',
|
|
52
|
+
content: openAiInput,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
}
|
|
56
|
+
: openAiInput;
|
|
57
|
+
const response = await openai.chat.completions.create(params);
|
|
28
58
|
|
|
29
59
|
return response;
|
|
30
60
|
}
|
|
@@ -39,9 +69,10 @@ export function fromChatCompletion<TInput>(
|
|
|
39
69
|
*/
|
|
40
70
|
export function fromChatCompletionStream<TInput>(
|
|
41
71
|
openai: OpenAI,
|
|
72
|
+
agentSettings: CreateAgentOutput<any>,
|
|
42
73
|
inputFn: (
|
|
43
74
|
input: TInput
|
|
44
|
-
) => OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming
|
|
75
|
+
) => string | OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming
|
|
45
76
|
) {
|
|
46
77
|
return fromObservable<OpenAI.Chat.Completions.ChatCompletionChunk, TInput>(
|
|
47
78
|
({ input }) => {
|
|
@@ -49,8 +80,20 @@ export function fromChatCompletionStream<TInput>(
|
|
|
49
80
|
|
|
50
81
|
(async () => {
|
|
51
82
|
const openAiInput = inputFn(input);
|
|
83
|
+
const resolvedParams: ChatCompletionCreateParamsBase =
|
|
84
|
+
typeof openAiInput === 'string'
|
|
85
|
+
? {
|
|
86
|
+
model: agentSettings.model,
|
|
87
|
+
messages: [
|
|
88
|
+
{
|
|
89
|
+
role: 'user',
|
|
90
|
+
content: openAiInput,
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
}
|
|
94
|
+
: openAiInput;
|
|
52
95
|
const stream = await openai.chat.completions.create({
|
|
53
|
-
...
|
|
96
|
+
...resolvedParams,
|
|
54
97
|
stream: true,
|
|
55
98
|
});
|
|
56
99
|
|
|
@@ -85,12 +128,20 @@ export function fromChatCompletionStream<TInput>(
|
|
|
85
128
|
*/
|
|
86
129
|
export function fromEventChoice<TInput>(
|
|
87
130
|
openai: OpenAI,
|
|
131
|
+
agentSettings: CreateAgentOutput<any>,
|
|
88
132
|
inputFn: (
|
|
89
133
|
input: TInput
|
|
90
|
-
) => OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming
|
|
134
|
+
) => string | OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming,
|
|
135
|
+
options?: {
|
|
136
|
+
/**
|
|
137
|
+
* Immediately execute sending the event to the parent actor.
|
|
138
|
+
* @default false
|
|
139
|
+
*/
|
|
140
|
+
execute?: boolean;
|
|
141
|
+
}
|
|
91
142
|
) {
|
|
92
143
|
return fromPromise<AnyEventObject[] | undefined, TInput>(
|
|
93
|
-
async ({ input, self }) => {
|
|
144
|
+
async ({ input, self, system }) => {
|
|
94
145
|
const transitions = getAllTransitions(self._parent!.getSnapshot());
|
|
95
146
|
const functionNameMapping: Record<string, string> = {};
|
|
96
147
|
const tools = transitions
|
|
@@ -104,32 +155,123 @@ export function fromEventChoice<TInput>(
|
|
|
104
155
|
type: 'function',
|
|
105
156
|
function: {
|
|
106
157
|
name,
|
|
107
|
-
description:
|
|
158
|
+
description:
|
|
159
|
+
t.description ??
|
|
160
|
+
agentSettings.schemas.events[t.eventType]?.description,
|
|
108
161
|
parameters: {
|
|
109
162
|
type: 'object',
|
|
110
|
-
properties:
|
|
163
|
+
properties:
|
|
164
|
+
agentSettings.schemas.events[t.eventType]?.properties ?? {},
|
|
111
165
|
},
|
|
112
166
|
},
|
|
113
167
|
} as const;
|
|
114
168
|
});
|
|
169
|
+
|
|
115
170
|
const openAiInput = inputFn(input);
|
|
171
|
+
const completionParams: ChatCompletionCreateParamsNonStreaming =
|
|
172
|
+
typeof openAiInput === 'string'
|
|
173
|
+
? {
|
|
174
|
+
model: agentSettings.model,
|
|
175
|
+
messages: [
|
|
176
|
+
{
|
|
177
|
+
role: 'user',
|
|
178
|
+
content: openAiInput,
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
}
|
|
182
|
+
: openAiInput;
|
|
116
183
|
const completion = await openai.chat.completions.create({
|
|
117
|
-
...
|
|
184
|
+
...completionParams,
|
|
118
185
|
tools,
|
|
119
186
|
});
|
|
120
187
|
|
|
121
188
|
const toolCalls = completion.choices[0]?.message.tool_calls;
|
|
122
189
|
|
|
123
190
|
if (toolCalls) {
|
|
124
|
-
|
|
191
|
+
const events = toolCalls.map((tc) => {
|
|
125
192
|
return {
|
|
126
193
|
type: functionNameMapping[tc.function.name],
|
|
127
194
|
...JSON.parse(tc.function.arguments),
|
|
128
195
|
};
|
|
129
196
|
});
|
|
197
|
+
|
|
198
|
+
if (options?.execute) {
|
|
199
|
+
events.forEach((event) => {
|
|
200
|
+
// @ts-ignore
|
|
201
|
+
system._relay(self, self._parent, event);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
130
204
|
}
|
|
131
205
|
|
|
132
|
-
return
|
|
206
|
+
return undefined;
|
|
133
207
|
}
|
|
134
208
|
);
|
|
135
209
|
}
|
|
210
|
+
|
|
211
|
+
interface CreateAgentOutput<
|
|
212
|
+
T extends {
|
|
213
|
+
model: ChatCompletionCreateParamsBase['model'];
|
|
214
|
+
context: ContextSchema;
|
|
215
|
+
events: EventSchemas;
|
|
216
|
+
}
|
|
217
|
+
> {
|
|
218
|
+
model: T['model'];
|
|
219
|
+
schemas: T;
|
|
220
|
+
types: {
|
|
221
|
+
context: FromSchema<ConvertContextToJSONSchema<T['context']>>;
|
|
222
|
+
events: FromSchema<Values<ConvertToJSONSchemas<T['events']>>>;
|
|
223
|
+
};
|
|
224
|
+
fromEvent: <TInput>(
|
|
225
|
+
inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
|
|
226
|
+
) => PromiseActorLogic<
|
|
227
|
+
FromSchema<Values<ConvertToJSONSchemas<T['events']>>>[] | undefined,
|
|
228
|
+
TInput
|
|
229
|
+
>;
|
|
230
|
+
fromEventChoice: <TInput>(
|
|
231
|
+
inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
|
|
232
|
+
) => PromiseActorLogic<
|
|
233
|
+
FromSchema<Values<ConvertToJSONSchemas<T['events']>>>[] | undefined,
|
|
234
|
+
TInput
|
|
235
|
+
>;
|
|
236
|
+
fromChatCompletion: <TInput>(
|
|
237
|
+
inputFn: (input: TInput) => string | ChatCompletionCreateParamsNonStreaming
|
|
238
|
+
) => PromiseActorLogic<OpenAI.Chat.Completions.ChatCompletion, TInput>;
|
|
239
|
+
fromChatCompletionStream: <TInput>(
|
|
240
|
+
inputFn: (input: TInput) => string | ChatCompletionCreateParamsStreaming
|
|
241
|
+
) => ObservableActorLogic<
|
|
242
|
+
OpenAI.Chat.Completions.ChatCompletionChunk,
|
|
243
|
+
TInput
|
|
244
|
+
>;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function createAgent<
|
|
248
|
+
T extends {
|
|
249
|
+
model: ChatCompletionCreateParamsBase['model'];
|
|
250
|
+
context: ContextSchema;
|
|
251
|
+
events: EventSchemas;
|
|
252
|
+
}
|
|
253
|
+
>(openai: OpenAI, settings: T): CreateAgentOutput<T> {
|
|
254
|
+
const agentSettings: CreateAgentOutput<T> = {
|
|
255
|
+
model: settings.model,
|
|
256
|
+
schemas: {
|
|
257
|
+
context: {
|
|
258
|
+
type: 'object',
|
|
259
|
+
properties: settings.context,
|
|
260
|
+
additionalProperties: false,
|
|
261
|
+
},
|
|
262
|
+
events: createEventSchemas(settings.events),
|
|
263
|
+
} as any,
|
|
264
|
+
types: {} as any,
|
|
265
|
+
fromEvent: (input) =>
|
|
266
|
+
// @ts-ignore
|
|
267
|
+
fromEventChoice(openai, agentSettings, input, { execute: true }),
|
|
268
|
+
// @ts-ignore infinitely deep
|
|
269
|
+
fromEventChoice: (input) => fromEventChoice(openai, agentSettings, input),
|
|
270
|
+
fromChatCompletion: (input) =>
|
|
271
|
+
fromChatCompletion(openai, agentSettings, input),
|
|
272
|
+
fromChatCompletionStream: (input) =>
|
|
273
|
+
fromChatCompletionStream(openai, agentSettings, input),
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
return agentSettings as any;
|
|
277
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { AnyMachineSnapshot, AnyStateNode } from 'xstate';
|
|
1
|
+
import { AnyMachineSnapshot, AnyStateNode, Prop, Values } from 'xstate';
|
|
2
|
+
import { FromSchema } from 'json-schema-to-ts';
|
|
3
|
+
import { JSONSchema7 } from 'json-schema-to-ts/lib/types/definitions';
|
|
2
4
|
|
|
3
5
|
export function getAllTransitions(state: AnyMachineSnapshot) {
|
|
4
6
|
const nodes = state._nodes;
|
|
@@ -8,3 +10,59 @@ export function getAllTransitions(state: AnyMachineSnapshot) {
|
|
|
8
10
|
|
|
9
11
|
return transitions;
|
|
10
12
|
}
|
|
13
|
+
|
|
14
|
+
export type EventSchemas = {
|
|
15
|
+
[key: string]: {
|
|
16
|
+
description?: string;
|
|
17
|
+
properties?: {
|
|
18
|
+
[key: string]: JSONSchema7;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export interface ContextSchema {
|
|
24
|
+
[key: string]: JSONSchema7;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ConvertToJSONSchemas<T> = {
|
|
28
|
+
[K in keyof T]: {
|
|
29
|
+
properties: { type: { const: K } };
|
|
30
|
+
type: 'object';
|
|
31
|
+
required: Array<keyof Prop<T[K], 'properties'> | 'type'>;
|
|
32
|
+
additionalProperties: false;
|
|
33
|
+
} & T[K];
|
|
34
|
+
} & {};
|
|
35
|
+
|
|
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
|
+
export function createEventSchemas<T extends EventSchemas>(
|
|
44
|
+
eventSchemaMap: T
|
|
45
|
+
): ConvertToJSONSchemas<T> {
|
|
46
|
+
const resolvedEventSchemaMap = {};
|
|
47
|
+
|
|
48
|
+
for (const [key, schema] of Object.entries(eventSchemaMap)) {
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
resolvedEventSchemaMap[key] = {
|
|
51
|
+
type: 'object',
|
|
52
|
+
required: ['type'],
|
|
53
|
+
properties: {
|
|
54
|
+
type: {
|
|
55
|
+
const: key,
|
|
56
|
+
},
|
|
57
|
+
...schema.properties,
|
|
58
|
+
},
|
|
59
|
+
additionalProperties: false,
|
|
60
|
+
...schema,
|
|
61
|
+
} as JSONSchema7;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return resolvedEventSchemaMap as ConvertToJSONSchemas<T>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type InferEventsFromSchemas<T extends ConvertToJSONSchemas<any>> =
|
|
68
|
+
FromSchema<Values<T>>;
|
package/dist/index.d.mts
DELETED