ai-functions 0.2.19 → 0.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 +5 -0
- package/.turbo/turbo-test.log +105 -0
- package/README.md +232 -37
- package/TODO.md +138 -0
- package/dist/ai-promise.d.ts +219 -0
- package/dist/ai-promise.d.ts.map +1 -0
- package/dist/ai-promise.js +610 -0
- package/dist/ai-promise.js.map +1 -0
- package/dist/ai.d.ts +285 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +842 -0
- package/dist/ai.js.map +1 -0
- package/dist/batch/anthropic.d.ts +23 -0
- package/dist/batch/anthropic.d.ts.map +1 -0
- package/dist/batch/anthropic.js +257 -0
- package/dist/batch/anthropic.js.map +1 -0
- package/dist/batch/bedrock.d.ts +64 -0
- package/dist/batch/bedrock.d.ts.map +1 -0
- package/dist/batch/bedrock.js +586 -0
- package/dist/batch/bedrock.js.map +1 -0
- package/dist/batch/cloudflare.d.ts +37 -0
- package/dist/batch/cloudflare.d.ts.map +1 -0
- package/dist/batch/cloudflare.js +289 -0
- package/dist/batch/cloudflare.js.map +1 -0
- package/dist/batch/google.d.ts +41 -0
- package/dist/batch/google.d.ts.map +1 -0
- package/dist/batch/google.js +360 -0
- package/dist/batch/google.js.map +1 -0
- package/dist/batch/index.d.ts +31 -0
- package/dist/batch/index.d.ts.map +1 -0
- package/dist/batch/index.js +31 -0
- package/dist/batch/index.js.map +1 -0
- package/dist/batch/memory.d.ts +44 -0
- package/dist/batch/memory.d.ts.map +1 -0
- package/dist/batch/memory.js +188 -0
- package/dist/batch/memory.js.map +1 -0
- package/dist/batch/openai.d.ts +37 -0
- package/dist/batch/openai.d.ts.map +1 -0
- package/dist/batch/openai.js +403 -0
- package/dist/batch/openai.js.map +1 -0
- package/dist/batch-map.d.ts +125 -0
- package/dist/batch-map.d.ts.map +1 -0
- package/dist/batch-map.js +406 -0
- package/dist/batch-map.js.map +1 -0
- package/dist/batch-queue.d.ts +273 -0
- package/dist/batch-queue.d.ts.map +1 -0
- package/dist/batch-queue.js +271 -0
- package/dist/batch-queue.js.map +1 -0
- package/dist/context.d.ts +133 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +267 -0
- package/dist/context.js.map +1 -0
- package/dist/embeddings.d.ts +123 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +170 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/eval/index.d.ts +8 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +8 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/models.d.ts +66 -0
- package/dist/eval/models.d.ts.map +1 -0
- package/dist/eval/models.js +120 -0
- package/dist/eval/models.js.map +1 -0
- package/dist/eval/runner.d.ts +64 -0
- package/dist/eval/runner.d.ts.map +1 -0
- package/dist/eval/runner.js +148 -0
- package/dist/eval/runner.js.map +1 -0
- package/dist/generate.d.ts +168 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +174 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/primitives.d.ts +292 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +471 -0
- package/dist/primitives.js.map +1 -0
- package/dist/providers/cloudflare.d.ts +9 -0
- package/dist/providers/cloudflare.d.ts.map +1 -0
- package/dist/providers/cloudflare.js +9 -0
- package/dist/providers/cloudflare.js.map +1 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +9 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/schema.d.ts +54 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +109 -0
- package/dist/schema.js.map +1 -0
- package/dist/template.d.ts +73 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +129 -0
- package/dist/template.js.map +1 -0
- package/dist/types.d.ts +481 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/evalite.config.ts +19 -0
- package/evals/README.md +212 -0
- package/evals/classification.eval.ts +108 -0
- package/evals/marketing.eval.ts +370 -0
- package/evals/math.eval.ts +94 -0
- package/evals/run-evals.ts +166 -0
- package/evals/structured-output.eval.ts +143 -0
- package/evals/writing.eval.ts +117 -0
- package/examples/batch-blog-posts.ts +160 -0
- package/package.json +59 -43
- package/src/ai-promise.ts +784 -0
- package/src/ai.ts +1183 -0
- package/src/batch/anthropic.ts +375 -0
- package/src/batch/bedrock.ts +801 -0
- package/src/batch/cloudflare.ts +421 -0
- package/src/batch/google.ts +491 -0
- package/src/batch/index.ts +31 -0
- package/src/batch/memory.ts +253 -0
- package/src/batch/openai.ts +557 -0
- package/src/batch-map.ts +534 -0
- package/src/batch-queue.ts +493 -0
- package/src/context.ts +332 -0
- package/src/embeddings.ts +244 -0
- package/src/eval/index.ts +8 -0
- package/src/eval/models.ts +158 -0
- package/src/eval/runner.ts +217 -0
- package/src/generate.ts +245 -0
- package/src/index.ts +154 -0
- package/src/primitives.ts +612 -0
- package/src/providers/cloudflare.ts +15 -0
- package/src/providers/index.ts +14 -0
- package/src/schema.ts +147 -0
- package/src/template.ts +209 -0
- package/src/types.ts +540 -0
- package/test/README.md +105 -0
- package/test/ai-proxy.test.ts +192 -0
- package/test/async-iterators.test.ts +327 -0
- package/test/batch-background.test.ts +482 -0
- package/test/batch-blog-posts.test.ts +387 -0
- package/test/blog-generation.test.ts +510 -0
- package/test/browse-read.test.ts +611 -0
- package/test/core-functions.test.ts +694 -0
- package/test/decide.test.ts +393 -0
- package/test/define.test.ts +274 -0
- package/test/e2e-bedrock-manual.ts +163 -0
- package/test/e2e-bedrock.test.ts +191 -0
- package/test/e2e-flex-gateway.ts +157 -0
- package/test/e2e-flex-manual.ts +183 -0
- package/test/e2e-flex.test.ts +209 -0
- package/test/e2e-google-manual.ts +178 -0
- package/test/e2e-google.test.ts +216 -0
- package/test/embeddings.test.ts +284 -0
- package/test/evals/define-function.eval.test.ts +379 -0
- package/test/evals/primitives.eval.test.ts +384 -0
- package/test/function-types.test.ts +492 -0
- package/test/generate-core.test.ts +319 -0
- package/test/generate.test.ts +163 -0
- package/test/implicit-batch.test.ts +422 -0
- package/test/schema.test.ts +109 -0
- package/test/tagged-templates.test.ts +302 -0
- package/tsconfig.json +8 -6
- package/vitest.config.ts +42 -0
- package/LICENSE +0 -21
- package/db/cache.ts +0 -6
- package/db/mongo.ts +0 -75
- package/dist/mjs/db/cache.d.ts +0 -1
- package/dist/mjs/db/cache.js +0 -5
- package/dist/mjs/db/mongo.d.ts +0 -31
- package/dist/mjs/db/mongo.js +0 -48
- package/dist/mjs/examples/data.d.ts +0 -1105
- package/dist/mjs/examples/data.js +0 -1105
- package/dist/mjs/functions/ai.d.ts +0 -20
- package/dist/mjs/functions/ai.js +0 -83
- package/dist/mjs/functions/ai.test.d.ts +0 -1
- package/dist/mjs/functions/ai.test.js +0 -29
- package/dist/mjs/functions/gpt.d.ts +0 -4
- package/dist/mjs/functions/gpt.js +0 -10
- package/dist/mjs/functions/list.d.ts +0 -7
- package/dist/mjs/functions/list.js +0 -72
- package/dist/mjs/index.d.ts +0 -3
- package/dist/mjs/index.js +0 -3
- package/dist/mjs/queue/kafka.d.ts +0 -0
- package/dist/mjs/queue/kafka.js +0 -1
- package/dist/mjs/queue/memory.d.ts +0 -0
- package/dist/mjs/queue/memory.js +0 -1
- package/dist/mjs/queue/mongo.d.ts +0 -30
- package/dist/mjs/queue/mongo.js +0 -42
- package/dist/mjs/streams/kafka.d.ts +0 -0
- package/dist/mjs/streams/kafka.js +0 -1
- package/dist/mjs/streams/memory.d.ts +0 -0
- package/dist/mjs/streams/memory.js +0 -1
- package/dist/mjs/streams/mongo.d.ts +0 -0
- package/dist/mjs/streams/mongo.js +0 -1
- package/dist/mjs/streams/types.d.ts +0 -0
- package/dist/mjs/streams/types.js +0 -1
- package/dist/mjs/types.d.ts +0 -11
- package/dist/mjs/types.js +0 -1
- package/dist/mjs/utils/completion.d.ts +0 -9
- package/dist/mjs/utils/completion.js +0 -20
- package/dist/mjs/utils/schema.d.ts +0 -10
- package/dist/mjs/utils/schema.js +0 -72
- package/dist/mjs/utils/schema.test.d.ts +0 -1
- package/dist/mjs/utils/schema.test.js +0 -60
- package/dist/mjs/utils/state.d.ts +0 -1
- package/dist/mjs/utils/state.js +0 -19
- package/examples/data.ts +0 -1105
- package/fixup +0 -11
- package/functions/ai.test.ts +0 -41
- package/functions/ai.ts +0 -115
- package/functions/gpt.ts +0 -12
- package/functions/list.ts +0 -84
- package/index.ts +0 -3
- package/queue/kafka.ts +0 -0
- package/queue/memory.ts +0 -0
- package/queue/mongo.ts +0 -88
- package/streams/kafka.ts +0 -0
- package/streams/memory.ts +0 -0
- package/streams/mongo.ts +0 -0
- package/streams/types.ts +0 -0
- package/tsconfig-backup.json +0 -105
- package/tsconfig-base.json +0 -26
- package/tsconfig-cjs.json +0 -8
- package/types.ts +0 -12
- package/utils/completion.ts +0 -28
- package/utils/schema.test.ts +0 -69
- package/utils/schema.ts +0 -74
- package/utils/state.ts +0 -23
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Message Batches API Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implements batch processing using Anthropic's Message Batches API:
|
|
5
|
+
* - 50% cost discount
|
|
6
|
+
* - 24-hour turnaround
|
|
7
|
+
* - Up to 10,000 requests per batch
|
|
8
|
+
*
|
|
9
|
+
* @see https://docs.anthropic.com/en/docs/build-with-claude/message-batches
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
registerBatchAdapter,
|
|
16
|
+
type BatchAdapter,
|
|
17
|
+
type BatchItem,
|
|
18
|
+
type BatchJob,
|
|
19
|
+
type BatchQueueOptions,
|
|
20
|
+
type BatchResult,
|
|
21
|
+
type BatchSubmitResult,
|
|
22
|
+
type BatchStatus,
|
|
23
|
+
} from '../batch-queue.js'
|
|
24
|
+
import { schema as convertSchema } from '../schema.js'
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Types
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
interface AnthropicBatchRequest {
|
|
31
|
+
custom_id: string
|
|
32
|
+
params: {
|
|
33
|
+
model: string
|
|
34
|
+
max_tokens: number
|
|
35
|
+
messages: Array<{ role: string; content: string }>
|
|
36
|
+
system?: string
|
|
37
|
+
temperature?: number
|
|
38
|
+
tool_choice?: { type: 'tool'; name: string }
|
|
39
|
+
tools?: Array<{
|
|
40
|
+
name: string
|
|
41
|
+
description: string
|
|
42
|
+
input_schema: Record<string, unknown>
|
|
43
|
+
}>
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface AnthropicBatchResult {
|
|
48
|
+
custom_id: string
|
|
49
|
+
result: {
|
|
50
|
+
type: 'succeeded' | 'errored' | 'canceled' | 'expired'
|
|
51
|
+
message?: {
|
|
52
|
+
id: string
|
|
53
|
+
content: Array<{
|
|
54
|
+
type: 'text' | 'tool_use'
|
|
55
|
+
text?: string
|
|
56
|
+
name?: string
|
|
57
|
+
input?: unknown
|
|
58
|
+
}>
|
|
59
|
+
usage: {
|
|
60
|
+
input_tokens: number
|
|
61
|
+
output_tokens: number
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
error?: {
|
|
65
|
+
type: string
|
|
66
|
+
message: string
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface AnthropicBatch {
|
|
72
|
+
id: string
|
|
73
|
+
type: 'message_batch'
|
|
74
|
+
processing_status: 'in_progress' | 'ended'
|
|
75
|
+
request_counts: {
|
|
76
|
+
processing: number
|
|
77
|
+
succeeded: number
|
|
78
|
+
errored: number
|
|
79
|
+
canceled: number
|
|
80
|
+
expired: number
|
|
81
|
+
}
|
|
82
|
+
ended_at: string | null
|
|
83
|
+
created_at: string
|
|
84
|
+
expires_at: string
|
|
85
|
+
cancel_initiated_at: string | null
|
|
86
|
+
results_url: string | null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// Anthropic Client
|
|
91
|
+
// ============================================================================
|
|
92
|
+
|
|
93
|
+
let anthropicApiKey: string | undefined
|
|
94
|
+
let anthropicBaseUrl = 'https://api.anthropic.com/v1'
|
|
95
|
+
const ANTHROPIC_VERSION = '2023-06-01'
|
|
96
|
+
const ANTHROPIC_BETA = 'message-batches-2024-09-24'
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Configure the Anthropic client
|
|
100
|
+
*/
|
|
101
|
+
export function configureAnthropic(options: { apiKey?: string; baseUrl?: string }): void {
|
|
102
|
+
if (options.apiKey) anthropicApiKey = options.apiKey
|
|
103
|
+
if (options.baseUrl) anthropicBaseUrl = options.baseUrl
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getApiKey(): string {
|
|
107
|
+
const key = anthropicApiKey || process.env.ANTHROPIC_API_KEY
|
|
108
|
+
if (!key) {
|
|
109
|
+
throw new Error('Anthropic API key not configured. Set ANTHROPIC_API_KEY or call configureAnthropic()')
|
|
110
|
+
}
|
|
111
|
+
return key
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function anthropicRequest<T>(
|
|
115
|
+
method: 'GET' | 'POST',
|
|
116
|
+
path: string,
|
|
117
|
+
body?: unknown
|
|
118
|
+
): Promise<T> {
|
|
119
|
+
const url = `${anthropicBaseUrl}${path}`
|
|
120
|
+
const response = await fetch(url, {
|
|
121
|
+
method,
|
|
122
|
+
headers: {
|
|
123
|
+
'x-api-key': getApiKey(),
|
|
124
|
+
'anthropic-version': ANTHROPIC_VERSION,
|
|
125
|
+
'anthropic-beta': ANTHROPIC_BETA,
|
|
126
|
+
'Content-Type': 'application/json',
|
|
127
|
+
},
|
|
128
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
const error = await response.text()
|
|
133
|
+
throw new Error(`Anthropic API error: ${response.status} ${error}`)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return response.json()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// Status Mapping
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
143
|
+
function mapStatus(batch: AnthropicBatch): BatchStatus {
|
|
144
|
+
if (batch.cancel_initiated_at) {
|
|
145
|
+
return batch.processing_status === 'ended' ? 'cancelled' : 'cancelling'
|
|
146
|
+
}
|
|
147
|
+
if (batch.processing_status === 'ended') {
|
|
148
|
+
return 'completed'
|
|
149
|
+
}
|
|
150
|
+
return 'in_progress'
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ============================================================================
|
|
154
|
+
// Anthropic Batch Adapter
|
|
155
|
+
// ============================================================================
|
|
156
|
+
|
|
157
|
+
const anthropicAdapter: BatchAdapter = {
|
|
158
|
+
async submit(items: BatchItem[], options: BatchQueueOptions): Promise<BatchSubmitResult> {
|
|
159
|
+
const model = options.model || 'claude-sonnet-4-20250514'
|
|
160
|
+
const maxTokens = 4096
|
|
161
|
+
|
|
162
|
+
// Build batch requests
|
|
163
|
+
const requests: AnthropicBatchRequest[] = items.map((item) => {
|
|
164
|
+
const request: AnthropicBatchRequest = {
|
|
165
|
+
custom_id: item.id,
|
|
166
|
+
params: {
|
|
167
|
+
model,
|
|
168
|
+
max_tokens: item.options?.maxTokens || maxTokens,
|
|
169
|
+
messages: [{ role: 'user', content: item.prompt }],
|
|
170
|
+
system: item.options?.system,
|
|
171
|
+
temperature: item.options?.temperature,
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Add JSON schema as a tool if provided
|
|
176
|
+
if (item.schema) {
|
|
177
|
+
const zodSchema = convertSchema(item.schema)
|
|
178
|
+
const jsonSchema = zodToJsonSchema(zodSchema)
|
|
179
|
+
|
|
180
|
+
request.params.tools = [
|
|
181
|
+
{
|
|
182
|
+
name: 'structured_response',
|
|
183
|
+
description: 'Generate a structured response matching the schema',
|
|
184
|
+
input_schema: jsonSchema,
|
|
185
|
+
},
|
|
186
|
+
]
|
|
187
|
+
request.params.tool_choice = { type: 'tool', name: 'structured_response' }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return request
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
// Create the batch
|
|
194
|
+
const batch = await anthropicRequest<AnthropicBatch>('POST', '/messages/batches', {
|
|
195
|
+
requests,
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
const job: BatchJob = {
|
|
199
|
+
id: batch.id,
|
|
200
|
+
provider: 'anthropic',
|
|
201
|
+
status: mapStatus(batch),
|
|
202
|
+
totalItems: items.length,
|
|
203
|
+
completedItems: batch.request_counts.succeeded,
|
|
204
|
+
failedItems: batch.request_counts.errored + batch.request_counts.expired + batch.request_counts.canceled,
|
|
205
|
+
createdAt: new Date(batch.created_at),
|
|
206
|
+
expiresAt: new Date(batch.expires_at),
|
|
207
|
+
webhookUrl: options.webhookUrl,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Create completion promise
|
|
211
|
+
const completion = this.waitForCompletion(batch.id)
|
|
212
|
+
|
|
213
|
+
return { job, completion }
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
async getStatus(batchId: string): Promise<BatchJob> {
|
|
217
|
+
const batch = await anthropicRequest<AnthropicBatch>('GET', `/messages/batches/${batchId}`)
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
id: batch.id,
|
|
221
|
+
provider: 'anthropic',
|
|
222
|
+
status: mapStatus(batch),
|
|
223
|
+
totalItems:
|
|
224
|
+
batch.request_counts.processing +
|
|
225
|
+
batch.request_counts.succeeded +
|
|
226
|
+
batch.request_counts.errored +
|
|
227
|
+
batch.request_counts.canceled +
|
|
228
|
+
batch.request_counts.expired,
|
|
229
|
+
completedItems: batch.request_counts.succeeded,
|
|
230
|
+
failedItems: batch.request_counts.errored + batch.request_counts.expired + batch.request_counts.canceled,
|
|
231
|
+
createdAt: new Date(batch.created_at),
|
|
232
|
+
completedAt: batch.ended_at ? new Date(batch.ended_at) : undefined,
|
|
233
|
+
expiresAt: new Date(batch.expires_at),
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
async cancel(batchId: string): Promise<void> {
|
|
238
|
+
await anthropicRequest('POST', `/messages/batches/${batchId}/cancel`)
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
async getResults(batchId: string): Promise<BatchResult[]> {
|
|
242
|
+
const status = await this.getStatus(batchId)
|
|
243
|
+
|
|
244
|
+
if (status.status !== 'completed' && status.status !== 'cancelled') {
|
|
245
|
+
throw new Error(`Batch not complete. Status: ${status.status}`)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Fetch results (Anthropic returns them directly via the API)
|
|
249
|
+
const batch = await anthropicRequest<AnthropicBatch>('GET', `/messages/batches/${batchId}`)
|
|
250
|
+
|
|
251
|
+
if (!batch.results_url) {
|
|
252
|
+
throw new Error('No results URL available')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Download results from the URL
|
|
256
|
+
const response = await fetch(batch.results_url, {
|
|
257
|
+
headers: {
|
|
258
|
+
'x-api-key': getApiKey(),
|
|
259
|
+
'anthropic-version': ANTHROPIC_VERSION,
|
|
260
|
+
'anthropic-beta': ANTHROPIC_BETA,
|
|
261
|
+
},
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
if (!response.ok) {
|
|
265
|
+
throw new Error(`Failed to fetch results: ${response.status}`)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const content = await response.text()
|
|
269
|
+
const lines = content.trim().split('\n')
|
|
270
|
+
const results: BatchResult[] = []
|
|
271
|
+
|
|
272
|
+
for (const line of lines) {
|
|
273
|
+
const result: AnthropicBatchResult = JSON.parse(line)
|
|
274
|
+
|
|
275
|
+
if (result.result.type === 'succeeded' && result.result.message) {
|
|
276
|
+
const message = result.result.message
|
|
277
|
+
let extractedResult: unknown
|
|
278
|
+
|
|
279
|
+
// Extract from tool use or text
|
|
280
|
+
const toolUse = message.content.find((c) => c.type === 'tool_use')
|
|
281
|
+
const textContent = message.content.find((c) => c.type === 'text')
|
|
282
|
+
|
|
283
|
+
if (toolUse?.input) {
|
|
284
|
+
extractedResult = toolUse.input
|
|
285
|
+
} else if (textContent?.text) {
|
|
286
|
+
// Try to parse as JSON
|
|
287
|
+
try {
|
|
288
|
+
extractedResult = JSON.parse(textContent.text)
|
|
289
|
+
} catch {
|
|
290
|
+
extractedResult = textContent.text
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
results.push({
|
|
295
|
+
id: result.custom_id,
|
|
296
|
+
customId: result.custom_id,
|
|
297
|
+
status: 'completed',
|
|
298
|
+
result: extractedResult,
|
|
299
|
+
usage: {
|
|
300
|
+
promptTokens: message.usage.input_tokens,
|
|
301
|
+
completionTokens: message.usage.output_tokens,
|
|
302
|
+
totalTokens: message.usage.input_tokens + message.usage.output_tokens,
|
|
303
|
+
},
|
|
304
|
+
})
|
|
305
|
+
} else {
|
|
306
|
+
results.push({
|
|
307
|
+
id: result.custom_id,
|
|
308
|
+
customId: result.custom_id,
|
|
309
|
+
status: 'failed',
|
|
310
|
+
error: result.result.error?.message || `Request ${result.result.type}`,
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return results
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
async waitForCompletion(batchId: string, pollInterval = 5000): Promise<BatchResult[]> {
|
|
319
|
+
while (true) {
|
|
320
|
+
const status = await this.getStatus(batchId)
|
|
321
|
+
|
|
322
|
+
if (status.status === 'completed' || status.status === 'cancelled') {
|
|
323
|
+
return this.getResults(batchId)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval))
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ============================================================================
|
|
332
|
+
// Helpers
|
|
333
|
+
// ============================================================================
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Simple Zod to JSON Schema converter
|
|
337
|
+
*/
|
|
338
|
+
function zodToJsonSchema(zodSchema: unknown): Record<string, unknown> {
|
|
339
|
+
const schema = zodSchema as { _def?: { typeName?: string; shape?: unknown } }
|
|
340
|
+
|
|
341
|
+
if (!schema._def) {
|
|
342
|
+
return { type: 'object' }
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const typeName = schema._def.typeName
|
|
346
|
+
|
|
347
|
+
switch (typeName) {
|
|
348
|
+
case 'ZodString':
|
|
349
|
+
return { type: 'string' }
|
|
350
|
+
case 'ZodNumber':
|
|
351
|
+
return { type: 'number' }
|
|
352
|
+
case 'ZodBoolean':
|
|
353
|
+
return { type: 'boolean' }
|
|
354
|
+
case 'ZodArray':
|
|
355
|
+
return { type: 'array', items: zodToJsonSchema((schema._def as any).type) }
|
|
356
|
+
case 'ZodObject': {
|
|
357
|
+
const shape = (schema._def as any).shape()
|
|
358
|
+
const properties: Record<string, unknown> = {}
|
|
359
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
360
|
+
properties[key] = zodToJsonSchema(value)
|
|
361
|
+
}
|
|
362
|
+
return { type: 'object', properties, required: Object.keys(properties) }
|
|
363
|
+
}
|
|
364
|
+
default:
|
|
365
|
+
return { type: 'object' }
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// ============================================================================
|
|
370
|
+
// Register Adapter
|
|
371
|
+
// ============================================================================
|
|
372
|
+
|
|
373
|
+
registerBatchAdapter('anthropic', anthropicAdapter)
|
|
374
|
+
|
|
375
|
+
export { anthropicAdapter }
|