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/test/define.test.ts
CHANGED
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { describe, it, expect, beforeEach } from 'vitest'
|
|
8
|
-
import { define, defineFunction, functions } from '../src/index.js'
|
|
8
|
+
import { define, defineFunction, functions, createFunctionRegistry, resetGlobalRegistry } from '../src/index.js'
|
|
9
9
|
|
|
10
10
|
// Skip tests if no gateway configured
|
|
11
11
|
const hasGateway = !!process.env.AI_GATEWAY_URL || !!process.env.ANTHROPIC_API_KEY
|
|
12
12
|
|
|
13
13
|
describe('functions registry', () => {
|
|
14
14
|
beforeEach(() => {
|
|
15
|
-
|
|
15
|
+
resetGlobalRegistry()
|
|
16
16
|
})
|
|
17
17
|
|
|
18
18
|
it('starts empty', () => {
|
|
@@ -75,14 +75,152 @@ describe('functions registry', () => {
|
|
|
75
75
|
functions.set('func1', fn1)
|
|
76
76
|
functions.set('func2', fn2)
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
resetGlobalRegistry()
|
|
79
|
+
expect(functions.list()).toEqual([])
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
describe('createFunctionRegistry', () => {
|
|
84
|
+
beforeEach(() => {
|
|
85
|
+
resetGlobalRegistry()
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('creates an isolated registry instance', () => {
|
|
89
|
+
const registry = createFunctionRegistry()
|
|
90
|
+
expect(registry.list()).toEqual([])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('registry operations do not affect global registry', () => {
|
|
94
|
+
// Add function to global registry
|
|
95
|
+
const globalFn = defineFunction({
|
|
96
|
+
type: 'generative',
|
|
97
|
+
name: 'globalFunc',
|
|
98
|
+
args: { input: 'Test input' },
|
|
99
|
+
output: 'string',
|
|
100
|
+
})
|
|
101
|
+
functions.set('globalFunc', globalFn)
|
|
102
|
+
|
|
103
|
+
// Create isolated registry and add different function
|
|
104
|
+
const registry = createFunctionRegistry()
|
|
105
|
+
const isolatedFn = defineFunction({
|
|
106
|
+
type: 'generative',
|
|
107
|
+
name: 'isolatedFunc',
|
|
108
|
+
args: { data: 'Test data' },
|
|
109
|
+
output: 'string',
|
|
110
|
+
})
|
|
111
|
+
registry.set('isolatedFunc', isolatedFn)
|
|
112
|
+
|
|
113
|
+
// Verify isolation
|
|
114
|
+
expect(functions.has('globalFunc')).toBe(true)
|
|
115
|
+
expect(functions.has('isolatedFunc')).toBe(false)
|
|
116
|
+
expect(registry.has('isolatedFunc')).toBe(true)
|
|
117
|
+
expect(registry.has('globalFunc')).toBe(false)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('multiple registries are independent of each other', () => {
|
|
121
|
+
const registry1 = createFunctionRegistry()
|
|
122
|
+
const registry2 = createFunctionRegistry()
|
|
123
|
+
|
|
124
|
+
const fn1 = defineFunction({
|
|
125
|
+
type: 'generative',
|
|
126
|
+
name: 'func1',
|
|
127
|
+
args: {},
|
|
128
|
+
output: 'string',
|
|
129
|
+
})
|
|
130
|
+
const fn2 = defineFunction({
|
|
131
|
+
type: 'generative',
|
|
132
|
+
name: 'func2',
|
|
133
|
+
args: {},
|
|
134
|
+
output: 'string',
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
registry1.set('func1', fn1)
|
|
138
|
+
registry2.set('func2', fn2)
|
|
139
|
+
|
|
140
|
+
expect(registry1.has('func1')).toBe(true)
|
|
141
|
+
expect(registry1.has('func2')).toBe(false)
|
|
142
|
+
expect(registry2.has('func1')).toBe(false)
|
|
143
|
+
expect(registry2.has('func2')).toBe(true)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
it('isolated registry supports all operations', () => {
|
|
147
|
+
const registry = createFunctionRegistry()
|
|
148
|
+
|
|
149
|
+
const fn = defineFunction({
|
|
150
|
+
type: 'generative',
|
|
151
|
+
name: 'testFunc',
|
|
152
|
+
args: { x: 'number' },
|
|
153
|
+
output: 'string',
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// set and get
|
|
157
|
+
registry.set('testFunc', fn)
|
|
158
|
+
expect(registry.get('testFunc')).toBe(fn)
|
|
159
|
+
|
|
160
|
+
// has
|
|
161
|
+
expect(registry.has('testFunc')).toBe(true)
|
|
162
|
+
|
|
163
|
+
// list
|
|
164
|
+
expect(registry.list()).toEqual(['testFunc'])
|
|
165
|
+
|
|
166
|
+
// delete
|
|
167
|
+
expect(registry.delete('testFunc')).toBe(true)
|
|
168
|
+
expect(registry.has('testFunc')).toBe(false)
|
|
169
|
+
|
|
170
|
+
// clear
|
|
171
|
+
registry.set('a', fn)
|
|
172
|
+
registry.set('b', fn)
|
|
173
|
+
registry.clear()
|
|
174
|
+
expect(registry.list()).toEqual([])
|
|
175
|
+
})
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
describe('resetGlobalRegistry', () => {
|
|
179
|
+
it('clears all functions from global registry', () => {
|
|
180
|
+
const fn = defineFunction({
|
|
181
|
+
type: 'generative',
|
|
182
|
+
name: 'testFunc',
|
|
183
|
+
args: {},
|
|
184
|
+
output: 'string',
|
|
185
|
+
})
|
|
186
|
+
functions.set('testFunc', fn)
|
|
187
|
+
expect(functions.has('testFunc')).toBe(true)
|
|
188
|
+
|
|
189
|
+
resetGlobalRegistry()
|
|
190
|
+
expect(functions.has('testFunc')).toBe(false)
|
|
191
|
+
expect(functions.list()).toEqual([])
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
it('does not affect isolated registries', () => {
|
|
195
|
+
const isolatedRegistry = createFunctionRegistry()
|
|
196
|
+
const fn = defineFunction({
|
|
197
|
+
type: 'generative',
|
|
198
|
+
name: 'isolatedFunc',
|
|
199
|
+
args: {},
|
|
200
|
+
output: 'string',
|
|
201
|
+
})
|
|
202
|
+
isolatedRegistry.set('isolatedFunc', fn)
|
|
203
|
+
|
|
204
|
+
// Add to global and reset
|
|
205
|
+
functions.set('globalFunc', fn)
|
|
206
|
+
resetGlobalRegistry()
|
|
207
|
+
|
|
208
|
+
// Global should be empty, isolated should still have function
|
|
209
|
+
expect(functions.list()).toEqual([])
|
|
210
|
+
expect(isolatedRegistry.has('isolatedFunc')).toBe(true)
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('can be called multiple times safely', () => {
|
|
214
|
+
resetGlobalRegistry()
|
|
215
|
+
resetGlobalRegistry()
|
|
216
|
+
resetGlobalRegistry()
|
|
79
217
|
expect(functions.list()).toEqual([])
|
|
80
218
|
})
|
|
81
219
|
})
|
|
82
220
|
|
|
83
221
|
describe('defineFunction', () => {
|
|
84
222
|
beforeEach(() => {
|
|
85
|
-
|
|
223
|
+
resetGlobalRegistry()
|
|
86
224
|
})
|
|
87
225
|
|
|
88
226
|
it('creates a generative function definition', () => {
|
|
@@ -132,6 +270,7 @@ describe('defineFunction', () => {
|
|
|
132
270
|
name: 'implement',
|
|
133
271
|
args: { spec: 'Function specification' },
|
|
134
272
|
language: 'typescript',
|
|
273
|
+
handler: () => 'ok',
|
|
135
274
|
})
|
|
136
275
|
|
|
137
276
|
expect(fn.definition.type).toBe('code')
|
|
@@ -163,7 +302,7 @@ describe('defineFunction', () => {
|
|
|
163
302
|
|
|
164
303
|
describe('define helpers', () => {
|
|
165
304
|
beforeEach(() => {
|
|
166
|
-
|
|
305
|
+
resetGlobalRegistry()
|
|
167
306
|
})
|
|
168
307
|
|
|
169
308
|
it('define.generative registers function', () => {
|
|
@@ -204,7 +343,8 @@ describe('define helpers', () => {
|
|
|
204
343
|
const fn = define.code({
|
|
205
344
|
name: 'generate',
|
|
206
345
|
args: { prompt: 'Code generation prompt' },
|
|
207
|
-
language: '
|
|
346
|
+
language: 'typescript',
|
|
347
|
+
handler: () => 'ok',
|
|
208
348
|
})
|
|
209
349
|
|
|
210
350
|
expect(functions.has('generate')).toBe(true)
|
|
@@ -212,9 +352,72 @@ describe('define helpers', () => {
|
|
|
212
352
|
})
|
|
213
353
|
})
|
|
214
354
|
|
|
355
|
+
// Code is the DETERMINISTIC kind — no gateway required. These tests assert the
|
|
356
|
+
// post-split contract: `type: 'code'` runs a handler (or inline body), never a
|
|
357
|
+
// model, at call time. (Code-authoring moved to generateCode().)
|
|
358
|
+
describe('code function execution (deterministic)', () => {
|
|
359
|
+
beforeEach(() => {
|
|
360
|
+
resetGlobalRegistry()
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
it('runs the supplied handler with no LLM call', async () => {
|
|
364
|
+
const calculateTax = defineFunction<number, { amount: number; rate: number }>({
|
|
365
|
+
type: 'code',
|
|
366
|
+
name: 'calculateTax',
|
|
367
|
+
args: { amount: 'Amount (number)', rate: 'Rate (number)' },
|
|
368
|
+
handler: ({ amount, rate }) => amount * rate,
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
const result = await calculateTax.call({ amount: 100, rate: 0.2 })
|
|
372
|
+
expect(result).toBe(20)
|
|
373
|
+
// Determinism: same input → same output, every time
|
|
374
|
+
expect(await calculateTax.call({ amount: 100, rate: 0.2 })).toBe(20)
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('awaits an async handler', async () => {
|
|
378
|
+
const fn = defineFunction<string, { name: string }>({
|
|
379
|
+
type: 'code',
|
|
380
|
+
name: 'greetAsync',
|
|
381
|
+
args: { name: 'Name' },
|
|
382
|
+
handler: async ({ name }) => `hi ${name}`,
|
|
383
|
+
})
|
|
384
|
+
expect(await fn.call({ name: 'world' })).toBe('hi world')
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
it('evaluates an inline code body deterministically', async () => {
|
|
388
|
+
const fn = defineFunction<number, { items: number[] }>({
|
|
389
|
+
type: 'code',
|
|
390
|
+
name: 'sum',
|
|
391
|
+
args: { items: ['Numbers'] },
|
|
392
|
+
language: 'typescript',
|
|
393
|
+
code: 'return args.items.reduce((a, b) => a + b, 0)',
|
|
394
|
+
})
|
|
395
|
+
expect(await fn.call({ items: [1, 2, 3, 4] })).toBe(10)
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
it('throws (does not call a model) when no handler or code is provided', async () => {
|
|
399
|
+
const fn = defineFunction({
|
|
400
|
+
type: 'code',
|
|
401
|
+
name: 'noImpl',
|
|
402
|
+
args: { spec: 'spec' },
|
|
403
|
+
language: 'typescript',
|
|
404
|
+
})
|
|
405
|
+
await expect(fn.call({ spec: 'x' })).rejects.toThrow(/no handler or inline code/i)
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
it('define.code runs the handler', async () => {
|
|
409
|
+
const fn = define.code<number, { a: number; b: number }>({
|
|
410
|
+
name: 'add',
|
|
411
|
+
args: { a: 'a (number)', b: 'b (number)' },
|
|
412
|
+
handler: ({ a, b }) => a + b,
|
|
413
|
+
})
|
|
414
|
+
expect(await fn.call({ a: 2, b: 3 })).toBe(5)
|
|
415
|
+
})
|
|
416
|
+
})
|
|
417
|
+
|
|
215
418
|
describe.skipIf(!hasGateway)('generative function execution', () => {
|
|
216
419
|
beforeEach(() => {
|
|
217
|
-
|
|
420
|
+
resetGlobalRegistry()
|
|
218
421
|
})
|
|
219
422
|
|
|
220
423
|
it('executes a generative string function', async () => {
|
|
@@ -251,7 +454,7 @@ describe.skipIf(!hasGateway)('generative function execution', () => {
|
|
|
251
454
|
|
|
252
455
|
describe.skipIf(!hasGateway)('auto-define', () => {
|
|
253
456
|
beforeEach(() => {
|
|
254
|
-
|
|
457
|
+
resetGlobalRegistry()
|
|
255
458
|
})
|
|
256
459
|
|
|
257
460
|
it('auto-defines a function from name and args', async () => {
|