@threaded/ai 1.0.29 → 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.
Files changed (112) hide show
  1. package/README.md +240 -0
  2. package/dist/approval.d.ts +18 -0
  3. package/dist/approval.d.ts.map +1 -0
  4. package/dist/approval.js +35 -0
  5. package/dist/approval.js.map +1 -0
  6. package/dist/composition/compose.d.ts +3 -0
  7. package/dist/composition/compose.d.ts.map +1 -0
  8. package/dist/composition/compose.js +38 -0
  9. package/dist/composition/compose.js.map +1 -0
  10. package/dist/composition/model.d.ts +9 -0
  11. package/dist/composition/model.d.ts.map +1 -0
  12. package/dist/composition/model.js +192 -0
  13. package/dist/composition/model.js.map +1 -0
  14. package/dist/composition/retry.d.ts +6 -0
  15. package/dist/composition/retry.d.ts.map +1 -0
  16. package/dist/composition/retry.js +18 -0
  17. package/dist/composition/retry.js.map +1 -0
  18. package/dist/composition/scope.d.ts +3 -0
  19. package/dist/composition/scope.d.ts.map +1 -0
  20. package/dist/composition/scope.js +83 -0
  21. package/dist/composition/scope.js.map +1 -0
  22. package/dist/composition/tap.d.ts +3 -0
  23. package/dist/composition/tap.d.ts.map +1 -0
  24. package/dist/composition/tap.js +7 -0
  25. package/dist/composition/tap.js.map +1 -0
  26. package/dist/composition/when.d.ts +3 -0
  27. package/dist/composition/when.d.ts.map +1 -0
  28. package/dist/composition/when.js +9 -0
  29. package/dist/composition/when.js.map +1 -0
  30. package/dist/embed.d.ts +16 -0
  31. package/dist/embed.d.ts.map +1 -0
  32. package/dist/embed.js +72 -0
  33. package/dist/embed.js.map +1 -0
  34. package/dist/examples.d.ts +2 -0
  35. package/dist/examples.d.ts.map +1 -0
  36. package/dist/examples.js +6 -0
  37. package/dist/examples.js.map +1 -0
  38. package/dist/helpers.d.ts +17 -0
  39. package/dist/helpers.d.ts.map +1 -0
  40. package/dist/helpers.js +104 -0
  41. package/dist/helpers.js.map +1 -0
  42. package/dist/image-model-schema.d.ts +19 -0
  43. package/dist/image-model-schema.d.ts.map +1 -0
  44. package/dist/image-model-schema.js +103 -0
  45. package/dist/image-model-schema.js.map +1 -0
  46. package/dist/image.d.ts +3 -0
  47. package/dist/image.d.ts.map +1 -0
  48. package/dist/image.js +120 -0
  49. package/dist/image.js.map +1 -0
  50. package/dist/index.d.ts +18 -350
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +17 -2061
  53. package/dist/index.js.map +1 -1
  54. package/dist/mcp.d.ts +3 -0
  55. package/dist/mcp.d.ts.map +1 -0
  56. package/dist/mcp.js +29 -0
  57. package/dist/mcp.js.map +1 -0
  58. package/dist/providers/anthropic.d.ts +3 -0
  59. package/dist/providers/anthropic.d.ts.map +1 -0
  60. package/dist/providers/anthropic.js +226 -0
  61. package/dist/providers/anthropic.js.map +1 -0
  62. package/dist/providers/google.d.ts +3 -0
  63. package/dist/providers/google.d.ts.map +1 -0
  64. package/dist/providers/google.js +244 -0
  65. package/dist/providers/google.js.map +1 -0
  66. package/dist/providers/huggingface.d.ts +3 -0
  67. package/dist/providers/huggingface.d.ts.map +1 -0
  68. package/dist/providers/huggingface.js +59 -0
  69. package/dist/providers/huggingface.js.map +1 -0
  70. package/dist/providers/index.d.ts +3 -0
  71. package/dist/providers/index.d.ts.map +1 -0
  72. package/dist/providers/index.js +29 -0
  73. package/dist/providers/index.js.map +1 -0
  74. package/dist/providers/local.d.ts +3 -0
  75. package/dist/providers/local.d.ts.map +1 -0
  76. package/dist/providers/local.js +152 -0
  77. package/dist/providers/local.js.map +1 -0
  78. package/dist/providers/openai.d.ts +3 -0
  79. package/dist/providers/openai.d.ts.map +1 -0
  80. package/dist/providers/openai.js +165 -0
  81. package/dist/providers/openai.js.map +1 -0
  82. package/dist/providers/xai.d.ts +3 -0
  83. package/dist/providers/xai.d.ts.map +1 -0
  84. package/dist/providers/xai.js +161 -0
  85. package/dist/providers/xai.js.map +1 -0
  86. package/dist/schema.d.ts +7 -0
  87. package/dist/schema.d.ts.map +1 -0
  88. package/dist/schema.js +44 -0
  89. package/dist/schema.js.map +1 -0
  90. package/dist/thread.d.ts +25 -0
  91. package/dist/thread.d.ts.map +1 -0
  92. package/dist/thread.js +87 -0
  93. package/dist/thread.js.map +1 -0
  94. package/dist/types.d.ts +193 -0
  95. package/dist/types.d.ts.map +1 -0
  96. package/dist/types.js +8 -0
  97. package/dist/types.js.map +1 -0
  98. package/dist/utils/rateLimited.d.ts +27 -0
  99. package/dist/utils/rateLimited.d.ts.map +1 -0
  100. package/dist/utils/rateLimited.js +74 -0
  101. package/dist/utils/rateLimited.js.map +1 -0
  102. package/dist/utils.d.ts +8 -0
  103. package/dist/utils.d.ts.map +1 -0
  104. package/dist/utils.js +78 -0
  105. package/dist/utils.js.map +1 -0
  106. package/package.json +34 -12
  107. package/.claude/settings.local.json +0 -15
  108. package/.lore +0 -65
  109. package/dist/index.cjs +0 -2137
  110. package/dist/index.cjs.map +0 -1
  111. package/dist/index.d.cts +0 -350
  112. 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"}
@@ -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,3 @@
1
+ import { ComposedFunction, StepFunction } from "../types";
2
+ export declare const compose: (...steps: StepFunction[]) => ComposedFunction;
3
+ //# sourceMappingURL=compose.d.ts.map
@@ -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,6 @@
1
+ import { StepFunction, RetryOptions } from "../types";
2
+ /**
3
+ * scope({}, retry({ times: 2 }, model(...)))
4
+ */
5
+ export declare const retry: ({ times }: RetryOptions | undefined, step: StepFunction) => StepFunction;
6
+ //# sourceMappingURL=retry.d.ts.map
@@ -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,3 @@
1
+ import { ScopeConfig, StepFunction } from "../types";
2
+ export declare const scope: (config: ScopeConfig, ...steps: StepFunction[]) => StepFunction;
3
+ //# sourceMappingURL=scope.d.ts.map
@@ -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"}