@threaded/ai 1.0.30 → 1.1.0
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/README.md +240 -0
- package/dist/approval.d.ts +18 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +35 -0
- package/dist/approval.js.map +1 -0
- package/dist/composition/compose.d.ts +3 -0
- package/dist/composition/compose.d.ts.map +1 -0
- package/dist/composition/compose.js +38 -0
- package/dist/composition/compose.js.map +1 -0
- package/dist/composition/model.d.ts +9 -0
- package/dist/composition/model.d.ts.map +1 -0
- package/dist/composition/model.js +192 -0
- package/dist/composition/model.js.map +1 -0
- package/dist/composition/retry.d.ts +6 -0
- package/dist/composition/retry.d.ts.map +1 -0
- package/dist/composition/retry.js +18 -0
- package/dist/composition/retry.js.map +1 -0
- package/dist/composition/scope.d.ts +3 -0
- package/dist/composition/scope.d.ts.map +1 -0
- package/dist/composition/scope.js +83 -0
- package/dist/composition/scope.js.map +1 -0
- package/dist/composition/tap.d.ts +3 -0
- package/dist/composition/tap.d.ts.map +1 -0
- package/dist/composition/tap.js +7 -0
- package/dist/composition/tap.js.map +1 -0
- package/dist/composition/when.d.ts +3 -0
- package/dist/composition/when.d.ts.map +1 -0
- package/dist/composition/when.js +9 -0
- package/dist/composition/when.js.map +1 -0
- package/dist/embed.d.ts +16 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +72 -0
- package/dist/embed.js.map +1 -0
- package/dist/examples.d.ts +2 -0
- package/dist/examples.d.ts.map +1 -0
- package/dist/examples.js +6 -0
- package/dist/examples.js.map +1 -0
- package/dist/helpers.d.ts +17 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +104 -0
- package/dist/helpers.js.map +1 -0
- package/dist/image-model-schema.d.ts +19 -0
- package/dist/image-model-schema.d.ts.map +1 -0
- package/dist/image-model-schema.js +103 -0
- package/dist/image-model-schema.js.map +1 -0
- package/dist/image.d.ts +3 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +120 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +18 -352
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -2073
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +29 -0
- package/dist/mcp.js.map +1 -0
- package/dist/providers/anthropic.d.ts +3 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +226 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/google.d.ts +3 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +244 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/huggingface.d.ts +3 -0
- package/dist/providers/huggingface.d.ts.map +1 -0
- package/dist/providers/huggingface.js +59 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +29 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/local.d.ts +3 -0
- package/dist/providers/local.d.ts.map +1 -0
- package/dist/providers/local.js +152 -0
- package/dist/providers/local.js.map +1 -0
- package/dist/providers/openai.d.ts +3 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +165 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/xai.d.ts +3 -0
- package/dist/providers/xai.d.ts.map +1 -0
- package/dist/providers/xai.js +161 -0
- package/dist/providers/xai.js.map +1 -0
- package/dist/schema.d.ts +7 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +44 -0
- package/dist/schema.js.map +1 -0
- package/dist/thread.d.ts +25 -0
- package/dist/thread.d.ts.map +1 -0
- package/dist/thread.js +87 -0
- package/dist/thread.js.map +1 -0
- package/dist/types.d.ts +193 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/rateLimited.d.ts +27 -0
- package/dist/utils/rateLimited.d.ts.map +1 -0
- package/dist/utils/rateLimited.js +74 -0
- package/dist/utils/rateLimited.js.map +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +78 -0
- package/dist/utils.js.map +1 -0
- package/package.json +34 -12
- package/.claude/settings.local.json +0 -15
- package/.lore +0 -65
- package/dist/index.cjs +0 -2149
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -352
- package/tsconfig.json +0 -29
package/README.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# @threaded/ai
|
|
2
|
+
|
|
3
|
+
Composable LLM inference with multi-provider support, tool execution, streaming, and approval workflows.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @threaded/ai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import { compose, scope, model, setKeys } from "@threaded/ai"
|
|
15
|
+
|
|
16
|
+
setKeys({ openai: process.env.OPENAI_API_KEY })
|
|
17
|
+
|
|
18
|
+
const result = await compose(model())("What is 2 + 2?")
|
|
19
|
+
console.log(result.lastResponse.content)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Composition
|
|
23
|
+
|
|
24
|
+
Build workflows by composing steps. Each step receives a context and returns a new one.
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { compose, scope, model, when, tap } from "@threaded/ai"
|
|
28
|
+
import { toolWasCalled } from "@threaded/ai"
|
|
29
|
+
|
|
30
|
+
const workflow = compose(
|
|
31
|
+
scope({ tools: [searchTool], system: "you are a researcher" },
|
|
32
|
+
model({ model: "openai/gpt-4o-mini" })
|
|
33
|
+
),
|
|
34
|
+
when(toolWasCalled("search"),
|
|
35
|
+
scope({ system: "summarize the findings" }, model())
|
|
36
|
+
),
|
|
37
|
+
tap(ctx => console.log(ctx.lastResponse?.content))
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const result = await workflow("find recent papers on WebSockets")
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Primitives
|
|
44
|
+
|
|
45
|
+
| Function | Purpose |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `compose(...steps)` | Chain steps into a pipeline |
|
|
48
|
+
| `scope(config, ...steps)` | Isolated context with tools, system prompt, inheritance |
|
|
49
|
+
| `model(config?)` | Call an LLM and auto-execute tool calls |
|
|
50
|
+
| `when(condition, step)` | Conditional execution |
|
|
51
|
+
| `tap(fn)` | Side effects without modifying context |
|
|
52
|
+
| `retry({ times }, step)` | Retry a step on failure |
|
|
53
|
+
|
|
54
|
+
## Providers
|
|
55
|
+
|
|
56
|
+
Select a provider by prefixing the model name:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
model({ model: "openai/gpt-4o-mini" })
|
|
60
|
+
model({ model: "anthropic/claude-sonnet-4-5-20250929" })
|
|
61
|
+
model({ model: "google/gemini-2.0-flash" })
|
|
62
|
+
model({ model: "xai/grok-3" })
|
|
63
|
+
model({ model: "local/llama2" }) // Ollama
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
API keys are resolved in order: `config.apiKey` > `setKeys()` > environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.)
|
|
67
|
+
|
|
68
|
+
## Tools
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
const searchTool = {
|
|
72
|
+
name: "search",
|
|
73
|
+
description: "search the web",
|
|
74
|
+
schema: {
|
|
75
|
+
query: { type: "string", description: "search query" },
|
|
76
|
+
},
|
|
77
|
+
execute: async ({ query }) => {
|
|
78
|
+
return await searchWeb(query)
|
|
79
|
+
},
|
|
80
|
+
_maxCalls: 5,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const result = await compose(
|
|
84
|
+
scope({ tools: [searchTool] }, model())
|
|
85
|
+
)("search for WebSocket frameworks")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Tool calls are automatic - when the model returns tool calls, they're executed and the results fed back until the model responds with text.
|
|
89
|
+
|
|
90
|
+
## Structured Output
|
|
91
|
+
|
|
92
|
+
Pass a JSON schema or Zod schema:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
import { z } from "zod"
|
|
96
|
+
|
|
97
|
+
const result = await compose(
|
|
98
|
+
model({
|
|
99
|
+
model: "openai/gpt-4o-mini",
|
|
100
|
+
schema: z.object({
|
|
101
|
+
name: z.string(),
|
|
102
|
+
age: z.number(),
|
|
103
|
+
}),
|
|
104
|
+
})
|
|
105
|
+
)("Extract: John is 30 years old")
|
|
106
|
+
|
|
107
|
+
JSON.parse(result.lastResponse.content)
|
|
108
|
+
// { name: "John", age: 30 }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Streaming
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
const result = await compose(
|
|
115
|
+
scope({
|
|
116
|
+
stream: (event) => {
|
|
117
|
+
if (event.type === "content") process.stdout.write(event.content)
|
|
118
|
+
if (event.type === "tool_executing") console.log("calling", event.call.function.name)
|
|
119
|
+
},
|
|
120
|
+
}, model())
|
|
121
|
+
)("explain WebSockets")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Threads
|
|
125
|
+
|
|
126
|
+
Persistent multi-turn conversations:
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
import { getOrCreateThread, compose, model } from "@threaded/ai"
|
|
130
|
+
|
|
131
|
+
const thread = getOrCreateThread("user-123")
|
|
132
|
+
await thread.message("hello", compose(model()))
|
|
133
|
+
await thread.message("what did I just say?", compose(model()))
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Custom storage:
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
const thread = getOrCreateThread("user-123", {
|
|
140
|
+
get: async (id) => db.getMessages(id),
|
|
141
|
+
set: async (id, messages) => db.setMessages(id, messages),
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Scope Inheritance
|
|
146
|
+
|
|
147
|
+
Control what inner steps see:
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
import { Inherit } from "@threaded/ai"
|
|
151
|
+
|
|
152
|
+
// fresh context, no history
|
|
153
|
+
scope({ inherit: Inherit.Nothing }, model())
|
|
154
|
+
|
|
155
|
+
// carry history but not tools
|
|
156
|
+
scope({ inherit: Inherit.Conversation }, model())
|
|
157
|
+
|
|
158
|
+
// carry everything
|
|
159
|
+
scope({ inherit: Inherit.All }, model())
|
|
160
|
+
|
|
161
|
+
// silent - tools execute but history isn't modified
|
|
162
|
+
scope({ silent: true, tools: [analysisTool] }, model())
|
|
163
|
+
|
|
164
|
+
// loop until condition
|
|
165
|
+
scope({ until: noToolsCalled(), tools: [researchTool] }, model())
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Tool Approval
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
const result = await compose(
|
|
172
|
+
scope({
|
|
173
|
+
tools: [deleteTool],
|
|
174
|
+
toolConfig: {
|
|
175
|
+
requireApproval: true,
|
|
176
|
+
approvalCallback: (call) => confirm(`Allow ${call.function.name}?`),
|
|
177
|
+
},
|
|
178
|
+
}, model())
|
|
179
|
+
)("delete all inactive users")
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Embeddings
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
import { embed } from "@threaded/ai"
|
|
186
|
+
|
|
187
|
+
const vector = await embed("openai/text-embedding-3-small", "hello world")
|
|
188
|
+
const vectors = await embed("openai/text-embedding-3-small", ["hello", "world"])
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Image Generation
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
import { generateImage } from "@threaded/ai"
|
|
195
|
+
|
|
196
|
+
const image = await generateImage("openai/dall-e-3", "a cat in space", {
|
|
197
|
+
size: "1024x1024",
|
|
198
|
+
quality: "hd",
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## MCP Integration
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
import { createMCPTools } from "@threaded/ai"
|
|
206
|
+
|
|
207
|
+
const mcpTools = await createMCPTools(mcpClient)
|
|
208
|
+
const result = await compose(
|
|
209
|
+
scope({ tools: mcpTools }, model())
|
|
210
|
+
)("use the available tools")
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Helpers
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
import { noToolsCalled, toolWasCalled, everyNMessages, appendToLastRequest } from "@threaded/ai"
|
|
217
|
+
|
|
218
|
+
// loop until model stops calling tools
|
|
219
|
+
scope({ until: noToolsCalled(), tools: [...] }, model())
|
|
220
|
+
|
|
221
|
+
// conditional on tool usage
|
|
222
|
+
when(toolWasCalled("search"), summarizeStep)
|
|
223
|
+
|
|
224
|
+
// periodic actions
|
|
225
|
+
everyNMessages(10, appendToLastRequest("stay concise"))
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Usage Tracking
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
const result = await workflow("prompt")
|
|
232
|
+
console.log(result.usage)
|
|
233
|
+
// { promptTokens: 150, completionTokens: 42, totalTokens: 192 }
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Usage accumulates through nested scopes automatically.
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
ISC
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ToolCall } from "./types";
|
|
2
|
+
export interface ApprovalRequest {
|
|
3
|
+
id: string;
|
|
4
|
+
toolCall: ToolCall;
|
|
5
|
+
approvalId?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ApprovalResponse {
|
|
8
|
+
id: string;
|
|
9
|
+
approved: boolean;
|
|
10
|
+
reason?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const generateApprovalToken: () => string;
|
|
13
|
+
export declare const requestApproval: (toolCall: ToolCall, approvalId?: string) => Promise<ApprovalResponse>;
|
|
14
|
+
export declare const resolveApproval: (response: ApprovalResponse) => boolean;
|
|
15
|
+
export declare const onApprovalRequested: (listener: (request: ApprovalRequest) => void) => void;
|
|
16
|
+
export declare const onApprovalResolved: (listener: (response: ApprovalResponse) => void) => void;
|
|
17
|
+
export declare const removeApprovalListener: (event: "approvalRequested" | "approvalResolved", listener: (...args: any[]) => void) => void;
|
|
18
|
+
//# sourceMappingURL=approval.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAYD,eAAO,MAAM,qBAAqB,QAAO,MAExC,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,UAAU,QAAQ,EAClB,aAAa,MAAM,KAClB,OAAO,CAAC,gBAAgB,CAS1B,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,UAAU,gBAAgB,KAAG,OAQ5D,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,UAAU,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,SAG7C,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,SAG/C,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,OAAO,mBAAmB,GAAG,kBAAkB,EAC/C,UAAU,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,SAGnC,CAAC"}
|
package/dist/approval.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
const state = {
|
|
3
|
+
resolvers: new Map(),
|
|
4
|
+
emitter: new EventEmitter(),
|
|
5
|
+
};
|
|
6
|
+
export const generateApprovalToken = () => {
|
|
7
|
+
return `approval_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
8
|
+
};
|
|
9
|
+
export const requestApproval = async (toolCall, approvalId) => {
|
|
10
|
+
const id = generateApprovalToken();
|
|
11
|
+
const request = { id, toolCall, approvalId };
|
|
12
|
+
state.emitter.emit("approvalRequested", request);
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
state.resolvers.set(id, resolve);
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
export const resolveApproval = (response) => {
|
|
18
|
+
const resolver = state.resolvers.get(response.id);
|
|
19
|
+
if (!resolver)
|
|
20
|
+
return false;
|
|
21
|
+
state.resolvers.delete(response.id);
|
|
22
|
+
resolver(response);
|
|
23
|
+
state.emitter.emit("approvalResolved", response);
|
|
24
|
+
return true;
|
|
25
|
+
};
|
|
26
|
+
export const onApprovalRequested = (listener) => {
|
|
27
|
+
state.emitter.on("approvalRequested", listener);
|
|
28
|
+
};
|
|
29
|
+
export const onApprovalResolved = (listener) => {
|
|
30
|
+
state.emitter.on("approvalResolved", listener);
|
|
31
|
+
};
|
|
32
|
+
export const removeApprovalListener = (event, listener) => {
|
|
33
|
+
state.emitter.removeListener(event, listener);
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAoBtC,MAAM,KAAK,GAAyB;IAClC,SAAS,EAAE,IAAI,GAAG,EAAE;IACpB,OAAO,EAAE,IAAI,YAAY,EAAE;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAW,EAAE;IAChD,OAAO,YAAY,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAChF,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,QAAkB,EAClB,UAAmB,EACQ,EAAE;IAC7B,MAAM,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACnC,MAAM,OAAO,GAAoB,EAAE,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAE9D,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC;IAEjD,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;QAC/C,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAA0B,EAAW,EAAE;IACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,QAA4C,EAC5C,EAAE;IACF,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,QAA8C,EAC9C,EAAE;IACF,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,KAA+C,EAC/C,QAAkC,EAClC,EAAE;IACF,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAChD,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/composition/compose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAuB,YAAY,EAAE,MAAM,UAAU,CAAC;AAY/E,eAAO,MAAM,OAAO,GAAI,GAAG,OAAO,YAAY,EAAE,KAAG,gBA8BlD,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const enrichContext = (ctx) => {
|
|
2
|
+
const lastUserMessage = [...ctx.history]
|
|
3
|
+
.reverse()
|
|
4
|
+
.find((msg) => msg.role === "user");
|
|
5
|
+
return {
|
|
6
|
+
...ctx,
|
|
7
|
+
lastRequest: lastUserMessage,
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export const compose = (...steps) => {
|
|
11
|
+
return async (ctxOrMessage) => {
|
|
12
|
+
let initialContext;
|
|
13
|
+
if (typeof ctxOrMessage === "string") {
|
|
14
|
+
initialContext = {
|
|
15
|
+
history: [{ role: "user", content: ctxOrMessage }],
|
|
16
|
+
tools: [],
|
|
17
|
+
toolExecutors: {},
|
|
18
|
+
toolLimits: {},
|
|
19
|
+
toolCallCounts: {},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
initialContext = ctxOrMessage || {
|
|
24
|
+
history: [],
|
|
25
|
+
tools: [],
|
|
26
|
+
toolExecutors: {},
|
|
27
|
+
toolLimits: {},
|
|
28
|
+
toolCallCounts: {},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
let next = enrichContext(initialContext);
|
|
32
|
+
for (const step of steps) {
|
|
33
|
+
next = await step(enrichContext(next));
|
|
34
|
+
}
|
|
35
|
+
return next;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.js","sourceRoot":"","sources":["../../src/composition/compose.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG,CAAC,GAAwB,EAAuB,EAAE;IACtE,MAAM,eAAe,GAAG,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;SACrC,OAAO,EAAE;SACT,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACtC,OAAO;QACL,GAAG,GAAG;QACN,WAAW,EAAE,eAAe;KAC7B,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,GAAG,KAAqB,EAAoB,EAAE;IACpE,OAAO,KAAK,EAAE,YAA0C,EAAgC,EAAE;QACxF,IAAI,cAAmC,CAAC;QAExC,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACrC,cAAc,GAAG;gBACf,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;gBAClD,KAAK,EAAE,EAAE;gBACT,aAAa,EAAE,EAAE;gBACjB,UAAU,EAAE,EAAE;gBACd,cAAc,EAAE,EAAE;aACnB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,YAAY,IAAI;gBAC/B,OAAO,EAAE,EAAE;gBACX,KAAK,EAAE,EAAE;gBACT,aAAa,EAAE,EAAE;gBACjB,UAAU,EAAE,EAAE;gBACd,cAAc,EAAE,EAAE;aACnB,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;QAEzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ConversationContext, JsonSchema, StandardSchema, ComposedFunction } from "../types";
|
|
2
|
+
export declare const model: ({ model, schema, system, apiKey, baseUrl, }?: {
|
|
3
|
+
model?: string;
|
|
4
|
+
schema?: JsonSchema | StandardSchema;
|
|
5
|
+
system?: string | ((ctx: ConversationContext) => string);
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
}) => ComposedFunction;
|
|
9
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/composition/model.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,mBAAmB,EAEnB,UAAU,EACV,cAAc,EACd,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAGlB,eAAO,MAAM,KAAK,GAAI,8CAMnB;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,GAAG,cAAc,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,MAAM,CAAC,CAAC;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,KAAG,gBA0DR,CAAC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { callProvider } from "../providers";
|
|
2
|
+
import { normalizeSchema } from "../schema";
|
|
3
|
+
import { requestApproval } from "../approval";
|
|
4
|
+
export const model = ({ model = "openai/gpt-4o-mini", schema, system, apiKey, baseUrl, } = {}) => {
|
|
5
|
+
return async (ctxOrMessage) => {
|
|
6
|
+
const ctx = typeof ctxOrMessage === "string"
|
|
7
|
+
? // model()("hello!");
|
|
8
|
+
{
|
|
9
|
+
history: [{ role: "user", content: ctxOrMessage }],
|
|
10
|
+
tools: [],
|
|
11
|
+
}
|
|
12
|
+
: // model()(/* few shot or history */);
|
|
13
|
+
ctxOrMessage;
|
|
14
|
+
const normalizedSchema = schema ? normalizeSchema(schema) : undefined;
|
|
15
|
+
let currentCtx = ctx;
|
|
16
|
+
if (system) {
|
|
17
|
+
const systemContent = typeof system === "function" ? system(currentCtx) : system;
|
|
18
|
+
const [first, ...rest] = currentCtx.history;
|
|
19
|
+
if (first?.role === "system") {
|
|
20
|
+
currentCtx = {
|
|
21
|
+
...currentCtx,
|
|
22
|
+
history: [{ role: "system", content: systemContent }, ...rest],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
currentCtx = {
|
|
27
|
+
...currentCtx,
|
|
28
|
+
history: [{ role: "system", content: systemContent }, ...currentCtx.history],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const systemMessage = currentCtx.history.find((m) => m.role === "system");
|
|
33
|
+
const instructions = systemMessage?.content;
|
|
34
|
+
do {
|
|
35
|
+
if (currentCtx.abortSignal?.aborted) {
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
currentCtx = await callProvider({ model, instructions, schema: normalizedSchema, apiKey, baseUrl }, currentCtx);
|
|
39
|
+
if (currentCtx.lastResponse?.tool_calls && currentCtx.tools?.length) {
|
|
40
|
+
currentCtx = await executeTools(currentCtx);
|
|
41
|
+
}
|
|
42
|
+
} while (currentCtx.lastResponse?.tool_calls &&
|
|
43
|
+
currentCtx.tools?.length &&
|
|
44
|
+
!currentCtx.abortSignal?.aborted);
|
|
45
|
+
return currentCtx;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
const executeTools = async (ctx) => {
|
|
49
|
+
const calls = ctx.lastResponse?.tool_calls || [];
|
|
50
|
+
if (!calls.length)
|
|
51
|
+
return ctx;
|
|
52
|
+
if (ctx.stream) {
|
|
53
|
+
ctx.stream({ type: "tool_calls_ready", calls });
|
|
54
|
+
}
|
|
55
|
+
const toolConfig = ctx.toolConfig || {};
|
|
56
|
+
const { requireApproval = false, approvalCallback, parallel = false, retryCount = 0, approvalId, executeOnApproval = false, } = toolConfig;
|
|
57
|
+
const updatedCounts = { ...(ctx.toolCallCounts || {}) };
|
|
58
|
+
const runCall = async (call, approved) => {
|
|
59
|
+
if (!approved) {
|
|
60
|
+
if (ctx.stream) {
|
|
61
|
+
ctx.stream({
|
|
62
|
+
type: "tool_error",
|
|
63
|
+
call,
|
|
64
|
+
error: "Tool execution denied by user",
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
call,
|
|
69
|
+
result: { error: "Tool execution denied by user" },
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const toolName = call.function.name;
|
|
73
|
+
const limits = ctx.toolLimits || {};
|
|
74
|
+
const maxCalls = limits[toolName];
|
|
75
|
+
const currentCount = updatedCounts[toolName] || 0;
|
|
76
|
+
if (maxCalls && currentCount >= maxCalls) {
|
|
77
|
+
const error = `Tool ${toolName} has reached its limit of ${maxCalls} calls`;
|
|
78
|
+
if (ctx.stream) {
|
|
79
|
+
ctx.stream({ type: "tool_error", call, error });
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
call,
|
|
83
|
+
result: { error },
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
updatedCounts[toolName] = currentCount + 1;
|
|
87
|
+
if (ctx.stream) {
|
|
88
|
+
ctx.stream({ type: "tool_executing", call });
|
|
89
|
+
}
|
|
90
|
+
let lastError;
|
|
91
|
+
for (let i = 0; i <= retryCount; i++) {
|
|
92
|
+
try {
|
|
93
|
+
const executor = ctx.toolExecutors?.[call.function.name];
|
|
94
|
+
if (!executor) {
|
|
95
|
+
throw new Error(`Tool executor not found: ${call.function.name}`);
|
|
96
|
+
}
|
|
97
|
+
let args = {};
|
|
98
|
+
try {
|
|
99
|
+
args = call.function.arguments
|
|
100
|
+
? JSON.parse(call.function.arguments)
|
|
101
|
+
: {};
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
throw new Error(`Invalid JSON arguments for tool ${call.function.name}: ${call.function.arguments}`);
|
|
105
|
+
}
|
|
106
|
+
const result = await executor(args);
|
|
107
|
+
if (ctx.stream) {
|
|
108
|
+
ctx.stream({ type: "tool_complete", call, result });
|
|
109
|
+
}
|
|
110
|
+
return { call, result };
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
lastError = e;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const error = lastError.message;
|
|
117
|
+
if (ctx.stream) {
|
|
118
|
+
ctx.stream({ type: "tool_error", call, error });
|
|
119
|
+
}
|
|
120
|
+
return { call, result: { error } };
|
|
121
|
+
};
|
|
122
|
+
if (executeOnApproval && requireApproval) {
|
|
123
|
+
const resultPromises = calls.map(async (call) => {
|
|
124
|
+
let approved;
|
|
125
|
+
if (approvalCallback) {
|
|
126
|
+
approved = await approvalCallback(call);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
const response = await requestApproval(call, approvalId);
|
|
130
|
+
approved = response.approved;
|
|
131
|
+
}
|
|
132
|
+
return runCall(call, approved);
|
|
133
|
+
});
|
|
134
|
+
const results = await Promise.all(resultPromises);
|
|
135
|
+
return {
|
|
136
|
+
...ctx,
|
|
137
|
+
history: [
|
|
138
|
+
...ctx.history,
|
|
139
|
+
...results.map(({ call, result }) => ({
|
|
140
|
+
role: "tool",
|
|
141
|
+
tool_call_id: call.id,
|
|
142
|
+
content: JSON.stringify(result),
|
|
143
|
+
})),
|
|
144
|
+
],
|
|
145
|
+
toolCallCounts: updatedCounts,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const approvalPromises = calls.map(async (call) => {
|
|
149
|
+
if (requireApproval) {
|
|
150
|
+
let approved;
|
|
151
|
+
if (approvalCallback) {
|
|
152
|
+
approved = await approvalCallback(call);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const response = await requestApproval(call, approvalId);
|
|
156
|
+
approved = response.approved;
|
|
157
|
+
}
|
|
158
|
+
return { call, approved };
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
return { call, approved: true };
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const approvals = await Promise.all(approvalPromises);
|
|
165
|
+
const runCallWithApproval = async (call) => {
|
|
166
|
+
const approval = approvals.find((a) => a.call.id === call.id);
|
|
167
|
+
return runCall(call, approval?.approved ?? true);
|
|
168
|
+
};
|
|
169
|
+
const results = parallel
|
|
170
|
+
? await Promise.all(calls.map(runCallWithApproval))
|
|
171
|
+
: await runCallsSequentially(calls, runCallWithApproval);
|
|
172
|
+
return {
|
|
173
|
+
...ctx,
|
|
174
|
+
history: [
|
|
175
|
+
...ctx.history,
|
|
176
|
+
...results.map(({ call, result }) => ({
|
|
177
|
+
role: "tool",
|
|
178
|
+
tool_call_id: call.id,
|
|
179
|
+
content: JSON.stringify(result),
|
|
180
|
+
})),
|
|
181
|
+
],
|
|
182
|
+
toolCallCounts: updatedCounts,
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
const runCallsSequentially = async (calls, runCall) => {
|
|
186
|
+
const results = [];
|
|
187
|
+
for (const call of calls) {
|
|
188
|
+
results.push(await runCall(call));
|
|
189
|
+
}
|
|
190
|
+
return results;
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/composition/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/composition/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,YAAY,EAAE,MAAM,UAAU,CAAC;AAE3E;;GAEG;AACH,eAAO,MAAM,KAAK,GAChB,WAAe,YAAY,YAAK,EAChC,MAAM,YAAY,KACjB,YAcF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* scope({}, retry({ times: 2 }, model(...)))
|
|
3
|
+
*/
|
|
4
|
+
export const retry = ({ times = 3 } = {}, step) => {
|
|
5
|
+
return async (ctx) => {
|
|
6
|
+
let err;
|
|
7
|
+
for (let i = 0; i < times; i++) {
|
|
8
|
+
try {
|
|
9
|
+
return await step(ctx);
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
err = e;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
throw err;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/composition/retry.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,EAAE,KAAK,GAAG,CAAC,KAAmB,EAAE,EAChC,IAAkB,EACJ,EAAE;IAChB,OAAO,KAAK,EAAE,GAAwB,EAAgC,EAAE;QACtE,IAAI,GAAU,CAAC;QAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,GAAG,GAAG,CAAU,CAAC;YACnB,CAAC;QACH,CAAC;QAED,MAAM,GAAI,CAAC;IACb,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/composition/scope.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,WAAW,EACX,YAAY,EACb,MAAM,UAAU,CAAC;AAmFlB,eAAO,MAAM,KAAK,GAChB,QAAQ,WAAW,EACnB,GAAG,OAAO,YAAY,EAAE,KACvB,YAqBF,CAAC"}
|