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/types.ts
CHANGED
|
@@ -2,16 +2,117 @@
|
|
|
2
2
|
* Core types for AI functions
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { SandboxEnv } from 'ai-evaluate'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Host Workers environment for the ai-evaluate sandbox.
|
|
9
|
+
*
|
|
10
|
+
* Re-exported from ai-evaluate so consumers can type the optional `env`
|
|
11
|
+
* argument threaded through `DefinedFunction.call` / `generateAndRunCode`
|
|
12
|
+
* without importing ai-evaluate directly.
|
|
13
|
+
*/
|
|
14
|
+
export type { SandboxEnv } from 'ai-evaluate'
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Human Function Pending Types
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Symbol used to identify pending human function results
|
|
22
|
+
*/
|
|
23
|
+
export const PENDING_HUMAN_RESULT_SYMBOL = Symbol.for('HumanFunctionPending')
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Human interaction channels
|
|
27
|
+
*
|
|
28
|
+
* - chat: Real-time messaging (WebSocket, in-app)
|
|
29
|
+
* - email: Async email communication
|
|
30
|
+
* - phone: Voice calls
|
|
31
|
+
* - sms: SMS text messages
|
|
32
|
+
* - workspace: Team collaboration platforms (Slack, Teams, Discord)
|
|
33
|
+
* - web: Web-based interface (browser, web app)
|
|
34
|
+
*/
|
|
35
|
+
export type HumanChannel = 'chat' | 'email' | 'phone' | 'sms' | 'workspace' | 'web'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Pending human function result returned when human input is not yet available.
|
|
39
|
+
*
|
|
40
|
+
* This is returned by human functions that need actual human input but are running
|
|
41
|
+
* in a placeholder mode (e.g., during testing or when channel integrations are not configured).
|
|
42
|
+
*
|
|
43
|
+
* Use `isPendingHumanResult()` to check if a result is pending before using it.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const result = await approveRefund({ amount: 500, reason: 'Duplicate charge' })
|
|
48
|
+
*
|
|
49
|
+
* if (isPendingHumanResult(result)) {
|
|
50
|
+
* console.log('Waiting for human approval via:', result.channel)
|
|
51
|
+
* // Handle pending state - queue for later, show UI, etc.
|
|
52
|
+
* } else {
|
|
53
|
+
* // result is the actual TOutput type
|
|
54
|
+
* console.log('Approved:', result.approved)
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export interface HumanFunctionPending<TExpected = unknown> {
|
|
59
|
+
/** Symbol marker for type identification */
|
|
60
|
+
readonly [PENDING_HUMAN_RESULT_SYMBOL]: true
|
|
61
|
+
/** Indicates this is a pending placeholder, not actual human response */
|
|
62
|
+
readonly _pending: true
|
|
63
|
+
/** The channel where human input was requested */
|
|
64
|
+
readonly channel: HumanChannel
|
|
65
|
+
/** Generated UI/content artifacts for the channel */
|
|
66
|
+
readonly artifacts: unknown
|
|
67
|
+
/** The expected response type schema */
|
|
68
|
+
readonly expectedResponseType: TExpected
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Type guard to check if a result is a pending human function result.
|
|
73
|
+
*
|
|
74
|
+
* Use this to safely handle cases where human input is not yet available.
|
|
75
|
+
*
|
|
76
|
+
* @param value - The value to check
|
|
77
|
+
* @returns True if the value is a HumanFunctionPending object
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* const result = await reviewDocument({ docId: '123' })
|
|
82
|
+
*
|
|
83
|
+
* if (isPendingHumanResult(result)) {
|
|
84
|
+
* // result is HumanFunctionPending - human input needed
|
|
85
|
+
* console.warn('Human review pending:', result.channel)
|
|
86
|
+
* return { status: 'pending', channel: result.channel }
|
|
87
|
+
* }
|
|
88
|
+
*
|
|
89
|
+
* // result is ReviewResult - actual human response
|
|
90
|
+
* return { status: 'reviewed', approved: result.approved }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export function isPendingHumanResult<T>(
|
|
94
|
+
value: T | HumanFunctionPending
|
|
95
|
+
): value is HumanFunctionPending {
|
|
96
|
+
return (
|
|
97
|
+
value !== null &&
|
|
98
|
+
typeof value === 'object' &&
|
|
99
|
+
'_pending' in value &&
|
|
100
|
+
value._pending === true &&
|
|
101
|
+
PENDING_HUMAN_RESULT_SYMBOL in value
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ============================================================================
|
|
106
|
+
// AI Function Types
|
|
107
|
+
// ============================================================================
|
|
108
|
+
|
|
5
109
|
/**
|
|
6
110
|
* A function definition that can be called by AI
|
|
7
111
|
*
|
|
8
112
|
* @typeParam TOutput - The return type of the function handler
|
|
9
113
|
* @typeParam TInput - The input type accepted by the function handler
|
|
10
114
|
*/
|
|
11
|
-
export interface AIFunctionDefinition<
|
|
12
|
-
TOutput = unknown,
|
|
13
|
-
TInput = unknown
|
|
14
|
-
> {
|
|
115
|
+
export interface AIFunctionDefinition<TOutput = unknown, TInput = unknown> {
|
|
15
116
|
/** Unique name for the function */
|
|
16
117
|
name: string
|
|
17
118
|
/** Human-readable description for the AI */
|
|
@@ -162,9 +263,11 @@ export interface WriteOptions {
|
|
|
162
263
|
/**
|
|
163
264
|
* Type for functions that support both regular calls and tagged template literals
|
|
164
265
|
*/
|
|
165
|
-
export type TemplateFunction<TArgs extends unknown[], TReturn> =
|
|
166
|
-
|
|
167
|
-
|
|
266
|
+
export type TemplateFunction<TArgs extends unknown[], TReturn> = ((
|
|
267
|
+
prompt: string,
|
|
268
|
+
...args: TArgs
|
|
269
|
+
) => TReturn) &
|
|
270
|
+
((strings: TemplateStringsArray, ...values: unknown[]) => TReturn)
|
|
168
271
|
|
|
169
272
|
/**
|
|
170
273
|
* A single item in a list
|
|
@@ -210,18 +313,6 @@ export type CodeLanguage = 'typescript' | 'javascript' | 'python' | 'go' | 'rust
|
|
|
210
313
|
*/
|
|
211
314
|
export type GenerativeOutputType = 'string' | 'object' | 'image' | 'video'
|
|
212
315
|
|
|
213
|
-
/**
|
|
214
|
-
* Human interaction channels
|
|
215
|
-
*
|
|
216
|
-
* - chat: Real-time messaging (WebSocket, in-app)
|
|
217
|
-
* - email: Async email communication
|
|
218
|
-
* - phone: Voice calls
|
|
219
|
-
* - sms: SMS text messages
|
|
220
|
-
* - workspace: Team collaboration platforms (Slack, Teams, Discord)
|
|
221
|
-
* - web: Web-based interface (browser, web app)
|
|
222
|
-
*/
|
|
223
|
-
export type HumanChannel = 'chat' | 'email' | 'phone' | 'sms' | 'workspace' | 'web'
|
|
224
|
-
|
|
225
316
|
/**
|
|
226
317
|
* Legacy channel type for backwards compatibility
|
|
227
318
|
* @deprecated Use HumanChannel instead
|
|
@@ -273,12 +364,24 @@ export interface BaseFunctionDefinition<TOutput = unknown, TInput = unknown> {
|
|
|
273
364
|
}
|
|
274
365
|
|
|
275
366
|
/**
|
|
276
|
-
* Code function -
|
|
367
|
+
* Code function - a **deterministic** handler.
|
|
368
|
+
*
|
|
369
|
+
* `Code` is the deterministic kind: a fetch/transform/rule handler that runs
|
|
370
|
+
* the **same logic every time** with no model in the execution path. When
|
|
371
|
+
* called, it invokes the supplied {@link CodeFunctionDefinition.handler}
|
|
372
|
+
* (or evaluates the inline {@link CodeFunctionDefinition.code} body) and
|
|
373
|
+
* returns the result directly — no LLM is consulted at call time.
|
|
277
374
|
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
375
|
+
* This is the contract consumers bind to (e.g. ADR-0033's
|
|
376
|
+
* "Code = deterministic"). If you want a model to *author* code, that is a
|
|
377
|
+
* generation task: use {@link generateCode} / the `generate('code', …)`
|
|
378
|
+
* primitive, or define a `Generative` function whose output is source text.
|
|
379
|
+
* See the migration note in the package README.
|
|
380
|
+
*
|
|
381
|
+
* Exactly one of `handler` or `code` should be supplied. `handler` is the
|
|
382
|
+
* canonical form (a native function reference); `code` is an inline source
|
|
383
|
+
* body, deterministically compiled by the consumer's runtime — never sent to
|
|
384
|
+
* a model.
|
|
282
385
|
*
|
|
283
386
|
* @example
|
|
284
387
|
* ```ts
|
|
@@ -290,7 +393,7 @@ export interface BaseFunctionDefinition<TOutput = unknown, TInput = unknown> {
|
|
|
290
393
|
* rate: 'Tax rate as decimal (number)',
|
|
291
394
|
* },
|
|
292
395
|
* returnType: 'The calculated tax amount (number)',
|
|
293
|
-
*
|
|
396
|
+
* handler: ({ amount, rate }) => amount * rate,
|
|
294
397
|
* })
|
|
295
398
|
* ```
|
|
296
399
|
*
|
|
@@ -300,6 +403,51 @@ export interface BaseFunctionDefinition<TOutput = unknown, TInput = unknown> {
|
|
|
300
403
|
export interface CodeFunctionDefinition<TOutput = unknown, TInput = unknown>
|
|
301
404
|
extends BaseFunctionDefinition<TOutput, TInput> {
|
|
302
405
|
type: 'code'
|
|
406
|
+
/**
|
|
407
|
+
* The deterministic handler invoked on every call. Receives the parsed
|
|
408
|
+
* `args` and returns (or resolves to) the result. No LLM is involved.
|
|
409
|
+
*
|
|
410
|
+
* Either `handler` or {@link CodeFunctionDefinition.code} must be provided;
|
|
411
|
+
* `handler` takes precedence when both are present.
|
|
412
|
+
*/
|
|
413
|
+
handler?: (input: TInput) => TOutput | Promise<TOutput>
|
|
414
|
+
/**
|
|
415
|
+
* Inline source body for the handler, as a string. Deterministically
|
|
416
|
+
* compiled by the consumer's runtime (it is **not** generated by a model).
|
|
417
|
+
* Used when a handler cannot be passed by reference (e.g. a definition
|
|
418
|
+
* loaded from storage). The body receives the `args` in scope and should
|
|
419
|
+
* `return` the result.
|
|
420
|
+
*
|
|
421
|
+
* Either `code` or {@link CodeFunctionDefinition.handler} must be provided.
|
|
422
|
+
*/
|
|
423
|
+
code?: string
|
|
424
|
+
/** Target programming language of `code` (default: `'typescript'`). Metadata only. */
|
|
425
|
+
language?: CodeLanguage
|
|
426
|
+
/** Optional human-readable note about what the handler does. Metadata only. */
|
|
427
|
+
instructions?: string
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Definition for a code-**authoring** request — the explicit, opt-in path for
|
|
432
|
+
* having a model *write* code. This is the behavior `type: 'code'` used to
|
|
433
|
+
* have implicitly; it has been split out so that `Code` can mean
|
|
434
|
+
* "deterministic handler" without a silent change of meaning.
|
|
435
|
+
*
|
|
436
|
+
* This is **not** part of the {@link FunctionDefinition} union and never
|
|
437
|
+
* executes deterministically — calling it consults a model. Drive it via
|
|
438
|
+
* {@link generateCode}.
|
|
439
|
+
*
|
|
440
|
+
* @typeParam TInput - The arguments schema describing the code to author
|
|
441
|
+
*/
|
|
442
|
+
export interface CodeGenerationDefinition<TInput = unknown> {
|
|
443
|
+
/** Name of the function/query to author */
|
|
444
|
+
name: string
|
|
445
|
+
/** Human-readable description of what the code should do */
|
|
446
|
+
description?: string
|
|
447
|
+
/** Arguments/spec schema describing the code to generate */
|
|
448
|
+
args: TInput
|
|
449
|
+
/** Return type schema the authored code should produce (optional) */
|
|
450
|
+
returnType?: unknown
|
|
303
451
|
/** Target programming language */
|
|
304
452
|
language?: CodeLanguage
|
|
305
453
|
/** Additional context or requirements for code generation */
|
|
@@ -308,6 +456,8 @@ export interface CodeFunctionDefinition<TOutput = unknown, TInput = unknown>
|
|
|
308
456
|
includeTests?: boolean
|
|
309
457
|
/** Whether to include example usage (default: true) */
|
|
310
458
|
includeExamples?: boolean
|
|
459
|
+
/** Model to use for authoring (defaults to 'sonnet') */
|
|
460
|
+
model?: string
|
|
311
461
|
}
|
|
312
462
|
|
|
313
463
|
/**
|
|
@@ -519,8 +669,17 @@ export type FunctionDefinition<TOutput = unknown, TInput = unknown> =
|
|
|
519
669
|
export interface DefinedFunction<TOutput = unknown, TInput = unknown> {
|
|
520
670
|
/** The original definition */
|
|
521
671
|
definition: FunctionDefinition<TOutput, TInput>
|
|
522
|
-
/**
|
|
523
|
-
|
|
672
|
+
/**
|
|
673
|
+
* Call the function.
|
|
674
|
+
*
|
|
675
|
+
* @param args - The function arguments.
|
|
676
|
+
* @param env - Optional host Workers env (carrying a `LOADER` worker-loader
|
|
677
|
+
* binding, and `TEST` for the test path) used by `type: 'code'` functions
|
|
678
|
+
* to run inline `code` bodies in ai-evaluate's sandbox. When omitted, the
|
|
679
|
+
* inline-code path falls back to the Miniflare-backed Node runtime. Has no
|
|
680
|
+
* effect on `handler`-based code functions or other function types.
|
|
681
|
+
*/
|
|
682
|
+
call: (args: TInput, env?: SandboxEnv) => Promise<TOutput>
|
|
524
683
|
/** Get the function as a tool definition for AI */
|
|
525
684
|
asTool: () => AIFunctionDefinition<TOutput, TInput>
|
|
526
685
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wrapForV3 — convenience composer for the v3 cascade-walker / evaluator-panel
|
|
3
|
+
* use case.
|
|
4
|
+
*
|
|
5
|
+
* Composes `cacheMiddleware`, `budgetMiddleware`, and `traceMiddleware` in a
|
|
6
|
+
* single `wrapLanguageModel` call so callers in services-as-software (round
|
|
7
|
+
* 15+ swap) can replace their existing post-hoc duck-typing in
|
|
8
|
+
* `cost-estimate.ts` with a single wrap call:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { wrapForV3, BudgetTracker, getEvalLogStore } from 'ai-functions'
|
|
12
|
+
*
|
|
13
|
+
* const tracker = new BudgetTracker({ maxCost: 1.0 })
|
|
14
|
+
* const store = getEvalLogStore()
|
|
15
|
+
*
|
|
16
|
+
* const wrapped = wrapForV3(openai('gpt-4o'), {
|
|
17
|
+
* cache: { store: 'disk', ttlMs: 86_400_000 },
|
|
18
|
+
* budget: { tracker },
|
|
19
|
+
* trace: { emit: (e) => store.record({ ...e, costUsd: e.costUsd ?? 0 }) },
|
|
20
|
+
* })
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* **Composition order:**
|
|
24
|
+
* 1. **cache** — first so cache hits skip budget+trace network cost. The
|
|
25
|
+
* cached payload's usage still flows downstream so budget records the
|
|
26
|
+
* cost on hits AND misses.
|
|
27
|
+
* 2. **budget** — second so it sees the wrapped result regardless of
|
|
28
|
+
* cache hit/miss; tracker.recordUsage fires either way.
|
|
29
|
+
* 3. **trace** — last so the event sees the final outcome (post-cache,
|
|
30
|
+
* post-budget). Errors from `emit` are swallowed.
|
|
31
|
+
*
|
|
32
|
+
* AI SDK 6 ordering semantics (per the wrapLanguageModel JSDoc): "the first
|
|
33
|
+
* middleware will transform the input first, and the last middleware will
|
|
34
|
+
* be wrapped directly around the model." So when we hand the array
|
|
35
|
+
* `[cache, budget, trace]`, the runtime call order is
|
|
36
|
+
* `cache → budget → trace → model` on the way in, and the reverse on the
|
|
37
|
+
* way out. Cache sees the call first; if it has a hit, downstream layers
|
|
38
|
+
* never run their `wrapGenerate` body for that call. Budget and trace each
|
|
39
|
+
* get their own post-completion hook on the result the layer below them
|
|
40
|
+
* returned — so on a cache hit, neither budget nor trace runs (because
|
|
41
|
+
* cache short-circuits via `return cached`). To get budget + trace on
|
|
42
|
+
* cache hits, the budgetMiddleware/traceMiddleware would need to wrap the
|
|
43
|
+
* cache middleware (i.e. install AFTER it in the chain). Per the spec
|
|
44
|
+
* above, "later in the array = closer to the model" → install order
|
|
45
|
+
* matters: callers who want cache-hit cost recording should pass
|
|
46
|
+
* `[budget, trace, cache]`. We use `[cache, budget, trace]` as the default
|
|
47
|
+
* because the eval-fixture use case wants the 5x verify-time win and is
|
|
48
|
+
* happy to skip the cost record on the hit path (the original miss already
|
|
49
|
+
* recorded it).
|
|
50
|
+
*
|
|
51
|
+
* @packageDocumentation
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
import { wrapLanguageModel, type LanguageModel } from 'ai'
|
|
55
|
+
import type { LanguageModelV3, LanguageModelV3Middleware } from '@ai-sdk/provider'
|
|
56
|
+
import { cacheMiddleware, type CacheMiddlewareOptions } from './middleware/cache.js'
|
|
57
|
+
import { budgetMiddleware, type BudgetMiddlewareOptions } from './middleware/budget.js'
|
|
58
|
+
import { traceMiddleware, type TraceMiddlewareOptions } from './middleware/trace.js'
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
// Types
|
|
62
|
+
// ============================================================================
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Options for {@link wrapForV3}. All three middleware sections are
|
|
66
|
+
* optional — pass only what you need.
|
|
67
|
+
*/
|
|
68
|
+
export interface WrapForV3Options {
|
|
69
|
+
/** Cache config (see {@link CacheMiddlewareOptions}). */
|
|
70
|
+
cache?: CacheMiddlewareOptions
|
|
71
|
+
/** Budget tracking config (see {@link BudgetMiddlewareOptions}). */
|
|
72
|
+
budget?: BudgetMiddlewareOptions
|
|
73
|
+
/** Trace emission config (see {@link TraceMiddlewareOptions}). */
|
|
74
|
+
trace?: TraceMiddlewareOptions
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Composer
|
|
79
|
+
// ============================================================================
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Wrap a {@link LanguageModel} with the v3-cascade middleware stack
|
|
83
|
+
* (cache → budget → trace, in install order).
|
|
84
|
+
*
|
|
85
|
+
* Returns the wrapped model with the same shape as the input; downstream
|
|
86
|
+
* `generateText` / `generateObject` / `streamText` calls treat it as a
|
|
87
|
+
* regular model.
|
|
88
|
+
*
|
|
89
|
+
* @see WrapForV3Options for partial-config behaviour
|
|
90
|
+
*/
|
|
91
|
+
export function wrapForV3(model: LanguageModel, opts: WrapForV3Options = {}): LanguageModel {
|
|
92
|
+
const middleware: LanguageModelV3Middleware[] = []
|
|
93
|
+
if (opts.cache) middleware.push(cacheMiddleware(opts.cache))
|
|
94
|
+
if (opts.budget) middleware.push(budgetMiddleware(opts.budget))
|
|
95
|
+
if (opts.trace) middleware.push(traceMiddleware(opts.trace))
|
|
96
|
+
if (middleware.length === 0) return model
|
|
97
|
+
// wrapLanguageModel currently accepts LanguageModelV3 — at the AI SDK 6
|
|
98
|
+
// surface, `LanguageModel` is the wider union. The runtime is V3
|
|
99
|
+
// everywhere in the published providers; the cast is the same one the
|
|
100
|
+
// wrapLanguageModel cookbook uses.
|
|
101
|
+
return wrapLanguageModel({
|
|
102
|
+
model: model as LanguageModelV3,
|
|
103
|
+
middleware,
|
|
104
|
+
}) as LanguageModel
|
|
105
|
+
}
|