ai-functions 2.1.3 → 2.3.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 +55 -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 +116 -0
- package/dist/function-registry.d.ts.map +1 -0
- package/dist/function-registry.js +546 -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/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 +135 -17
- 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 +28 -25
- package/src/ai-promise.ts +226 -140
- package/src/ai-schemas.ts +122 -0
- package/src/ai.ts +69 -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 +671 -0
- package/src/generate.ts +33 -28
- package/src/index.ts +119 -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/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 +164 -25
- 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/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/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/batch/cloudflare.js
DELETED
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cloudflare AI Gateway Batch Adapter
|
|
3
|
-
*
|
|
4
|
-
* Implements batch processing using Cloudflare AI Gateway's batch endpoint.
|
|
5
|
-
* Cloudflare's batch API is newer but integrates well with Workers.
|
|
6
|
-
*
|
|
7
|
-
* Note: Cloudflare's batch API is evolving. This adapter implements
|
|
8
|
-
* the current batch capabilities and can be extended as new features land.
|
|
9
|
-
*
|
|
10
|
-
* @see https://developers.cloudflare.com/ai-gateway/
|
|
11
|
-
*
|
|
12
|
-
* @packageDocumentation
|
|
13
|
-
*/
|
|
14
|
-
import { registerBatchAdapter, } from '../batch-queue.js';
|
|
15
|
-
// ============================================================================
|
|
16
|
-
// Cloudflare Client Configuration
|
|
17
|
-
// ============================================================================
|
|
18
|
-
let accountId;
|
|
19
|
-
let gatewayId;
|
|
20
|
-
let apiToken;
|
|
21
|
-
let baseUrl = 'https://api.cloudflare.com/client/v4';
|
|
22
|
-
/**
|
|
23
|
-
* Configure the Cloudflare client
|
|
24
|
-
*/
|
|
25
|
-
export function configureCloudflare(options) {
|
|
26
|
-
if (options.accountId)
|
|
27
|
-
accountId = options.accountId;
|
|
28
|
-
if (options.gatewayId)
|
|
29
|
-
gatewayId = options.gatewayId;
|
|
30
|
-
if (options.apiToken)
|
|
31
|
-
apiToken = options.apiToken;
|
|
32
|
-
if (options.baseUrl)
|
|
33
|
-
baseUrl = options.baseUrl;
|
|
34
|
-
}
|
|
35
|
-
function getConfig() {
|
|
36
|
-
const accId = accountId || process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
37
|
-
const gwId = gatewayId || process.env.CLOUDFLARE_AI_GATEWAY_ID || process.env.AI_GATEWAY_ID;
|
|
38
|
-
const token = apiToken || process.env.CLOUDFLARE_API_TOKEN;
|
|
39
|
-
if (!accId) {
|
|
40
|
-
throw new Error('Cloudflare account ID not configured. Set CLOUDFLARE_ACCOUNT_ID or call configureCloudflare()');
|
|
41
|
-
}
|
|
42
|
-
if (!gwId) {
|
|
43
|
-
throw new Error('Cloudflare AI Gateway ID not configured. Set CLOUDFLARE_AI_GATEWAY_ID or call configureCloudflare()');
|
|
44
|
-
}
|
|
45
|
-
if (!token) {
|
|
46
|
-
throw new Error('Cloudflare API token not configured. Set CLOUDFLARE_API_TOKEN or call configureCloudflare()');
|
|
47
|
-
}
|
|
48
|
-
return { accountId: accId, gatewayId: gwId, apiToken: token };
|
|
49
|
-
}
|
|
50
|
-
async function cloudflareRequest(method, path, body) {
|
|
51
|
-
const config = getConfig();
|
|
52
|
-
const url = `${baseUrl}${path}`;
|
|
53
|
-
const response = await fetch(url, {
|
|
54
|
-
method,
|
|
55
|
-
headers: {
|
|
56
|
-
Authorization: `Bearer ${config.apiToken}`,
|
|
57
|
-
'Content-Type': 'application/json',
|
|
58
|
-
},
|
|
59
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
60
|
-
});
|
|
61
|
-
if (!response.ok) {
|
|
62
|
-
const error = await response.text();
|
|
63
|
-
throw new Error(`Cloudflare API error: ${response.status} ${error}`);
|
|
64
|
-
}
|
|
65
|
-
const data = await response.json();
|
|
66
|
-
if (!data.success) {
|
|
67
|
-
throw new Error(`Cloudflare API error: ${JSON.stringify(data.errors)}`);
|
|
68
|
-
}
|
|
69
|
-
return data.result;
|
|
70
|
-
}
|
|
71
|
-
// ============================================================================
|
|
72
|
-
// In-memory job storage (for polling)
|
|
73
|
-
// ============================================================================
|
|
74
|
-
const pendingJobs = new Map();
|
|
75
|
-
let jobCounter = 0;
|
|
76
|
-
// ============================================================================
|
|
77
|
-
// Cloudflare Batch Adapter
|
|
78
|
-
// ============================================================================
|
|
79
|
-
/**
|
|
80
|
-
* Cloudflare batch adapter
|
|
81
|
-
*
|
|
82
|
-
* Note: Cloudflare's AI Gateway doesn't have a native batch API like OpenAI/Anthropic.
|
|
83
|
-
* This adapter implements batch processing by:
|
|
84
|
-
* 1. Sending requests concurrently through the gateway
|
|
85
|
-
* 2. Utilizing Cloudflare's caching and rate limiting
|
|
86
|
-
* 3. Tracking job state locally (or in D1/KV for production)
|
|
87
|
-
*
|
|
88
|
-
* For true async batch processing, consider using Cloudflare Queues + Workers.
|
|
89
|
-
*/
|
|
90
|
-
const cloudflareAdapter = {
|
|
91
|
-
async submit(items, options) {
|
|
92
|
-
const config = getConfig();
|
|
93
|
-
const jobId = `cf_batch_${++jobCounter}_${Date.now()}`;
|
|
94
|
-
const model = options.model || 'mistral/mistral-7b-instruct-v0.1';
|
|
95
|
-
// Store job state
|
|
96
|
-
pendingJobs.set(jobId, {
|
|
97
|
-
items,
|
|
98
|
-
options,
|
|
99
|
-
results: [],
|
|
100
|
-
status: 'pending',
|
|
101
|
-
createdAt: new Date(),
|
|
102
|
-
});
|
|
103
|
-
// Process requests concurrently (Cloudflare handles rate limiting)
|
|
104
|
-
const completion = processCloudflareRequests(jobId, items, config, model, options);
|
|
105
|
-
const job = {
|
|
106
|
-
id: jobId,
|
|
107
|
-
provider: 'cloudflare',
|
|
108
|
-
status: 'pending',
|
|
109
|
-
totalItems: items.length,
|
|
110
|
-
completedItems: 0,
|
|
111
|
-
failedItems: 0,
|
|
112
|
-
createdAt: new Date(),
|
|
113
|
-
webhookUrl: options.webhookUrl,
|
|
114
|
-
};
|
|
115
|
-
return { job, completion };
|
|
116
|
-
},
|
|
117
|
-
async getStatus(batchId) {
|
|
118
|
-
const job = pendingJobs.get(batchId);
|
|
119
|
-
if (!job) {
|
|
120
|
-
throw new Error(`Batch not found: ${batchId}`);
|
|
121
|
-
}
|
|
122
|
-
const completedItems = job.results.filter((r) => r.status === 'completed').length;
|
|
123
|
-
const failedItems = job.results.filter((r) => r.status === 'failed').length;
|
|
124
|
-
return {
|
|
125
|
-
id: batchId,
|
|
126
|
-
provider: 'cloudflare',
|
|
127
|
-
status: job.status,
|
|
128
|
-
totalItems: job.items.length,
|
|
129
|
-
completedItems,
|
|
130
|
-
failedItems,
|
|
131
|
-
createdAt: job.createdAt,
|
|
132
|
-
completedAt: job.completedAt,
|
|
133
|
-
};
|
|
134
|
-
},
|
|
135
|
-
async cancel(batchId) {
|
|
136
|
-
const job = pendingJobs.get(batchId);
|
|
137
|
-
if (job) {
|
|
138
|
-
job.status = 'cancelled';
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
async getResults(batchId) {
|
|
142
|
-
const job = pendingJobs.get(batchId);
|
|
143
|
-
if (!job) {
|
|
144
|
-
throw new Error(`Batch not found: ${batchId}`);
|
|
145
|
-
}
|
|
146
|
-
return job.results;
|
|
147
|
-
},
|
|
148
|
-
async waitForCompletion(batchId, pollInterval = 1000) {
|
|
149
|
-
const job = pendingJobs.get(batchId);
|
|
150
|
-
if (!job) {
|
|
151
|
-
throw new Error(`Batch not found: ${batchId}`);
|
|
152
|
-
}
|
|
153
|
-
while (job.status !== 'completed' && job.status !== 'failed' && job.status !== 'cancelled') {
|
|
154
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
155
|
-
}
|
|
156
|
-
return job.results;
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
// ============================================================================
|
|
160
|
-
// Processing
|
|
161
|
-
// ============================================================================
|
|
162
|
-
async function processCloudflareRequests(jobId, items, config, model, options) {
|
|
163
|
-
const job = pendingJobs.get(jobId);
|
|
164
|
-
if (!job) {
|
|
165
|
-
throw new Error(`Job not found: ${jobId}`);
|
|
166
|
-
}
|
|
167
|
-
job.status = 'in_progress';
|
|
168
|
-
// Process all requests concurrently with concurrency limit
|
|
169
|
-
const CONCURRENCY = 10;
|
|
170
|
-
const results = [];
|
|
171
|
-
for (let i = 0; i < items.length; i += CONCURRENCY) {
|
|
172
|
-
const batch = items.slice(i, i + CONCURRENCY);
|
|
173
|
-
const batchResults = await Promise.all(batch.map(async (item) => {
|
|
174
|
-
try {
|
|
175
|
-
const result = await processCloudflareItem(item, config, model);
|
|
176
|
-
return result;
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
return {
|
|
180
|
-
id: item.id,
|
|
181
|
-
customId: item.id,
|
|
182
|
-
status: 'failed',
|
|
183
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
}));
|
|
187
|
-
results.push(...batchResults);
|
|
188
|
-
job.results = results;
|
|
189
|
-
}
|
|
190
|
-
job.status = results.every((r) => r.status === 'completed') ? 'completed' : 'failed';
|
|
191
|
-
job.completedAt = new Date();
|
|
192
|
-
return results;
|
|
193
|
-
}
|
|
194
|
-
async function processCloudflareItem(item, config, model) {
|
|
195
|
-
// Route through AI Gateway
|
|
196
|
-
const gatewayUrl = `https://gateway.ai.cloudflare.com/v1/${config.accountId}/${config.gatewayId}`;
|
|
197
|
-
// Determine provider from model
|
|
198
|
-
let provider = 'workers-ai';
|
|
199
|
-
let endpoint = '';
|
|
200
|
-
if (model.startsWith('openai/') || model.startsWith('gpt-')) {
|
|
201
|
-
provider = 'openai';
|
|
202
|
-
endpoint = '/chat/completions';
|
|
203
|
-
}
|
|
204
|
-
else if (model.startsWith('anthropic/') || model.startsWith('claude-')) {
|
|
205
|
-
provider = 'anthropic';
|
|
206
|
-
endpoint = '/messages';
|
|
207
|
-
}
|
|
208
|
-
else if (model.startsWith('@cf/') || model.startsWith('workers-ai/')) {
|
|
209
|
-
provider = 'workers-ai';
|
|
210
|
-
endpoint = `/ai/run/${model.replace('workers-ai/', '').replace('@cf/', '')}`;
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
// Default to OpenAI-compatible
|
|
214
|
-
provider = 'openai';
|
|
215
|
-
endpoint = '/chat/completions';
|
|
216
|
-
}
|
|
217
|
-
const url = `${gatewayUrl}/${provider}${endpoint}`;
|
|
218
|
-
const messages = [
|
|
219
|
-
...(item.options?.system ? [{ role: 'system', content: item.options.system }] : []),
|
|
220
|
-
{ role: 'user', content: item.prompt },
|
|
221
|
-
];
|
|
222
|
-
const body = {
|
|
223
|
-
model: model.replace(`${provider}/`, ''),
|
|
224
|
-
messages,
|
|
225
|
-
max_tokens: item.options?.maxTokens || 4096,
|
|
226
|
-
temperature: item.options?.temperature,
|
|
227
|
-
};
|
|
228
|
-
// Add JSON mode if schema is provided
|
|
229
|
-
if (item.schema) {
|
|
230
|
-
body.response_format = { type: 'json_object' };
|
|
231
|
-
}
|
|
232
|
-
const response = await fetch(url, {
|
|
233
|
-
method: 'POST',
|
|
234
|
-
headers: {
|
|
235
|
-
'cf-aig-authorization': `Bearer ${config.apiToken}`,
|
|
236
|
-
'Content-Type': 'application/json',
|
|
237
|
-
},
|
|
238
|
-
body: JSON.stringify(body),
|
|
239
|
-
});
|
|
240
|
-
if (!response.ok) {
|
|
241
|
-
const error = await response.text();
|
|
242
|
-
throw new Error(`Cloudflare Gateway error: ${response.status} ${error}`);
|
|
243
|
-
}
|
|
244
|
-
const data = await response.json();
|
|
245
|
-
// Extract content based on response format
|
|
246
|
-
let content;
|
|
247
|
-
if (data.choices?.[0]?.message?.content) {
|
|
248
|
-
// OpenAI format
|
|
249
|
-
content = data.choices[0].message.content;
|
|
250
|
-
}
|
|
251
|
-
else if (data.content?.[0]?.text) {
|
|
252
|
-
// Anthropic format
|
|
253
|
-
content = data.content[0].text;
|
|
254
|
-
}
|
|
255
|
-
else if (data.response) {
|
|
256
|
-
// Workers AI format
|
|
257
|
-
content = data.response;
|
|
258
|
-
}
|
|
259
|
-
let result = content;
|
|
260
|
-
// Try to parse JSON if schema was provided
|
|
261
|
-
if (item.schema && content) {
|
|
262
|
-
try {
|
|
263
|
-
result = JSON.parse(content);
|
|
264
|
-
}
|
|
265
|
-
catch {
|
|
266
|
-
// Keep as string
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return {
|
|
270
|
-
id: item.id,
|
|
271
|
-
customId: item.id,
|
|
272
|
-
status: 'completed',
|
|
273
|
-
result,
|
|
274
|
-
usage: data.usage
|
|
275
|
-
? {
|
|
276
|
-
promptTokens: data.usage.prompt_tokens,
|
|
277
|
-
completionTokens: data.usage.completion_tokens,
|
|
278
|
-
totalTokens: data.usage.total_tokens,
|
|
279
|
-
}
|
|
280
|
-
: undefined,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
// ============================================================================
|
|
284
|
-
// Register Adapter
|
|
285
|
-
// ============================================================================
|
|
286
|
-
registerBatchAdapter('cloudflare', cloudflareAdapter);
|
|
287
|
-
export { cloudflareAdapter };
|
package/src/batch/google.js
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Google GenAI (Gemini) Adapter
|
|
3
|
-
*
|
|
4
|
-
* Implements processing using Google's Generative AI API (Gemini models).
|
|
5
|
-
* Google doesn't have a native batch API like OpenAI/Anthropic, so this
|
|
6
|
-
* implements concurrent processing for the flex tier.
|
|
7
|
-
*
|
|
8
|
-
* @see https://ai.google.dev/gemini-api/docs
|
|
9
|
-
*
|
|
10
|
-
* @packageDocumentation
|
|
11
|
-
*/
|
|
12
|
-
import { registerBatchAdapter, registerFlexAdapter, } from '../batch-queue.js';
|
|
13
|
-
// ============================================================================
|
|
14
|
-
// Google GenAI Client Configuration
|
|
15
|
-
// ============================================================================
|
|
16
|
-
let googleApiKey;
|
|
17
|
-
let googleBaseUrl = 'https://generativelanguage.googleapis.com/v1beta';
|
|
18
|
-
// AI Gateway configuration (optional - for routing through Cloudflare AI Gateway)
|
|
19
|
-
let gatewayUrl;
|
|
20
|
-
let gatewayToken;
|
|
21
|
-
/**
|
|
22
|
-
* Configure the Google GenAI client
|
|
23
|
-
*/
|
|
24
|
-
export function configureGoogleGenAI(options) {
|
|
25
|
-
if (options.apiKey)
|
|
26
|
-
googleApiKey = options.apiKey;
|
|
27
|
-
if (options.baseUrl)
|
|
28
|
-
googleBaseUrl = options.baseUrl;
|
|
29
|
-
if (options.gatewayUrl)
|
|
30
|
-
gatewayUrl = options.gatewayUrl;
|
|
31
|
-
if (options.gatewayToken)
|
|
32
|
-
gatewayToken = options.gatewayToken;
|
|
33
|
-
}
|
|
34
|
-
function getConfig() {
|
|
35
|
-
// Check for AI Gateway configuration
|
|
36
|
-
const gwUrl = gatewayUrl || process.env.AI_GATEWAY_URL;
|
|
37
|
-
const gwToken = gatewayToken || process.env.AI_GATEWAY_TOKEN;
|
|
38
|
-
// If using gateway, we don't need a direct API key
|
|
39
|
-
if (gwUrl && gwToken) {
|
|
40
|
-
return {
|
|
41
|
-
apiKey: '',
|
|
42
|
-
baseUrl: googleBaseUrl,
|
|
43
|
-
gatewayUrl: gwUrl,
|
|
44
|
-
gatewayToken: gwToken,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
const key = googleApiKey || process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY;
|
|
48
|
-
if (!key) {
|
|
49
|
-
throw new Error('Google API key not configured. Set GOOGLE_API_KEY or GEMINI_API_KEY, or use AI_GATEWAY_URL and AI_GATEWAY_TOKEN');
|
|
50
|
-
}
|
|
51
|
-
return { apiKey: key, baseUrl: googleBaseUrl, gatewayUrl: undefined, gatewayToken: undefined };
|
|
52
|
-
}
|
|
53
|
-
// ============================================================================
|
|
54
|
-
// In-memory job tracking
|
|
55
|
-
// ============================================================================
|
|
56
|
-
const pendingJobs = new Map();
|
|
57
|
-
let jobCounter = 0;
|
|
58
|
-
// ============================================================================
|
|
59
|
-
// Google GenAI Batch Adapter
|
|
60
|
-
// ============================================================================
|
|
61
|
-
/**
|
|
62
|
-
* Google GenAI batch adapter
|
|
63
|
-
*
|
|
64
|
-
* Note: Google doesn't have a native batch API like OpenAI/Anthropic.
|
|
65
|
-
* This adapter implements batch processing via concurrent requests.
|
|
66
|
-
* For true async batch processing, consider using Google Cloud Batch
|
|
67
|
-
* with Vertex AI.
|
|
68
|
-
*/
|
|
69
|
-
const googleAdapter = {
|
|
70
|
-
async submit(items, options) {
|
|
71
|
-
const jobId = `google_batch_${++jobCounter}_${Date.now()}`;
|
|
72
|
-
const model = options.model || 'gemini-2.0-flash';
|
|
73
|
-
// Store job state
|
|
74
|
-
pendingJobs.set(jobId, {
|
|
75
|
-
items,
|
|
76
|
-
options,
|
|
77
|
-
results: [],
|
|
78
|
-
status: 'pending',
|
|
79
|
-
createdAt: new Date(),
|
|
80
|
-
});
|
|
81
|
-
// Process requests concurrently
|
|
82
|
-
const completion = processGoogleRequestsConcurrently(jobId, items, model, options);
|
|
83
|
-
const job = {
|
|
84
|
-
id: jobId,
|
|
85
|
-
provider: 'google',
|
|
86
|
-
status: 'pending',
|
|
87
|
-
totalItems: items.length,
|
|
88
|
-
completedItems: 0,
|
|
89
|
-
failedItems: 0,
|
|
90
|
-
createdAt: new Date(),
|
|
91
|
-
webhookUrl: options.webhookUrl,
|
|
92
|
-
};
|
|
93
|
-
return { job, completion };
|
|
94
|
-
},
|
|
95
|
-
async getStatus(batchId) {
|
|
96
|
-
const job = pendingJobs.get(batchId);
|
|
97
|
-
if (!job) {
|
|
98
|
-
throw new Error(`Batch not found: ${batchId}`);
|
|
99
|
-
}
|
|
100
|
-
const completedItems = job.results.filter((r) => r.status === 'completed').length;
|
|
101
|
-
const failedItems = job.results.filter((r) => r.status === 'failed').length;
|
|
102
|
-
return {
|
|
103
|
-
id: batchId,
|
|
104
|
-
provider: 'google',
|
|
105
|
-
status: job.status,
|
|
106
|
-
totalItems: job.items.length,
|
|
107
|
-
completedItems,
|
|
108
|
-
failedItems,
|
|
109
|
-
createdAt: job.createdAt,
|
|
110
|
-
completedAt: job.completedAt,
|
|
111
|
-
};
|
|
112
|
-
},
|
|
113
|
-
async cancel(batchId) {
|
|
114
|
-
const job = pendingJobs.get(batchId);
|
|
115
|
-
if (job) {
|
|
116
|
-
job.status = 'cancelled';
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
async getResults(batchId) {
|
|
120
|
-
const job = pendingJobs.get(batchId);
|
|
121
|
-
if (!job) {
|
|
122
|
-
throw new Error(`Batch not found: ${batchId}`);
|
|
123
|
-
}
|
|
124
|
-
return job.results;
|
|
125
|
-
},
|
|
126
|
-
async waitForCompletion(batchId, pollInterval = 1000) {
|
|
127
|
-
const job = pendingJobs.get(batchId);
|
|
128
|
-
if (!job) {
|
|
129
|
-
throw new Error(`Batch not found: ${batchId}`);
|
|
130
|
-
}
|
|
131
|
-
while (job.status !== 'completed' && job.status !== 'failed' && job.status !== 'cancelled') {
|
|
132
|
-
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
133
|
-
}
|
|
134
|
-
return job.results;
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
// ============================================================================
|
|
138
|
-
// Google GenAI Flex Adapter
|
|
139
|
-
// ============================================================================
|
|
140
|
-
/**
|
|
141
|
-
* Google GenAI Flex Adapter
|
|
142
|
-
*
|
|
143
|
-
* Implements concurrent processing for medium-sized batches.
|
|
144
|
-
* Uses the Gemini API for fast turnaround.
|
|
145
|
-
*/
|
|
146
|
-
const googleFlexAdapter = {
|
|
147
|
-
async submitFlex(items, options) {
|
|
148
|
-
const model = options.model || 'gemini-2.0-flash';
|
|
149
|
-
const CONCURRENCY = 10;
|
|
150
|
-
const results = [];
|
|
151
|
-
// Process items concurrently
|
|
152
|
-
for (let i = 0; i < items.length; i += CONCURRENCY) {
|
|
153
|
-
const batch = items.slice(i, i + CONCURRENCY);
|
|
154
|
-
const batchResults = await Promise.all(batch.map(async (item) => {
|
|
155
|
-
try {
|
|
156
|
-
return await processGoogleItem(item, model);
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
return {
|
|
160
|
-
id: item.id,
|
|
161
|
-
customId: item.id,
|
|
162
|
-
status: 'failed',
|
|
163
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
}));
|
|
167
|
-
results.push(...batchResults);
|
|
168
|
-
}
|
|
169
|
-
return results;
|
|
170
|
-
},
|
|
171
|
-
};
|
|
172
|
-
// ============================================================================
|
|
173
|
-
// Processing
|
|
174
|
-
// ============================================================================
|
|
175
|
-
async function processGoogleRequestsConcurrently(jobId, items, model, options) {
|
|
176
|
-
const job = pendingJobs.get(jobId);
|
|
177
|
-
if (!job) {
|
|
178
|
-
throw new Error(`Job not found: ${jobId}`);
|
|
179
|
-
}
|
|
180
|
-
job.status = 'in_progress';
|
|
181
|
-
const CONCURRENCY = 10;
|
|
182
|
-
const results = [];
|
|
183
|
-
for (let i = 0; i < items.length; i += CONCURRENCY) {
|
|
184
|
-
const batch = items.slice(i, i + CONCURRENCY);
|
|
185
|
-
const batchResults = await Promise.all(batch.map(async (item) => {
|
|
186
|
-
try {
|
|
187
|
-
return await processGoogleItem(item, model);
|
|
188
|
-
}
|
|
189
|
-
catch (error) {
|
|
190
|
-
return {
|
|
191
|
-
id: item.id,
|
|
192
|
-
customId: item.id,
|
|
193
|
-
status: 'failed',
|
|
194
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
}));
|
|
198
|
-
results.push(...batchResults);
|
|
199
|
-
job.results = results;
|
|
200
|
-
}
|
|
201
|
-
job.status = results.every((r) => r.status === 'completed') ? 'completed' : 'failed';
|
|
202
|
-
job.completedAt = new Date();
|
|
203
|
-
return results;
|
|
204
|
-
}
|
|
205
|
-
async function processGoogleItem(item, model) {
|
|
206
|
-
const config = getConfig();
|
|
207
|
-
// Check if using AI Gateway
|
|
208
|
-
if (config.gatewayUrl && config.gatewayToken) {
|
|
209
|
-
return processGoogleItemViaGateway(item, config, model);
|
|
210
|
-
}
|
|
211
|
-
// Build the model name (add models/ prefix if not present)
|
|
212
|
-
const modelName = model.startsWith('models/') ? model : `models/${model}`;
|
|
213
|
-
const url = `${config.baseUrl}/${modelName}:generateContent?key=${config.apiKey}`;
|
|
214
|
-
// Build messages
|
|
215
|
-
const contents = [];
|
|
216
|
-
// Add system instruction as a user message if provided (Gemini handles this differently)
|
|
217
|
-
if (item.options?.system) {
|
|
218
|
-
contents.push({
|
|
219
|
-
role: 'user',
|
|
220
|
-
parts: [{ text: `System instruction: ${item.options.system}\n\nUser request: ${item.prompt}` }],
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
contents.push({
|
|
225
|
-
role: 'user',
|
|
226
|
-
parts: [{ text: item.prompt }],
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
const body = {
|
|
230
|
-
contents,
|
|
231
|
-
generationConfig: {
|
|
232
|
-
maxOutputTokens: item.options?.maxTokens || 8192,
|
|
233
|
-
temperature: item.options?.temperature,
|
|
234
|
-
},
|
|
235
|
-
};
|
|
236
|
-
// Add JSON mode if schema is provided
|
|
237
|
-
if (item.schema) {
|
|
238
|
-
body.generationConfig = {
|
|
239
|
-
...body.generationConfig,
|
|
240
|
-
responseMimeType: 'application/json',
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
const response = await fetch(url, {
|
|
244
|
-
method: 'POST',
|
|
245
|
-
headers: {
|
|
246
|
-
'Content-Type': 'application/json',
|
|
247
|
-
},
|
|
248
|
-
body: JSON.stringify(body),
|
|
249
|
-
});
|
|
250
|
-
if (!response.ok) {
|
|
251
|
-
const error = await response.text();
|
|
252
|
-
throw new Error(`Google GenAI API error: ${response.status} ${error}`);
|
|
253
|
-
}
|
|
254
|
-
const data = (await response.json());
|
|
255
|
-
// Extract content
|
|
256
|
-
const content = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
257
|
-
let result = content;
|
|
258
|
-
// Try to parse JSON if schema was provided or content looks like JSON
|
|
259
|
-
if (content && (item.schema || content.trim().startsWith('{') || content.trim().startsWith('['))) {
|
|
260
|
-
try {
|
|
261
|
-
result = JSON.parse(content);
|
|
262
|
-
}
|
|
263
|
-
catch {
|
|
264
|
-
// Keep as string
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return {
|
|
268
|
-
id: item.id,
|
|
269
|
-
customId: item.id,
|
|
270
|
-
status: 'completed',
|
|
271
|
-
result,
|
|
272
|
-
usage: data.usageMetadata
|
|
273
|
-
? {
|
|
274
|
-
promptTokens: data.usageMetadata.promptTokenCount,
|
|
275
|
-
completionTokens: data.usageMetadata.candidatesTokenCount,
|
|
276
|
-
totalTokens: data.usageMetadata.totalTokenCount,
|
|
277
|
-
}
|
|
278
|
-
: undefined,
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Process a Google GenAI item via Cloudflare AI Gateway
|
|
283
|
-
* Gateway URL format: {gateway_url}/google-ai-studio/v1beta/models/{model}:generateContent
|
|
284
|
-
*/
|
|
285
|
-
async function processGoogleItemViaGateway(item, config, model) {
|
|
286
|
-
// AI Gateway URL for Google AI Studio
|
|
287
|
-
// Format: {gateway_url}/google-ai-studio/v1beta/models/{model}:generateContent
|
|
288
|
-
const modelName = model.startsWith('models/') ? model.replace('models/', '') : model;
|
|
289
|
-
const url = `${config.gatewayUrl}/google-ai-studio/v1beta/models/${modelName}:generateContent`;
|
|
290
|
-
// Build messages
|
|
291
|
-
const contents = [];
|
|
292
|
-
if (item.options?.system) {
|
|
293
|
-
contents.push({
|
|
294
|
-
role: 'user',
|
|
295
|
-
parts: [{ text: `System instruction: ${item.options.system}\n\nUser request: ${item.prompt}` }],
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
contents.push({
|
|
300
|
-
role: 'user',
|
|
301
|
-
parts: [{ text: item.prompt }],
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
const body = {
|
|
305
|
-
contents,
|
|
306
|
-
generationConfig: {
|
|
307
|
-
maxOutputTokens: item.options?.maxTokens || 8192,
|
|
308
|
-
temperature: item.options?.temperature,
|
|
309
|
-
},
|
|
310
|
-
};
|
|
311
|
-
if (item.schema) {
|
|
312
|
-
body.generationConfig = {
|
|
313
|
-
...body.generationConfig,
|
|
314
|
-
responseMimeType: 'application/json',
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
const response = await fetch(url, {
|
|
318
|
-
method: 'POST',
|
|
319
|
-
headers: {
|
|
320
|
-
'cf-aig-authorization': `Bearer ${config.gatewayToken}`,
|
|
321
|
-
'Content-Type': 'application/json',
|
|
322
|
-
},
|
|
323
|
-
body: JSON.stringify(body),
|
|
324
|
-
});
|
|
325
|
-
if (!response.ok) {
|
|
326
|
-
const error = await response.text();
|
|
327
|
-
throw new Error(`Google GenAI via Gateway error: ${response.status} ${error}`);
|
|
328
|
-
}
|
|
329
|
-
const data = (await response.json());
|
|
330
|
-
const content = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
331
|
-
let result = content;
|
|
332
|
-
if (content && (item.schema || content.trim().startsWith('{') || content.trim().startsWith('['))) {
|
|
333
|
-
try {
|
|
334
|
-
result = JSON.parse(content);
|
|
335
|
-
}
|
|
336
|
-
catch {
|
|
337
|
-
// Keep as string
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
return {
|
|
341
|
-
id: item.id,
|
|
342
|
-
customId: item.id,
|
|
343
|
-
status: 'completed',
|
|
344
|
-
result,
|
|
345
|
-
usage: data.usageMetadata
|
|
346
|
-
? {
|
|
347
|
-
promptTokens: data.usageMetadata.promptTokenCount,
|
|
348
|
-
completionTokens: data.usageMetadata.candidatesTokenCount,
|
|
349
|
-
totalTokens: data.usageMetadata.totalTokenCount,
|
|
350
|
-
}
|
|
351
|
-
: undefined,
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
// ============================================================================
|
|
355
|
-
// Register Adapters
|
|
356
|
-
// ============================================================================
|
|
357
|
-
registerBatchAdapter('google', googleAdapter);
|
|
358
|
-
registerFlexAdapter('google', googleFlexAdapter);
|
|
359
|
-
export { googleAdapter, googleFlexAdapter };
|
package/src/batch/index.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Batch Adapters Index
|
|
3
|
-
*
|
|
4
|
-
* Import specific adapters to register them:
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```ts
|
|
8
|
-
* // Import to register the OpenAI batch adapter
|
|
9
|
-
* import 'ai-functions/batch/openai'
|
|
10
|
-
*
|
|
11
|
-
* // Import to register the Anthropic batch adapter
|
|
12
|
-
* import 'ai-functions/batch/anthropic'
|
|
13
|
-
*
|
|
14
|
-
* // Import to register the Cloudflare adapter
|
|
15
|
-
* import 'ai-functions/batch/cloudflare'
|
|
16
|
-
*
|
|
17
|
-
* // Import to register the AWS Bedrock adapter
|
|
18
|
-
* import 'ai-functions/batch/bedrock'
|
|
19
|
-
*
|
|
20
|
-
* // Or import the in-memory adapter for testing
|
|
21
|
-
* import 'ai-functions/batch/memory'
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* @packageDocumentation
|
|
25
|
-
*/
|
|
26
|
-
export * from './openai.js';
|
|
27
|
-
export * from './anthropic.js';
|
|
28
|
-
export * from './cloudflare.js';
|
|
29
|
-
export * from './bedrock.js';
|
|
30
|
-
export * from './memory.js';
|