ai-functions 2.1.3 → 2.4.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +90 -1
- package/README.md +38 -0
- package/dist/ai-promise.d.ts +3 -3
- package/dist/ai-promise.d.ts.map +1 -1
- package/dist/ai-promise.js +135 -64
- package/dist/ai-promise.js.map +1 -1
- package/dist/ai-schemas.d.ts +56 -0
- package/dist/ai-schemas.d.ts.map +1 -0
- package/dist/ai-schemas.js +53 -0
- package/dist/ai-schemas.js.map +1 -0
- package/dist/ai.d.ts +16 -242
- package/dist/ai.d.ts.map +1 -1
- package/dist/ai.js +51 -858
- package/dist/ai.js.map +1 -1
- package/dist/batch/anthropic.d.ts +6 -4
- package/dist/batch/anthropic.d.ts.map +1 -1
- package/dist/batch/anthropic.js +83 -145
- package/dist/batch/anthropic.js.map +1 -1
- package/dist/batch/bedrock.d.ts +8 -30
- package/dist/batch/bedrock.d.ts.map +1 -1
- package/dist/batch/bedrock.js +155 -338
- package/dist/batch/bedrock.js.map +1 -1
- package/dist/batch/cloudflare.d.ts +8 -20
- package/dist/batch/cloudflare.d.ts.map +1 -1
- package/dist/batch/cloudflare.js +68 -189
- package/dist/batch/cloudflare.js.map +1 -1
- package/dist/batch/google.d.ts +6 -20
- package/dist/batch/google.d.ts.map +1 -1
- package/dist/batch/google.js +70 -238
- package/dist/batch/google.js.map +1 -1
- package/dist/batch/index.d.ts +4 -1
- package/dist/batch/index.d.ts.map +1 -1
- package/dist/batch/index.js +4 -1
- package/dist/batch/index.js.map +1 -1
- package/dist/batch/memory.d.ts +1 -1
- package/dist/batch/memory.d.ts.map +1 -1
- package/dist/batch/memory.js +14 -10
- package/dist/batch/memory.js.map +1 -1
- package/dist/batch/openai.d.ts +11 -14
- package/dist/batch/openai.d.ts.map +1 -1
- package/dist/batch/openai.js +52 -156
- package/dist/batch/openai.js.map +1 -1
- package/dist/batch/provider.d.ts +111 -0
- package/dist/batch/provider.d.ts.map +1 -0
- package/dist/batch/provider.js +233 -0
- package/dist/batch/provider.js.map +1 -0
- package/dist/batch-map.d.ts.map +1 -1
- package/dist/batch-map.js +23 -17
- package/dist/batch-map.js.map +1 -1
- package/dist/batch-queue.d.ts +65 -0
- package/dist/batch-queue.d.ts.map +1 -1
- package/dist/batch-queue.js +169 -14
- package/dist/batch-queue.js.map +1 -1
- package/dist/budget.d.ts.map +1 -1
- package/dist/budget.js +27 -14
- package/dist/budget.js.map +1 -1
- package/dist/cache.d.ts +23 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +36 -15
- package/dist/cache.js.map +1 -1
- package/dist/context.d.ts +26 -8
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +64 -62
- package/dist/context.js.map +1 -1
- package/dist/digital-objects-registry.d.ts +229 -0
- package/dist/digital-objects-registry.d.ts.map +1 -0
- package/dist/digital-objects-registry.js +617 -0
- package/dist/digital-objects-registry.js.map +1 -0
- package/dist/embeddings.d.ts +2 -2
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +35 -0
- package/dist/errors.js.map +1 -0
- package/dist/eval/runner.d.ts +8 -0
- package/dist/eval/runner.d.ts.map +1 -1
- package/dist/eval/runner.js +41 -35
- package/dist/eval/runner.js.map +1 -1
- package/dist/eval-log/in-memory.d.ts +34 -0
- package/dist/eval-log/in-memory.d.ts.map +1 -0
- package/dist/eval-log/in-memory.js +84 -0
- package/dist/eval-log/in-memory.js.map +1 -0
- package/dist/eval-log/index.d.ts +29 -0
- package/dist/eval-log/index.d.ts.map +1 -0
- package/dist/eval-log/index.js +39 -0
- package/dist/eval-log/index.js.map +1 -0
- package/dist/eval-log/types.d.ts +101 -0
- package/dist/eval-log/types.d.ts.map +1 -0
- package/dist/eval-log/types.js +16 -0
- package/dist/eval-log/types.js.map +1 -0
- package/dist/function-registry.d.ts +176 -0
- package/dist/function-registry.d.ts.map +1 -0
- package/dist/function-registry.js +685 -0
- package/dist/function-registry.js.map +1 -0
- package/dist/generate.d.ts +9 -3
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +18 -18
- package/dist/generate.js.map +1 -1
- package/dist/index.d.ts +18 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -18
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +118 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +187 -0
- package/dist/logger.js.map +1 -0
- package/dist/middleware/budget.d.ts +84 -0
- package/dist/middleware/budget.d.ts.map +1 -0
- package/dist/middleware/budget.js +110 -0
- package/dist/middleware/budget.js.map +1 -0
- package/dist/middleware/cache.d.ts +103 -0
- package/dist/middleware/cache.d.ts.map +1 -0
- package/dist/middleware/cache.js +228 -0
- package/dist/middleware/cache.js.map +1 -0
- package/dist/middleware/embed-cache.d.ts +99 -0
- package/dist/middleware/embed-cache.d.ts.map +1 -0
- package/dist/middleware/embed-cache.js +128 -0
- package/dist/middleware/embed-cache.js.map +1 -0
- package/dist/middleware/index.d.ts +11 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +11 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/trace.d.ts +103 -0
- package/dist/middleware/trace.d.ts.map +1 -0
- package/dist/middleware/trace.js +176 -0
- package/dist/middleware/trace.js.map +1 -0
- package/dist/primitives.d.ts +120 -1
- package/dist/primitives.d.ts.map +1 -1
- package/dist/primitives.js +398 -26
- package/dist/primitives.js.map +1 -1
- package/dist/retry.d.ts +66 -1
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +115 -8
- package/dist/retry.js.map +1 -1
- package/dist/sandbox.d.ts +36 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +44 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/schema.js +2 -2
- package/dist/schema.js.map +1 -1
- package/dist/telemetry.d.ts +128 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +285 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/template.d.ts.map +1 -1
- package/dist/template.js +6 -1
- package/dist/template.js.map +1 -1
- package/dist/tool-orchestration.d.ts +66 -4
- package/dist/tool-orchestration.d.ts.map +1 -1
- package/dist/tool-orchestration.js +123 -23
- package/dist/tool-orchestration.js.map +1 -1
- package/dist/type-guards.d.ts +28 -0
- package/dist/type-guards.d.ts.map +1 -0
- package/dist/type-guards.js +29 -0
- package/dist/type-guards.js.map +1 -0
- package/dist/types.d.ts +155 -19
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +36 -1
- package/dist/types.js.map +1 -1
- package/dist/wrap-for-v3.d.ts +80 -0
- package/dist/wrap-for-v3.d.ts.map +1 -0
- package/dist/wrap-for-v3.js +89 -0
- package/dist/wrap-for-v3.js.map +1 -0
- package/examples/00-quickstart.ts +232 -0
- package/examples/01-rag-chatbot.ts +212 -0
- package/examples/02-multi-agent-research.ts +290 -0
- package/examples/03-email-classification.ts +379 -0
- package/examples/04-content-moderation.ts +400 -0
- package/examples/05-document-extraction.ts +455 -0
- package/examples/06-streaming-chat-nextjs.ts +437 -0
- package/examples/07-cloudflare-worker.ts +483 -0
- package/examples/08-batch-processing.ts +491 -0
- package/examples/09-budget-constrained.ts +527 -0
- package/examples/10-tool-orchestration.ts +565 -0
- package/examples/11-retry-resilience.ts +403 -0
- package/examples/12-caching-strategies.ts +422 -0
- package/examples/README.md +145 -0
- package/package.json +29 -25
- package/src/ai-promise.ts +226 -140
- package/src/ai-schemas.ts +122 -0
- package/src/ai.ts +71 -1176
- package/src/batch/anthropic.ts +96 -161
- package/src/batch/bedrock.ts +203 -454
- package/src/batch/cloudflare.ts +99 -282
- package/src/batch/google.ts +91 -297
- package/src/batch/index.ts +4 -1
- package/src/batch/memory.ts +15 -10
- package/src/batch/openai.ts +65 -193
- package/src/batch/provider.ts +336 -0
- package/src/batch-map.ts +29 -24
- package/src/batch-queue.ts +200 -11
- package/src/budget.ts +31 -18
- package/src/cache.ts +45 -17
- package/src/context.ts +106 -77
- package/src/digital-objects-registry.ts +750 -0
- package/src/errors.ts +37 -0
- package/src/eval/runner.ts +60 -36
- package/src/eval-log/in-memory.ts +90 -0
- package/src/eval-log/index.ts +46 -0
- package/src/eval-log/types.ts +110 -0
- package/src/function-registry.ts +874 -0
- package/src/generate.ts +33 -28
- package/src/index.ts +122 -21
- package/src/logger.ts +232 -0
- package/src/middleware/budget.ts +171 -0
- package/src/middleware/cache.ts +299 -0
- package/src/middleware/embed-cache.ts +195 -0
- package/src/middleware/index.ts +23 -0
- package/src/middleware/trace.ts +248 -0
- package/src/primitives.ts +589 -62
- package/src/retry.ts +144 -18
- package/src/sandbox.ts +52 -0
- package/src/schema.ts +8 -8
- package/src/telemetry.ts +403 -0
- package/src/template.ts +8 -4
- package/src/tool-orchestration.ts +213 -48
- package/src/type-guards.ts +31 -0
- package/src/types.ts +186 -27
- package/src/wrap-for-v3.ts +105 -0
- package/test/ai-promise.test.ts +1080 -0
- package/test/ai-proxy.test.ts +1 -1
- package/test/batch-autosubmit-errors.test.ts +49 -37
- package/test/batch-blog-posts.test.ts +87 -129
- package/test/core-functions.test.ts +183 -579
- package/test/decide.test.ts +154 -322
- package/test/define.test.ts +211 -8
- package/test/digital-objects-registry.test.ts +760 -0
- package/test/embedding-cache-middleware.test.ts +140 -0
- package/test/fill-template.test.ts +89 -0
- package/test/generate-core.test.ts +140 -229
- package/test/implicit-batch.test.ts +22 -65
- package/test/retry-policy-integration.test.ts +117 -0
- package/test/sandbox-execution.test.ts +155 -0
- package/test/schema.test.ts +55 -19
- package/test/template.test.ts +1164 -0
- package/test/tool-orchestration.test.ts +270 -0
- package/test/wrap-for-v3.test.ts +612 -0
- package/vitest.config.js +6 -0
- package/vitest.config.ts +20 -0
- package/LICENSE +0 -21
- package/dist/rpc/auth.d.ts +0 -69
- package/dist/rpc/auth.d.ts.map +0 -1
- package/dist/rpc/auth.js +0 -136
- package/dist/rpc/auth.js.map +0 -1
- package/dist/rpc/client.d.ts +0 -62
- package/dist/rpc/client.d.ts.map +0 -1
- package/dist/rpc/client.js +0 -103
- package/dist/rpc/client.js.map +0 -1
- package/dist/rpc/deferred.d.ts +0 -60
- package/dist/rpc/deferred.d.ts.map +0 -1
- package/dist/rpc/deferred.js +0 -96
- package/dist/rpc/deferred.js.map +0 -1
- package/dist/rpc/index.d.ts +0 -22
- package/dist/rpc/index.d.ts.map +0 -1
- package/dist/rpc/index.js +0 -38
- package/dist/rpc/index.js.map +0 -1
- package/dist/rpc/local.d.ts +0 -42
- package/dist/rpc/local.d.ts.map +0 -1
- package/dist/rpc/local.js +0 -50
- package/dist/rpc/local.js.map +0 -1
- package/dist/rpc/server.d.ts +0 -165
- package/dist/rpc/server.d.ts.map +0 -1
- package/dist/rpc/server.js +0 -405
- package/dist/rpc/server.js.map +0 -1
- package/dist/rpc/session.d.ts +0 -32
- package/dist/rpc/session.d.ts.map +0 -1
- package/dist/rpc/session.js +0 -43
- package/dist/rpc/session.js.map +0 -1
- package/dist/rpc/transport.d.ts +0 -306
- package/dist/rpc/transport.d.ts.map +0 -1
- package/dist/rpc/transport.js +0 -731
- package/dist/rpc/transport.js.map +0 -1
- package/src/batch/anthropic.js +0 -256
- package/src/batch/bedrock.js +0 -584
- package/src/batch/cloudflare.js +0 -287
- package/src/batch/google.js +0 -359
- package/src/batch/index.js +0 -30
- package/src/batch/memory.js +0 -187
- package/src/batch/openai.js +0 -402
- package/src/eval/index.js +0 -7
- package/src/eval/models.js +0 -119
- package/src/eval/runner.js +0 -147
- package/test/schema.test.js +0 -96
package/src/primitives.ts
CHANGED
|
@@ -39,7 +39,23 @@ import {
|
|
|
39
39
|
} from './ai-promise.js'
|
|
40
40
|
import { generateObject, generateText } from './generate.js'
|
|
41
41
|
import type { SimpleSchema } from './schema.js'
|
|
42
|
-
import type {
|
|
42
|
+
import type {
|
|
43
|
+
AgenticFunctionDefinition,
|
|
44
|
+
AutoDefineResult,
|
|
45
|
+
CodeFunctionDefinition,
|
|
46
|
+
DefinedFunction,
|
|
47
|
+
FunctionDefinition,
|
|
48
|
+
FunctionRegistry,
|
|
49
|
+
GenerativeFunctionDefinition,
|
|
50
|
+
HumanChannel,
|
|
51
|
+
HumanFunctionDefinition,
|
|
52
|
+
} from './types.js'
|
|
53
|
+
import {
|
|
54
|
+
createDefinedFunction,
|
|
55
|
+
defineFunction,
|
|
56
|
+
functions,
|
|
57
|
+
generateCode,
|
|
58
|
+
} from './function-registry.js'
|
|
43
59
|
|
|
44
60
|
// ============================================================================
|
|
45
61
|
// Types
|
|
@@ -122,42 +138,77 @@ export async function generate(
|
|
|
122
138
|
}
|
|
123
139
|
|
|
124
140
|
// Helper functions
|
|
125
|
-
async function generateTextContent(
|
|
126
|
-
|
|
141
|
+
async function generateTextContent(
|
|
142
|
+
prompt: string,
|
|
143
|
+
model: string,
|
|
144
|
+
options: GenerateOptions
|
|
145
|
+
): Promise<string> {
|
|
146
|
+
const result = await generateText({
|
|
147
|
+
model,
|
|
148
|
+
prompt,
|
|
149
|
+
...(options.system !== undefined && { system: options.system }),
|
|
150
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
151
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
152
|
+
})
|
|
127
153
|
return result.text
|
|
128
154
|
}
|
|
129
155
|
|
|
130
|
-
async function generateJsonContent(
|
|
156
|
+
async function generateJsonContent(
|
|
157
|
+
prompt: string,
|
|
158
|
+
model: string,
|
|
159
|
+
schema: SimpleSchema | undefined,
|
|
160
|
+
options: GenerateOptions
|
|
161
|
+
): Promise<unknown> {
|
|
131
162
|
const effectiveSchema = schema || { result: 'The generated result' }
|
|
132
|
-
const result = await generateObject({
|
|
163
|
+
const result = await generateObject({
|
|
164
|
+
model,
|
|
165
|
+
schema: effectiveSchema,
|
|
166
|
+
prompt,
|
|
167
|
+
...(options.system !== undefined && { system: options.system }),
|
|
168
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
169
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
170
|
+
})
|
|
133
171
|
return result.object
|
|
134
172
|
}
|
|
135
173
|
|
|
136
|
-
async function generateCodeContent(
|
|
174
|
+
async function generateCodeContent(
|
|
175
|
+
prompt: string,
|
|
176
|
+
model: string,
|
|
177
|
+
language: string,
|
|
178
|
+
options: GenerateOptions
|
|
179
|
+
): Promise<string> {
|
|
137
180
|
const result = await generateObject({
|
|
138
181
|
model,
|
|
139
182
|
schema: { code: `The ${language} implementation code` },
|
|
140
183
|
prompt: `Generate ${language} code for: ${prompt}`,
|
|
141
184
|
system: `You are an expert ${language} developer. Generate clean, well-documented code.`,
|
|
142
|
-
temperature: options.temperature,
|
|
143
|
-
maxTokens: options.maxTokens,
|
|
185
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
186
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
144
187
|
})
|
|
145
188
|
return (result.object as { code: string }).code
|
|
146
189
|
}
|
|
147
190
|
|
|
148
|
-
async function generateListContent(
|
|
191
|
+
async function generateListContent(
|
|
192
|
+
prompt: string,
|
|
193
|
+
model: string,
|
|
194
|
+
options: GenerateOptions
|
|
195
|
+
): Promise<string[]> {
|
|
149
196
|
const result = await generateObject({
|
|
150
197
|
model,
|
|
151
198
|
schema: { items: ['List items'] },
|
|
152
199
|
prompt,
|
|
153
200
|
system: options.system || 'Generate a list of items based on the prompt.',
|
|
154
|
-
temperature: options.temperature,
|
|
155
|
-
maxTokens: options.maxTokens,
|
|
201
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
202
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
156
203
|
})
|
|
157
204
|
return (result.object as { items: string[] }).items
|
|
158
205
|
}
|
|
159
206
|
|
|
160
|
-
async function generateListsContent(
|
|
207
|
+
async function generateListsContent(
|
|
208
|
+
prompt: string,
|
|
209
|
+
model: string,
|
|
210
|
+
options: GenerateOptions
|
|
211
|
+
): Promise<Record<string, string[]>> {
|
|
161
212
|
const result = await generateObject({
|
|
162
213
|
model,
|
|
163
214
|
schema: {
|
|
@@ -165,9 +216,11 @@ async function generateListsContent(prompt: string, model: string, options: Gene
|
|
|
165
216
|
data: 'JSON string containing the categorized lists',
|
|
166
217
|
},
|
|
167
218
|
prompt: `Generate categorized lists for: ${prompt}\n\nFirst identify appropriate category names, then provide the lists as a JSON object.`,
|
|
168
|
-
system:
|
|
169
|
-
|
|
170
|
-
|
|
219
|
+
system:
|
|
220
|
+
options.system ||
|
|
221
|
+
'Generate multiple categorized lists. Determine appropriate categories based on the prompt.',
|
|
222
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
223
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
171
224
|
})
|
|
172
225
|
const obj = result.object as { categories: string[]; data: string }
|
|
173
226
|
try {
|
|
@@ -181,79 +234,114 @@ async function generateListsContent(prompt: string, model: string, options: Gene
|
|
|
181
234
|
}
|
|
182
235
|
}
|
|
183
236
|
|
|
184
|
-
async function generateBooleanContent(
|
|
237
|
+
async function generateBooleanContent(
|
|
238
|
+
prompt: string,
|
|
239
|
+
model: string,
|
|
240
|
+
options: GenerateOptions
|
|
241
|
+
): Promise<boolean> {
|
|
185
242
|
const result = await generateObject({
|
|
186
243
|
model,
|
|
187
244
|
schema: { answer: 'true | false' },
|
|
188
245
|
prompt,
|
|
189
246
|
system: options.system || 'Answer the question with true or false.',
|
|
190
247
|
temperature: options.temperature ?? 0,
|
|
191
|
-
maxTokens: options.maxTokens,
|
|
248
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
192
249
|
})
|
|
193
250
|
return (result.object as { answer: string }).answer === 'true'
|
|
194
251
|
}
|
|
195
252
|
|
|
196
|
-
async function generateSummaryContent(
|
|
253
|
+
async function generateSummaryContent(
|
|
254
|
+
prompt: string,
|
|
255
|
+
model: string,
|
|
256
|
+
options: GenerateOptions
|
|
257
|
+
): Promise<string> {
|
|
197
258
|
const result = await generateObject({
|
|
198
259
|
model,
|
|
199
260
|
schema: { summary: 'A concise summary of the content' },
|
|
200
261
|
prompt: `Summarize the following:\n\n${prompt}`,
|
|
201
262
|
system: options.system || 'Create a clear, concise summary.',
|
|
202
|
-
temperature: options.temperature,
|
|
203
|
-
maxTokens: options.maxTokens,
|
|
263
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
264
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
204
265
|
})
|
|
205
266
|
return (result.object as { summary: string }).summary
|
|
206
267
|
}
|
|
207
268
|
|
|
208
|
-
async function generateExtractContent(
|
|
209
|
-
|
|
269
|
+
async function generateExtractContent(
|
|
270
|
+
prompt: string,
|
|
271
|
+
model: string,
|
|
272
|
+
schema: SimpleSchema | undefined,
|
|
273
|
+
options: GenerateOptions
|
|
274
|
+
): Promise<unknown[]> {
|
|
275
|
+
const effectiveSchema = schema || {
|
|
276
|
+
items: ['Array of extracted items as strings - extract ALL matching items from the text'],
|
|
277
|
+
}
|
|
210
278
|
const result = await generateObject({
|
|
211
279
|
model,
|
|
212
280
|
schema: effectiveSchema,
|
|
213
|
-
prompt: `Extract from the
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
281
|
+
prompt: `Extract the following from the text below. Return ALL matching items in the items array.
|
|
282
|
+
|
|
283
|
+
Task: ${prompt}
|
|
284
|
+
|
|
285
|
+
IMPORTANT: Return the extracted items as an array. If the task asks for email addresses, return all email addresses found. If it asks for names, return all names found. Do not return an empty array if there are items to extract.`,
|
|
286
|
+
system:
|
|
287
|
+
options.system ||
|
|
288
|
+
'You are a precise data extraction assistant. Extract exactly what is requested and return it as an array of items. Be thorough - find ALL matching items in the text.',
|
|
289
|
+
temperature: options.temperature ?? 0, // Use low temperature for extraction tasks
|
|
290
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
217
291
|
})
|
|
218
292
|
const obj = result.object as Record<string, unknown>
|
|
219
|
-
if ('items' in obj && Array.isArray(obj
|
|
220
|
-
return obj
|
|
293
|
+
if ('items' in obj && Array.isArray(obj['items'])) {
|
|
294
|
+
return obj['items']
|
|
221
295
|
}
|
|
222
296
|
return Object.values(obj).flat() as unknown[]
|
|
223
297
|
}
|
|
224
298
|
|
|
225
|
-
async function generateYamlContent(
|
|
299
|
+
async function generateYamlContent(
|
|
300
|
+
prompt: string,
|
|
301
|
+
model: string,
|
|
302
|
+
options: GenerateOptions
|
|
303
|
+
): Promise<string> {
|
|
226
304
|
const result = await generateObject({
|
|
227
305
|
model,
|
|
228
306
|
schema: { yaml: 'The YAML content' },
|
|
229
307
|
prompt: `Generate YAML for: ${prompt}`,
|
|
230
308
|
system: options.system || 'Generate valid YAML content.',
|
|
231
|
-
temperature: options.temperature,
|
|
232
|
-
maxTokens: options.maxTokens,
|
|
309
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
310
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
233
311
|
})
|
|
234
312
|
return (result.object as { yaml: string }).yaml
|
|
235
313
|
}
|
|
236
314
|
|
|
237
|
-
async function generateDiagramContent(
|
|
315
|
+
async function generateDiagramContent(
|
|
316
|
+
prompt: string,
|
|
317
|
+
model: string,
|
|
318
|
+
format: string,
|
|
319
|
+
options: GenerateOptions
|
|
320
|
+
): Promise<string> {
|
|
238
321
|
const result = await generateObject({
|
|
239
322
|
model,
|
|
240
323
|
schema: { diagram: `The ${format} diagram code` },
|
|
241
324
|
prompt: `Generate a ${format} diagram for: ${prompt}`,
|
|
242
325
|
system: options.system || `Generate ${format} diagram syntax.`,
|
|
243
|
-
temperature: options.temperature,
|
|
244
|
-
maxTokens: options.maxTokens,
|
|
326
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
327
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
245
328
|
})
|
|
246
329
|
return (result.object as { diagram: string }).diagram
|
|
247
330
|
}
|
|
248
331
|
|
|
249
|
-
async function generateSlidesContent(
|
|
332
|
+
async function generateSlidesContent(
|
|
333
|
+
prompt: string,
|
|
334
|
+
model: string,
|
|
335
|
+
slideCount: number,
|
|
336
|
+
options: GenerateOptions
|
|
337
|
+
): Promise<string> {
|
|
250
338
|
const result = await generateObject({
|
|
251
339
|
model,
|
|
252
340
|
schema: { slides: `Slidev/Marp markdown with ${slideCount} slides` },
|
|
253
341
|
prompt: `Generate a ${slideCount}-slide presentation about: ${prompt}`,
|
|
254
342
|
system: options.system || 'Generate markdown slides in Slidev/Marp format.',
|
|
255
|
-
temperature: options.temperature,
|
|
256
|
-
maxTokens: options.maxTokens,
|
|
343
|
+
...(options.temperature !== undefined && { temperature: options.temperature }),
|
|
344
|
+
...(options.maxTokens !== undefined && { maxTokens: options.maxTokens }),
|
|
257
345
|
})
|
|
258
346
|
return (result.object as { slides: string }).slides
|
|
259
347
|
}
|
|
@@ -445,17 +533,14 @@ function doImpl(
|
|
|
445
533
|
prompt = promptOrStrings as string
|
|
446
534
|
}
|
|
447
535
|
|
|
448
|
-
const promise = new AIPromise<{ summary: string; actions: string[] }>(
|
|
449
|
-
|
|
450
|
-
{
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
system: 'You are a task executor. Describe what actions you would take.',
|
|
457
|
-
}
|
|
458
|
-
)
|
|
536
|
+
const promise = new AIPromise<{ summary: string; actions: string[] }>(prompt, {
|
|
537
|
+
type: 'object',
|
|
538
|
+
baseSchema: {
|
|
539
|
+
summary: 'Summary of what was done',
|
|
540
|
+
actions: ['List of actions taken'],
|
|
541
|
+
},
|
|
542
|
+
system: 'You are a task executor. Describe what actions you would take.',
|
|
543
|
+
})
|
|
459
544
|
|
|
460
545
|
for (const dep of dependencies) {
|
|
461
546
|
promise.addDependency(dep.promise, dep.path)
|
|
@@ -474,7 +559,11 @@ export { doImpl as do }
|
|
|
474
559
|
* const { summary, findings, sources } = await research`${competitor} vs our product`
|
|
475
560
|
* ```
|
|
476
561
|
*/
|
|
477
|
-
export const research = createAITemplateFunction<{
|
|
562
|
+
export const research = createAITemplateFunction<{
|
|
563
|
+
summary: string
|
|
564
|
+
findings: string[]
|
|
565
|
+
sources: string[]
|
|
566
|
+
}>('object', {
|
|
478
567
|
system: 'You are a research analyst. Provide thorough research.',
|
|
479
568
|
})
|
|
480
569
|
|
|
@@ -545,10 +634,7 @@ export function decide(
|
|
|
545
634
|
let criteria: string
|
|
546
635
|
|
|
547
636
|
if (Array.isArray(criteriaOrStrings) && 'raw' in criteriaOrStrings) {
|
|
548
|
-
criteria = criteriaOrStrings.reduce(
|
|
549
|
-
(acc, str, i) => acc + str + (templateArgs[i] ?? ''),
|
|
550
|
-
''
|
|
551
|
-
)
|
|
637
|
+
criteria = criteriaOrStrings.reduce((acc, str, i) => acc + str + (templateArgs[i] ?? ''), '')
|
|
552
638
|
} else {
|
|
553
639
|
criteria = criteriaOrStrings as string
|
|
554
640
|
}
|
|
@@ -571,11 +657,12 @@ export function decide(
|
|
|
571
657
|
|
|
572
658
|
// Override resolve to return the actual option
|
|
573
659
|
const originalResolve = promise.resolve.bind(promise)
|
|
574
|
-
;(promise as
|
|
575
|
-
const result = await originalResolve() as { chosenIndex: string | number }
|
|
576
|
-
const index =
|
|
577
|
-
|
|
578
|
-
|
|
660
|
+
;(promise as { resolve: () => Promise<T> }).resolve = async () => {
|
|
661
|
+
const result = (await originalResolve()) as { chosenIndex: string | number }
|
|
662
|
+
const index =
|
|
663
|
+
typeof result.chosenIndex === 'string'
|
|
664
|
+
? parseInt(result.chosenIndex, 10)
|
|
665
|
+
: result.chosenIndex
|
|
579
666
|
return options[index - 1] as T
|
|
580
667
|
}
|
|
581
668
|
|
|
@@ -618,13 +705,453 @@ export const ask = createAITemplateFunction<HumanResult<string>>('object', {
|
|
|
618
705
|
/**
|
|
619
706
|
* Request human approval
|
|
620
707
|
*/
|
|
621
|
-
export const approve = createAITemplateFunction<HumanResult<{ approved: boolean; notes?: string }>>(
|
|
622
|
-
|
|
623
|
-
|
|
708
|
+
export const approve = createAITemplateFunction<HumanResult<{ approved: boolean; notes?: string }>>(
|
|
709
|
+
'object',
|
|
710
|
+
{
|
|
711
|
+
system: 'Generate an approval request.',
|
|
712
|
+
}
|
|
713
|
+
)
|
|
624
714
|
|
|
625
715
|
/**
|
|
626
716
|
* Request human review
|
|
627
717
|
*/
|
|
628
|
-
export const review = createAITemplateFunction<
|
|
718
|
+
export const review = createAITemplateFunction<
|
|
719
|
+
HumanResult<{ rating?: number; feedback: string; approved?: boolean }>
|
|
720
|
+
>('object', {
|
|
629
721
|
system: 'Generate a review request.',
|
|
630
722
|
})
|
|
723
|
+
|
|
724
|
+
// ============================================================================
|
|
725
|
+
// Auto-Define Functions
|
|
726
|
+
//
|
|
727
|
+
// Inlined from former ai-proxy.ts. These helpers provide the auto-define
|
|
728
|
+
// convenience layer (analyze a name + example args, infer a function type and
|
|
729
|
+
// schema, register it). Property-access tracking lives entirely in
|
|
730
|
+
// ai-promise.ts; this section is a shallow dispatch over define() and
|
|
731
|
+
// generateObject().
|
|
732
|
+
// ============================================================================
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Analyze a function call and determine what type of function it should be
|
|
736
|
+
*/
|
|
737
|
+
async function analyzeFunction(
|
|
738
|
+
name: string,
|
|
739
|
+
args: Record<string, unknown>
|
|
740
|
+
): Promise<AutoDefineResult> {
|
|
741
|
+
// Convert camelCase/snake_case to readable name
|
|
742
|
+
const readableName = name
|
|
743
|
+
.replace(/([A-Z])/g, ' $1')
|
|
744
|
+
.replace(/_/g, ' ')
|
|
745
|
+
.toLowerCase()
|
|
746
|
+
.trim()
|
|
747
|
+
|
|
748
|
+
const argDescriptions = Object.entries(args)
|
|
749
|
+
.map(([key, value]) => {
|
|
750
|
+
const type = Array.isArray(value) ? 'array' : typeof value
|
|
751
|
+
return ` - ${key}: ${type} (example: ${JSON.stringify(value).slice(0, 50)})`
|
|
752
|
+
})
|
|
753
|
+
.join('\n')
|
|
754
|
+
|
|
755
|
+
const result = await generateObject({
|
|
756
|
+
model: 'sonnet',
|
|
757
|
+
schema: {
|
|
758
|
+
type: 'code | generative | agentic | human',
|
|
759
|
+
reasoning: 'Why this function type is appropriate (1-2 sentences)',
|
|
760
|
+
description: 'What this function does',
|
|
761
|
+
output: 'string | object | image | video | audio',
|
|
762
|
+
returnType: 'Schema for the return type as a SimpleSchema object',
|
|
763
|
+
system: 'System prompt for the AI (if generative/agentic)',
|
|
764
|
+
promptTemplate: 'Prompt template with {{arg}} placeholders',
|
|
765
|
+
instructions: 'Instructions for agentic/human functions',
|
|
766
|
+
needsTools: 'true | false',
|
|
767
|
+
suggestedTools: ['Names of tools that might be needed'],
|
|
768
|
+
channel: 'slack | email | web | sms | custom',
|
|
769
|
+
},
|
|
770
|
+
system: `You are an expert at designing AI functions. Analyze the function name and arguments to determine the best function type.
|
|
771
|
+
|
|
772
|
+
Function Types:
|
|
773
|
+
- "code": A DETERMINISTIC algorithm with no model at run time — a pure calculation, data transformation, or rule that always produces the same output for the same input (e.g. tax math, parsing, formatting). A self-contained TypeScript body can be written for it once.
|
|
774
|
+
- "generative": For generating content (text, summaries, translations, creative writing, structured data) — needs a model on every call
|
|
775
|
+
- "agentic": For complex tasks requiring multiple steps, research, or tool use (research, planning, multi-step workflows)
|
|
776
|
+
- "human": For tasks requiring human judgment, approval, or input (approvals, reviews, decisions)
|
|
777
|
+
|
|
778
|
+
Guidelines:
|
|
779
|
+
- Most functions should be "generative" - they generate content or structured data
|
|
780
|
+
- Use "code" ONLY when the task is a deterministic algorithm expressible as a self-contained function body (no model, no external state). If it needs a model at run time, it is "generative", not "code".
|
|
781
|
+
- Use "agentic" when the task requires research, multiple steps, or external tool use
|
|
782
|
+
- Use "human" when human judgment/approval is essential`,
|
|
783
|
+
prompt: `Analyze this function call and determine how to define it:
|
|
784
|
+
|
|
785
|
+
Function Name: ${name}
|
|
786
|
+
Readable Name: ${readableName}
|
|
787
|
+
Arguments:
|
|
788
|
+
${argDescriptions || ' (no arguments)'}
|
|
789
|
+
|
|
790
|
+
Determine:
|
|
791
|
+
1. What type of function this should be
|
|
792
|
+
2. What it should return
|
|
793
|
+
3. How it should be implemented`,
|
|
794
|
+
})
|
|
795
|
+
|
|
796
|
+
const analysis = result.object as {
|
|
797
|
+
type: string
|
|
798
|
+
reasoning: string
|
|
799
|
+
description: string
|
|
800
|
+
output: string
|
|
801
|
+
returnType: unknown
|
|
802
|
+
system: string
|
|
803
|
+
promptTemplate: string
|
|
804
|
+
instructions: string
|
|
805
|
+
needsTools: string
|
|
806
|
+
suggestedTools: string[]
|
|
807
|
+
channel: string
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Build the function definition based on the analysis
|
|
811
|
+
let definition: FunctionDefinition
|
|
812
|
+
|
|
813
|
+
const baseDefinition = {
|
|
814
|
+
name,
|
|
815
|
+
description: analysis.description,
|
|
816
|
+
args: inferArgsSchema(args),
|
|
817
|
+
returnType: analysis.returnType as SimpleSchema,
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
switch (analysis.type) {
|
|
821
|
+
case 'code': {
|
|
822
|
+
// `Code` is deterministic — it cannot be a call-time model invocation.
|
|
823
|
+
// Author a self-contained TS body ONCE here (at define time), then carry
|
|
824
|
+
// it as an inline `code` body so every subsequent call is deterministic.
|
|
825
|
+
const authored = await generateCode(
|
|
826
|
+
{
|
|
827
|
+
name,
|
|
828
|
+
description: analysis.description,
|
|
829
|
+
args: baseDefinition.args,
|
|
830
|
+
returnType: baseDefinition.returnType,
|
|
831
|
+
language: 'typescript',
|
|
832
|
+
instructions: `${analysis.instructions ?? ''}\n\nWrite the body of a single function that receives a parameter named \`args\` (an object with the keys above) and \`return\`s the result. Do not include the function signature, imports, or surrounding declarations — only the statements that go inside the function body.`.trim(),
|
|
833
|
+
},
|
|
834
|
+
args
|
|
835
|
+
)
|
|
836
|
+
definition = {
|
|
837
|
+
...baseDefinition,
|
|
838
|
+
type: 'code' as const,
|
|
839
|
+
language: 'typescript' as const,
|
|
840
|
+
instructions: analysis.instructions,
|
|
841
|
+
code: authored,
|
|
842
|
+
}
|
|
843
|
+
break
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
case 'agentic':
|
|
847
|
+
definition = {
|
|
848
|
+
...baseDefinition,
|
|
849
|
+
type: 'agentic' as const,
|
|
850
|
+
instructions: analysis.instructions || `Complete the ${readableName} task`,
|
|
851
|
+
promptTemplate: analysis.promptTemplate,
|
|
852
|
+
tools: [], // Tools would need to be provided separately
|
|
853
|
+
maxIterations: 10,
|
|
854
|
+
}
|
|
855
|
+
break
|
|
856
|
+
|
|
857
|
+
case 'human':
|
|
858
|
+
definition = {
|
|
859
|
+
...baseDefinition,
|
|
860
|
+
type: 'human' as const,
|
|
861
|
+
channel: (analysis.channel || 'web') as HumanChannel,
|
|
862
|
+
instructions:
|
|
863
|
+
analysis.instructions || `Please review and respond to this ${readableName} request`,
|
|
864
|
+
promptTemplate: analysis.promptTemplate,
|
|
865
|
+
}
|
|
866
|
+
break
|
|
867
|
+
|
|
868
|
+
case 'generative':
|
|
869
|
+
default:
|
|
870
|
+
definition = {
|
|
871
|
+
...baseDefinition,
|
|
872
|
+
type: 'generative' as const,
|
|
873
|
+
output: (analysis.output || 'object') as 'string' | 'object' | 'image' | 'video',
|
|
874
|
+
system: analysis.system,
|
|
875
|
+
promptTemplate: analysis.promptTemplate || `{{${Object.keys(args)[0] || 'input'}}}`,
|
|
876
|
+
}
|
|
877
|
+
break
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
return {
|
|
881
|
+
type: analysis.type as 'code' | 'generative' | 'agentic' | 'human',
|
|
882
|
+
reasoning: analysis.reasoning,
|
|
883
|
+
definition,
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Infer a schema from example arguments
|
|
889
|
+
*/
|
|
890
|
+
function inferArgsSchema(
|
|
891
|
+
args: Record<string, unknown>
|
|
892
|
+
): Record<string, string | string[] | Record<string, unknown>> {
|
|
893
|
+
const schema: Record<string, string | string[] | Record<string, unknown>> = {}
|
|
894
|
+
|
|
895
|
+
for (const [key, value] of Object.entries(args)) {
|
|
896
|
+
if (typeof value === 'string') {
|
|
897
|
+
schema[key] = `The ${key.replace(/([A-Z])/g, ' $1').toLowerCase()}`
|
|
898
|
+
} else if (typeof value === 'number') {
|
|
899
|
+
schema[key] = `The ${key.replace(/([A-Z])/g, ' $1').toLowerCase()} (number)`
|
|
900
|
+
} else if (typeof value === 'boolean') {
|
|
901
|
+
schema[key] = `Whether ${key.replace(/([A-Z])/g, ' $1').toLowerCase()} (boolean)`
|
|
902
|
+
} else if (Array.isArray(value)) {
|
|
903
|
+
if (value.length > 0 && typeof value[0] === 'string') {
|
|
904
|
+
schema[key] = [`List of ${key.replace(/([A-Z])/g, ' $1').toLowerCase()}`]
|
|
905
|
+
} else {
|
|
906
|
+
schema[key] = [`Items for ${key.replace(/([A-Z])/g, ' $1').toLowerCase()}`]
|
|
907
|
+
}
|
|
908
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
909
|
+
schema[key] = inferArgsSchema(value as Record<string, unknown>)
|
|
910
|
+
} else {
|
|
911
|
+
schema[key] = `The ${key.replace(/([A-Z])/g, ' $1').toLowerCase()}`
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
return schema
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Auto-define a function based on its name and arguments, or define with explicit definition
|
|
920
|
+
*
|
|
921
|
+
* When called with (name, args), uses AI to analyze and determine:
|
|
922
|
+
* - What type of function it should be (code, generative, agentic, human)
|
|
923
|
+
* - What it should return
|
|
924
|
+
* - How it should be implemented
|
|
925
|
+
*
|
|
926
|
+
* When called with a FunctionDefinition, creates the function directly.
|
|
927
|
+
*
|
|
928
|
+
* @example
|
|
929
|
+
* ```ts
|
|
930
|
+
* // Auto-define from name and example args
|
|
931
|
+
* const planTrip = await define('planTrip', { destination: 'Tokyo', travelers: 2 })
|
|
932
|
+
*
|
|
933
|
+
* // Or define explicitly
|
|
934
|
+
* const summarize = define.generative({
|
|
935
|
+
* name: 'summarize',
|
|
936
|
+
* args: { text: 'Text to summarize' },
|
|
937
|
+
* output: 'string',
|
|
938
|
+
* })
|
|
939
|
+
*
|
|
940
|
+
* // Or with full definition
|
|
941
|
+
* const fn = defineFunction({
|
|
942
|
+
* type: 'generative',
|
|
943
|
+
* name: 'translate',
|
|
944
|
+
* args: { text: 'Text', lang: 'Target language' },
|
|
945
|
+
* output: 'string',
|
|
946
|
+
* })
|
|
947
|
+
* ```
|
|
948
|
+
*/
|
|
949
|
+
async function autoDefineImpl(
|
|
950
|
+
name: string,
|
|
951
|
+
args: Record<string, unknown>
|
|
952
|
+
): Promise<DefinedFunction> {
|
|
953
|
+
// Check if already defined
|
|
954
|
+
const existing = functions.get(name)
|
|
955
|
+
if (existing) {
|
|
956
|
+
return existing
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// Analyze and define the function
|
|
960
|
+
const { definition } = await analyzeFunction(name, args)
|
|
961
|
+
|
|
962
|
+
// Create the defined function
|
|
963
|
+
const definedFn = createDefinedFunction(definition)
|
|
964
|
+
|
|
965
|
+
// Store in registry
|
|
966
|
+
functions.set(name, definedFn)
|
|
967
|
+
|
|
968
|
+
return definedFn
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Define functions - auto-define or use typed helpers
|
|
973
|
+
*/
|
|
974
|
+
export const define = Object.assign(autoDefineImpl, {
|
|
975
|
+
/**
|
|
976
|
+
* Define a **deterministic** code function (a handler — no LLM at call time).
|
|
977
|
+
*
|
|
978
|
+
* Supply a `handler` (canonical) or an inline `code` body. To have a model
|
|
979
|
+
* *author* code instead, use {@link generateCode} or `define.generative`.
|
|
980
|
+
*/
|
|
981
|
+
code: <TOutput, TInput>(
|
|
982
|
+
definition: Omit<CodeFunctionDefinition<TOutput, TInput>, 'type'>
|
|
983
|
+
): DefinedFunction<TOutput, TInput> => {
|
|
984
|
+
const fn = defineFunction({ type: 'code', ...definition } as CodeFunctionDefinition<
|
|
985
|
+
TOutput,
|
|
986
|
+
TInput
|
|
987
|
+
>)
|
|
988
|
+
functions.set(definition.name, fn as DefinedFunction)
|
|
989
|
+
return fn
|
|
990
|
+
},
|
|
991
|
+
|
|
992
|
+
/**
|
|
993
|
+
* Define a generative function
|
|
994
|
+
*/
|
|
995
|
+
generative: <TOutput, TInput>(
|
|
996
|
+
definition: Omit<GenerativeFunctionDefinition<TOutput, TInput>, 'type'>
|
|
997
|
+
): DefinedFunction<TOutput, TInput> => {
|
|
998
|
+
const fn = defineFunction({ type: 'generative', ...definition } as GenerativeFunctionDefinition<
|
|
999
|
+
TOutput,
|
|
1000
|
+
TInput
|
|
1001
|
+
>)
|
|
1002
|
+
functions.set(definition.name, fn as DefinedFunction)
|
|
1003
|
+
return fn
|
|
1004
|
+
},
|
|
1005
|
+
|
|
1006
|
+
/**
|
|
1007
|
+
* Define an agentic function
|
|
1008
|
+
*/
|
|
1009
|
+
agentic: <TOutput, TInput>(
|
|
1010
|
+
definition: Omit<AgenticFunctionDefinition<TOutput, TInput>, 'type'>
|
|
1011
|
+
): DefinedFunction<TOutput, TInput> => {
|
|
1012
|
+
const fn = defineFunction({ type: 'agentic', ...definition } as AgenticFunctionDefinition<
|
|
1013
|
+
TOutput,
|
|
1014
|
+
TInput
|
|
1015
|
+
>)
|
|
1016
|
+
functions.set(definition.name, fn as DefinedFunction)
|
|
1017
|
+
return fn
|
|
1018
|
+
},
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Define a human-in-the-loop function
|
|
1022
|
+
*/
|
|
1023
|
+
human: <TOutput, TInput>(
|
|
1024
|
+
definition: Omit<HumanFunctionDefinition<TOutput, TInput>, 'type'>
|
|
1025
|
+
): DefinedFunction<TOutput, TInput> => {
|
|
1026
|
+
const fn = defineFunction({ type: 'human', ...definition } as HumanFunctionDefinition<
|
|
1027
|
+
TOutput,
|
|
1028
|
+
TInput
|
|
1029
|
+
>)
|
|
1030
|
+
functions.set(definition.name, fn as DefinedFunction)
|
|
1031
|
+
return fn
|
|
1032
|
+
},
|
|
1033
|
+
})
|
|
1034
|
+
|
|
1035
|
+
// ============================================================================
|
|
1036
|
+
// AI Proxy - Smart AI Client with Auto-Definition
|
|
1037
|
+
// ============================================================================
|
|
1038
|
+
|
|
1039
|
+
/** Known built-in method names that should not be auto-defined */
|
|
1040
|
+
const BUILTIN_METHODS = new Set([
|
|
1041
|
+
'do',
|
|
1042
|
+
'is',
|
|
1043
|
+
'code',
|
|
1044
|
+
'decide',
|
|
1045
|
+
'diagram',
|
|
1046
|
+
'generate',
|
|
1047
|
+
'image',
|
|
1048
|
+
'video',
|
|
1049
|
+
'write',
|
|
1050
|
+
'list',
|
|
1051
|
+
'lists',
|
|
1052
|
+
'functions',
|
|
1053
|
+
'define',
|
|
1054
|
+
'defineFunction',
|
|
1055
|
+
'then',
|
|
1056
|
+
'catch',
|
|
1057
|
+
'finally',
|
|
1058
|
+
])
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Type for the AI proxy with auto-define capability
|
|
1062
|
+
*/
|
|
1063
|
+
export interface AIProxy {
|
|
1064
|
+
/** Function registry */
|
|
1065
|
+
functions: FunctionRegistry
|
|
1066
|
+
/** Define functions */
|
|
1067
|
+
define: typeof define
|
|
1068
|
+
/** Define a function with full definition */
|
|
1069
|
+
defineFunction: typeof defineFunction
|
|
1070
|
+
/** Dynamic function calls */
|
|
1071
|
+
[key: string]: unknown
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* Create a smart AI client that auto-defines functions on first call
|
|
1076
|
+
*
|
|
1077
|
+
* @example
|
|
1078
|
+
* ```ts
|
|
1079
|
+
* const ai = createSmartAI()
|
|
1080
|
+
*
|
|
1081
|
+
* // First call - auto-defines the function
|
|
1082
|
+
* const trip = await ai.planTrip({
|
|
1083
|
+
* destination: 'Tokyo',
|
|
1084
|
+
* dates: { start: '2024-03-01', end: '2024-03-10' },
|
|
1085
|
+
* travelers: 2,
|
|
1086
|
+
* })
|
|
1087
|
+
*
|
|
1088
|
+
* // Second call - uses cached definition (in-memory)
|
|
1089
|
+
* const trip2 = await ai.planTrip({
|
|
1090
|
+
* destination: 'Paris',
|
|
1091
|
+
* dates: { start: '2024-06-01', end: '2024-06-07' },
|
|
1092
|
+
* travelers: 4,
|
|
1093
|
+
* })
|
|
1094
|
+
*
|
|
1095
|
+
* // Access registry and define
|
|
1096
|
+
* console.log(ai.functions.list()) // ['planTrip']
|
|
1097
|
+
* ai.define.generative({ name: 'summarize', ... })
|
|
1098
|
+
* ```
|
|
1099
|
+
*/
|
|
1100
|
+
export function createSmartAI(): AIProxy {
|
|
1101
|
+
const base = {
|
|
1102
|
+
functions,
|
|
1103
|
+
define,
|
|
1104
|
+
defineFunction,
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
return new Proxy(base as AIProxy, {
|
|
1108
|
+
get(target, prop: string) {
|
|
1109
|
+
// Return built-in properties
|
|
1110
|
+
if (prop in target) {
|
|
1111
|
+
return (target as Record<string, unknown>)[prop]
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
// Skip internal properties
|
|
1115
|
+
if (typeof prop === 'symbol' || prop.startsWith('_') || BUILTIN_METHODS.has(prop)) {
|
|
1116
|
+
return undefined
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// Return a function that auto-defines and calls
|
|
1120
|
+
return async (args: Record<string, unknown> = {}) => {
|
|
1121
|
+
// Check if function is already defined
|
|
1122
|
+
let fn = functions.get(prop)
|
|
1123
|
+
|
|
1124
|
+
if (!fn) {
|
|
1125
|
+
// Auto-define the function
|
|
1126
|
+
fn = await define(prop, args)
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// Call the function
|
|
1130
|
+
return fn.call(args)
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
})
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* Default AI proxy instance with auto-define capability.
|
|
1138
|
+
*
|
|
1139
|
+
* This is the smart proxy `aiProxy` (re-exported from index.ts as `aiProxy`).
|
|
1140
|
+
* It is intentionally distinct from the `ai` template-tag primitive above —
|
|
1141
|
+
* see `ai` (line ~354) for the template function used like `ai\`...\``.
|
|
1142
|
+
*
|
|
1143
|
+
* @example
|
|
1144
|
+
* ```ts
|
|
1145
|
+
* import { aiProxy } from 'ai-functions'
|
|
1146
|
+
*
|
|
1147
|
+
* // Auto-define and call
|
|
1148
|
+
* const result = await aiProxy.summarize({ text: 'Long article...' })
|
|
1149
|
+
*
|
|
1150
|
+
* // Access functions registry
|
|
1151
|
+
* aiProxy.functions.list()
|
|
1152
|
+
*
|
|
1153
|
+
* // Define explicitly
|
|
1154
|
+
* aiProxy.define.generative({ name: 'translate', ... })
|
|
1155
|
+
* ```
|
|
1156
|
+
*/
|
|
1157
|
+
export const aiProxy: AIProxy = createSmartAI()
|