@assemble-dev/providers 0.3.1 → 0.4.1
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/dist/index.cjs +429 -0
- package/dist/index.d.cts +36 -1
- package/dist/index.d.ts +36 -1
- package/dist/index.js +424 -0
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -44,11 +44,13 @@ __export(index_exports, {
|
|
|
44
44
|
buildAzureOpenAiChatRequestBody: () => buildAzureOpenAiChatRequestBody,
|
|
45
45
|
buildBedrockInvokeModelRequestBody: () => buildBedrockInvokeModelRequestBody,
|
|
46
46
|
buildBedrockInvokeModelUrl: () => buildBedrockInvokeModelUrl,
|
|
47
|
+
buildCloudflareWorkersAiChatCompletionsUrl: () => buildCloudflareWorkersAiChatCompletionsUrl,
|
|
47
48
|
buildGeminiResponseSchema: () => buildGeminiResponseSchema,
|
|
48
49
|
buildOpenAiRequestBody: () => buildOpenAiRequestBody,
|
|
49
50
|
buildOpenAiStructuredOutputJsonSchema: () => buildOpenAiStructuredOutputJsonSchema,
|
|
50
51
|
buildProviderCanceledError: () => buildProviderCanceledError,
|
|
51
52
|
calculateProviderRetryDelayMs: () => calculateProviderRetryDelayMs,
|
|
53
|
+
cloudflareWorkersAi: () => cloudflareWorkersAi,
|
|
52
54
|
convertZodSchemaToJsonSchema: () => convertZodSchemaToJsonSchema,
|
|
53
55
|
createAnthropicBatchClient: () => createAnthropicBatchClient,
|
|
54
56
|
defaultAnthropicBaseUrl: () => defaultAnthropicBaseUrl,
|
|
@@ -57,8 +59,10 @@ __export(index_exports, {
|
|
|
57
59
|
defaultAnthropicMaxOutputTokens: () => defaultAnthropicMaxOutputTokens,
|
|
58
60
|
defaultAzureOpenAiApiVersion: () => defaultAzureOpenAiApiVersion,
|
|
59
61
|
defaultBedrockMaxOutputTokens: () => defaultBedrockMaxOutputTokens,
|
|
62
|
+
defaultCloudflareApiBaseUrl: () => defaultCloudflareApiBaseUrl,
|
|
60
63
|
defaultGeminiBaseUrl: () => defaultGeminiBaseUrl,
|
|
61
64
|
defaultOpenAiBaseUrl: () => defaultOpenAiBaseUrl,
|
|
65
|
+
defaultOpenRouterBaseUrl: () => defaultOpenRouterBaseUrl,
|
|
62
66
|
defaultProviderRetryInitialDelayMs: () => defaultProviderRetryInitialDelayMs,
|
|
63
67
|
defaultProviderRetryMaxAttempts: () => defaultProviderRetryMaxAttempts,
|
|
64
68
|
defaultProviderRetryMaxDelayMs: () => defaultProviderRetryMaxDelayMs,
|
|
@@ -92,6 +96,7 @@ __export(index_exports, {
|
|
|
92
96
|
normalizeAzureOpenAiFinishReason: () => normalizeAzureOpenAiFinishReason,
|
|
93
97
|
openAiStructuredOutputSchemaName: () => openAiStructuredOutputSchemaName,
|
|
94
98
|
openai: () => openai,
|
|
99
|
+
openrouter: () => openrouter,
|
|
95
100
|
parseAnthropicBatchStructuredContent: () => parseAnthropicBatchStructuredContent,
|
|
96
101
|
parseAnthropicStreamEvents: () => parseAnthropicStreamEvents,
|
|
97
102
|
parseAnthropicToolInputJson: () => parseAnthropicToolInputJson,
|
|
@@ -3448,6 +3453,425 @@ JSON Schema:
|
|
|
3448
3453
|
${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
|
|
3449
3454
|
};
|
|
3450
3455
|
}
|
|
3456
|
+
|
|
3457
|
+
// src/openrouter-adapter.ts
|
|
3458
|
+
var import_zod12 = require("zod");
|
|
3459
|
+
var import_errors36 = require("@assemble-dev/shared-types/errors");
|
|
3460
|
+
var import_json10 = require("@assemble-dev/shared-types/json");
|
|
3461
|
+
var import_errors37 = require("@assemble-dev/shared-utils/errors");
|
|
3462
|
+
var defaultOpenRouterBaseUrl = "https://openrouter.ai/api/v1";
|
|
3463
|
+
var OpenRouterResponseToolCallSchema = import_zod12.z.object({
|
|
3464
|
+
id: import_zod12.z.string(),
|
|
3465
|
+
function: import_zod12.z.object({
|
|
3466
|
+
name: import_zod12.z.string(),
|
|
3467
|
+
arguments: import_zod12.z.string()
|
|
3468
|
+
})
|
|
3469
|
+
});
|
|
3470
|
+
var OpenRouterChatCompletionResponseSchema = import_zod12.z.object({
|
|
3471
|
+
choices: import_zod12.z.array(
|
|
3472
|
+
import_zod12.z.object({
|
|
3473
|
+
message: import_zod12.z.object({
|
|
3474
|
+
content: import_zod12.z.string().nullable(),
|
|
3475
|
+
tool_calls: import_zod12.z.array(OpenRouterResponseToolCallSchema).optional()
|
|
3476
|
+
}),
|
|
3477
|
+
finish_reason: import_zod12.z.string().nullable().optional()
|
|
3478
|
+
})
|
|
3479
|
+
).min(1),
|
|
3480
|
+
usage: import_zod12.z.object({
|
|
3481
|
+
prompt_tokens: import_zod12.z.number().int().nonnegative(),
|
|
3482
|
+
completion_tokens: import_zod12.z.number().int().nonnegative(),
|
|
3483
|
+
total_tokens: import_zod12.z.number().int().nonnegative()
|
|
3484
|
+
})
|
|
3485
|
+
});
|
|
3486
|
+
function openrouter(options) {
|
|
3487
|
+
return {
|
|
3488
|
+
name: `openrouter:${options.model}`,
|
|
3489
|
+
async generateChatCompletion(request) {
|
|
3490
|
+
return await executeOpenRouterAdapterCall(options, {
|
|
3491
|
+
messages: request.messages,
|
|
3492
|
+
temperature: request.temperature ?? options.temperature,
|
|
3493
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3494
|
+
reasoningModel: options.reasoningModel,
|
|
3495
|
+
tools: request.tools,
|
|
3496
|
+
toolChoice: request.toolChoice,
|
|
3497
|
+
abortSignal: request.abortSignal,
|
|
3498
|
+
extraBody: request.extraBody
|
|
3499
|
+
});
|
|
3500
|
+
},
|
|
3501
|
+
async generateStructuredOutput(request) {
|
|
3502
|
+
const completion = await executeOpenRouterAdapterCall(options, {
|
|
3503
|
+
...resolveOpenAiStructuredOutputMode(request.messages, request.schema),
|
|
3504
|
+
temperature: request.temperature ?? options.temperature,
|
|
3505
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3506
|
+
reasoningModel: options.reasoningModel,
|
|
3507
|
+
abortSignal: request.abortSignal
|
|
3508
|
+
});
|
|
3509
|
+
return {
|
|
3510
|
+
value: parseStructuredJsonText(completion.content, request.schema),
|
|
3511
|
+
tokenUsage: completion.tokenUsage,
|
|
3512
|
+
latencyMs: completion.latencyMs
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3515
|
+
};
|
|
3516
|
+
}
|
|
3517
|
+
async function executeOpenRouterAdapterCall(options, input) {
|
|
3518
|
+
return await executeProviderCallWithModelFallback(
|
|
3519
|
+
options.fallbackModel,
|
|
3520
|
+
async () => await executeProviderCallWithRetry(
|
|
3521
|
+
options.retry,
|
|
3522
|
+
async () => await requestOpenRouterChatCompletion(options, input)
|
|
3523
|
+
),
|
|
3524
|
+
async (fallbackModelId) => await requestOpenRouterChatCompletion(
|
|
3525
|
+
{ ...options, model: fallbackModelId },
|
|
3526
|
+
input
|
|
3527
|
+
)
|
|
3528
|
+
);
|
|
3529
|
+
}
|
|
3530
|
+
function buildOpenRouterRequestHeaders(options, apiKey) {
|
|
3531
|
+
const headers = {
|
|
3532
|
+
"Content-Type": "application/json",
|
|
3533
|
+
Authorization: `Bearer ${apiKey}`
|
|
3534
|
+
};
|
|
3535
|
+
if (options.appUrl !== void 0) {
|
|
3536
|
+
headers["HTTP-Referer"] = options.appUrl;
|
|
3537
|
+
}
|
|
3538
|
+
if (options.appName !== void 0) {
|
|
3539
|
+
headers["X-Title"] = options.appName;
|
|
3540
|
+
}
|
|
3541
|
+
return headers;
|
|
3542
|
+
}
|
|
3543
|
+
async function requestOpenRouterChatCompletion(options, input) {
|
|
3544
|
+
const apiKey = resolveProviderApiKey({
|
|
3545
|
+
providerLabel: "OpenRouter",
|
|
3546
|
+
adapterFunctionName: "openrouter()",
|
|
3547
|
+
baseEnvVarName: "OPENROUTER_API_KEY",
|
|
3548
|
+
apiKey: options.apiKey,
|
|
3549
|
+
apiKeyName: options.apiKeyName
|
|
3550
|
+
});
|
|
3551
|
+
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
3552
|
+
const baseUrl = options.baseURL ?? defaultOpenRouterBaseUrl;
|
|
3553
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
3554
|
+
buildOpenAiRequestBody(options.model, input),
|
|
3555
|
+
options.extraBody,
|
|
3556
|
+
input.extraBody
|
|
3557
|
+
);
|
|
3558
|
+
const startedAt = Date.now();
|
|
3559
|
+
const response = await executeAbortableProviderFetch(
|
|
3560
|
+
"OpenRouter",
|
|
3561
|
+
async () => await fetchImplementation(`${baseUrl}/chat/completions`, {
|
|
3562
|
+
method: "POST",
|
|
3563
|
+
headers: buildOpenRouterRequestHeaders(options, apiKey),
|
|
3564
|
+
body: JSON.stringify(requestBody),
|
|
3565
|
+
signal: input.abortSignal
|
|
3566
|
+
})
|
|
3567
|
+
);
|
|
3568
|
+
const latencyMs = Date.now() - startedAt;
|
|
3569
|
+
if (!response.ok) {
|
|
3570
|
+
throw buildProviderStatusError("OpenRouter", response.status);
|
|
3571
|
+
}
|
|
3572
|
+
const parseResult = OpenRouterChatCompletionResponseSchema.safeParse(
|
|
3573
|
+
await response.json()
|
|
3574
|
+
);
|
|
3575
|
+
if (!parseResult.success) {
|
|
3576
|
+
throw buildProviderInvalidResponseError("OpenRouter", "chat completion");
|
|
3577
|
+
}
|
|
3578
|
+
return mapOpenRouterResponseToChatCompletionResult(
|
|
3579
|
+
parseResult.data,
|
|
3580
|
+
latencyMs
|
|
3581
|
+
);
|
|
3582
|
+
}
|
|
3583
|
+
function mapOpenRouterResponseToChatCompletionResult(response, latencyMs) {
|
|
3584
|
+
const toolCalls = extractOpenRouterToolCalls(response);
|
|
3585
|
+
const result = {
|
|
3586
|
+
content: extractOpenRouterMessageContent(response, toolCalls.length > 0),
|
|
3587
|
+
tokenUsage: mapOpenRouterUsageToTokenUsage(response),
|
|
3588
|
+
latencyMs
|
|
3589
|
+
};
|
|
3590
|
+
const finishReason = response.choices[0]?.finish_reason;
|
|
3591
|
+
if (toolCalls.length > 0) {
|
|
3592
|
+
result.toolCalls = toolCalls;
|
|
3593
|
+
}
|
|
3594
|
+
if (finishReason !== null && finishReason !== void 0) {
|
|
3595
|
+
result.stopReason = normalizeOpenRouterFinishReason(finishReason);
|
|
3596
|
+
}
|
|
3597
|
+
return result;
|
|
3598
|
+
}
|
|
3599
|
+
function extractOpenRouterToolCalls(response) {
|
|
3600
|
+
const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
|
|
3601
|
+
return responseToolCalls.map((responseToolCall) => ({
|
|
3602
|
+
id: responseToolCall.id,
|
|
3603
|
+
toolName: responseToolCall.function.name,
|
|
3604
|
+
input: parseOpenRouterToolArgumentsJson(
|
|
3605
|
+
responseToolCall.function.arguments
|
|
3606
|
+
)
|
|
3607
|
+
}));
|
|
3608
|
+
}
|
|
3609
|
+
function parseOpenRouterToolArgumentsJson(argumentsJsonText) {
|
|
3610
|
+
if (argumentsJsonText.trim().length === 0) {
|
|
3611
|
+
return {};
|
|
3612
|
+
}
|
|
3613
|
+
try {
|
|
3614
|
+
return import_json10.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
|
|
3615
|
+
} catch (error) {
|
|
3616
|
+
throw new import_errors37.AppError({
|
|
3617
|
+
code: import_errors36.AppErrorCode.ValidationFailed,
|
|
3618
|
+
message: "OpenRouter tool call arguments were not valid JSON",
|
|
3619
|
+
statusCode: 502,
|
|
3620
|
+
cause: error instanceof Error ? error : void 0
|
|
3621
|
+
});
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
function normalizeOpenRouterFinishReason(finishReason) {
|
|
3625
|
+
if (finishReason === "tool_calls") {
|
|
3626
|
+
return "tool_use";
|
|
3627
|
+
}
|
|
3628
|
+
if (finishReason === "length") {
|
|
3629
|
+
return "max_tokens";
|
|
3630
|
+
}
|
|
3631
|
+
return "end_turn";
|
|
3632
|
+
}
|
|
3633
|
+
function extractOpenRouterMessageContent(response, allowEmptyContent) {
|
|
3634
|
+
const content = response.choices[0]?.message.content;
|
|
3635
|
+
if (content === void 0 || content === null) {
|
|
3636
|
+
if (allowEmptyContent) {
|
|
3637
|
+
return "";
|
|
3638
|
+
}
|
|
3639
|
+
throw new import_errors37.AppError({
|
|
3640
|
+
code: import_errors36.AppErrorCode.ValidationFailed,
|
|
3641
|
+
message: "OpenRouter response contained no message content",
|
|
3642
|
+
statusCode: 502
|
|
3643
|
+
});
|
|
3644
|
+
}
|
|
3645
|
+
return content;
|
|
3646
|
+
}
|
|
3647
|
+
function mapOpenRouterUsageToTokenUsage(response) {
|
|
3648
|
+
return {
|
|
3649
|
+
inputTokens: response.usage.prompt_tokens,
|
|
3650
|
+
outputTokens: response.usage.completion_tokens,
|
|
3651
|
+
totalTokens: response.usage.total_tokens
|
|
3652
|
+
};
|
|
3653
|
+
}
|
|
3654
|
+
|
|
3655
|
+
// src/cloudflare-workers-ai-adapter.ts
|
|
3656
|
+
var import_zod13 = require("zod");
|
|
3657
|
+
var import_errors38 = require("@assemble-dev/shared-types/errors");
|
|
3658
|
+
var import_json11 = require("@assemble-dev/shared-types/json");
|
|
3659
|
+
var import_errors39 = require("@assemble-dev/shared-utils/errors");
|
|
3660
|
+
var defaultCloudflareApiBaseUrl = "https://api.cloudflare.com/client/v4";
|
|
3661
|
+
var cloudflareAccountIdEnvVarName = "CLOUDFLARE_ACCOUNT_ID";
|
|
3662
|
+
var CloudflareWorkersAiResponseToolCallSchema = import_zod13.z.object({
|
|
3663
|
+
id: import_zod13.z.string(),
|
|
3664
|
+
function: import_zod13.z.object({
|
|
3665
|
+
name: import_zod13.z.string(),
|
|
3666
|
+
arguments: import_zod13.z.string()
|
|
3667
|
+
})
|
|
3668
|
+
});
|
|
3669
|
+
var CloudflareWorkersAiChatCompletionResponseSchema = import_zod13.z.object({
|
|
3670
|
+
choices: import_zod13.z.array(
|
|
3671
|
+
import_zod13.z.object({
|
|
3672
|
+
message: import_zod13.z.object({
|
|
3673
|
+
content: import_zod13.z.string().nullable(),
|
|
3674
|
+
tool_calls: import_zod13.z.array(CloudflareWorkersAiResponseToolCallSchema).optional()
|
|
3675
|
+
}),
|
|
3676
|
+
finish_reason: import_zod13.z.string().nullable().optional()
|
|
3677
|
+
})
|
|
3678
|
+
).min(1),
|
|
3679
|
+
usage: import_zod13.z.object({
|
|
3680
|
+
prompt_tokens: import_zod13.z.number().int().nonnegative(),
|
|
3681
|
+
completion_tokens: import_zod13.z.number().int().nonnegative(),
|
|
3682
|
+
total_tokens: import_zod13.z.number().int().nonnegative()
|
|
3683
|
+
}).optional()
|
|
3684
|
+
});
|
|
3685
|
+
function cloudflareWorkersAi(options) {
|
|
3686
|
+
return {
|
|
3687
|
+
name: `cloudflare-workers-ai:${options.model}`,
|
|
3688
|
+
async generateChatCompletion(request) {
|
|
3689
|
+
return await executeCloudflareWorkersAiAdapterCall(options, {
|
|
3690
|
+
messages: request.messages,
|
|
3691
|
+
temperature: request.temperature ?? options.temperature,
|
|
3692
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3693
|
+
tools: request.tools,
|
|
3694
|
+
toolChoice: request.toolChoice,
|
|
3695
|
+
abortSignal: request.abortSignal,
|
|
3696
|
+
extraBody: request.extraBody
|
|
3697
|
+
});
|
|
3698
|
+
},
|
|
3699
|
+
async generateStructuredOutput(request) {
|
|
3700
|
+
const completion = await executeCloudflareWorkersAiAdapterCall(options, {
|
|
3701
|
+
...resolveOpenAiStructuredOutputMode(request.messages, request.schema),
|
|
3702
|
+
temperature: request.temperature ?? options.temperature,
|
|
3703
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3704
|
+
abortSignal: request.abortSignal
|
|
3705
|
+
});
|
|
3706
|
+
return {
|
|
3707
|
+
value: parseStructuredJsonText(completion.content, request.schema),
|
|
3708
|
+
tokenUsage: completion.tokenUsage,
|
|
3709
|
+
latencyMs: completion.latencyMs
|
|
3710
|
+
};
|
|
3711
|
+
}
|
|
3712
|
+
};
|
|
3713
|
+
}
|
|
3714
|
+
function buildCloudflareWorkersAiChatCompletionsUrl(options) {
|
|
3715
|
+
if (options.baseURL !== void 0 && options.baseURL.length > 0) {
|
|
3716
|
+
return `${options.baseURL.replace(/\/+$/, "")}/chat/completions`;
|
|
3717
|
+
}
|
|
3718
|
+
const accountId = resolveCloudflareWorkersAiAccountId(options);
|
|
3719
|
+
return `${defaultCloudflareApiBaseUrl}/accounts/${encodeURIComponent(accountId)}/ai/v1/chat/completions`;
|
|
3720
|
+
}
|
|
3721
|
+
function resolveCloudflareWorkersAiAccountId(options) {
|
|
3722
|
+
if (options.accountId !== void 0 && options.accountId.length > 0) {
|
|
3723
|
+
return options.accountId;
|
|
3724
|
+
}
|
|
3725
|
+
const envAccountId = readEnvironmentVariable2(cloudflareAccountIdEnvVarName);
|
|
3726
|
+
if (envAccountId !== void 0 && envAccountId.length > 0) {
|
|
3727
|
+
return envAccountId;
|
|
3728
|
+
}
|
|
3729
|
+
throw new import_errors39.AppError({
|
|
3730
|
+
code: import_errors38.AppErrorCode.BadRequest,
|
|
3731
|
+
message: "Cloudflare Workers AI account is missing. Pass accountId or baseURL to cloudflareWorkersAi() or set the CLOUDFLARE_ACCOUNT_ID environment variable.",
|
|
3732
|
+
statusCode: 400
|
|
3733
|
+
});
|
|
3734
|
+
}
|
|
3735
|
+
function readEnvironmentVariable2(envVarName) {
|
|
3736
|
+
const parsedEnv = import_zod13.z.object({ [envVarName]: import_zod13.z.string().optional() }).parse(process.env);
|
|
3737
|
+
return parsedEnv[envVarName];
|
|
3738
|
+
}
|
|
3739
|
+
async function executeCloudflareWorkersAiAdapterCall(options, input) {
|
|
3740
|
+
return await executeProviderCallWithModelFallback(
|
|
3741
|
+
options.fallbackModel,
|
|
3742
|
+
async () => await executeProviderCallWithRetry(
|
|
3743
|
+
options.retry,
|
|
3744
|
+
async () => await requestCloudflareWorkersAiChatCompletion(options, input)
|
|
3745
|
+
),
|
|
3746
|
+
async (fallbackModelId) => await requestCloudflareWorkersAiChatCompletion(
|
|
3747
|
+
{ ...options, model: fallbackModelId },
|
|
3748
|
+
input
|
|
3749
|
+
)
|
|
3750
|
+
);
|
|
3751
|
+
}
|
|
3752
|
+
async function requestCloudflareWorkersAiChatCompletion(options, input) {
|
|
3753
|
+
const apiToken = resolveProviderApiKey({
|
|
3754
|
+
providerLabel: "Cloudflare Workers AI",
|
|
3755
|
+
adapterFunctionName: "cloudflareWorkersAi()",
|
|
3756
|
+
baseEnvVarName: "CLOUDFLARE_API_TOKEN",
|
|
3757
|
+
apiKey: options.apiKey,
|
|
3758
|
+
apiKeyName: options.apiKeyName
|
|
3759
|
+
});
|
|
3760
|
+
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
3761
|
+
const requestUrl = buildCloudflareWorkersAiChatCompletionsUrl(options);
|
|
3762
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
3763
|
+
buildOpenAiRequestBody(options.model, input),
|
|
3764
|
+
options.extraBody,
|
|
3765
|
+
input.extraBody
|
|
3766
|
+
);
|
|
3767
|
+
const startedAt = Date.now();
|
|
3768
|
+
const response = await executeAbortableProviderFetch(
|
|
3769
|
+
"Cloudflare Workers AI",
|
|
3770
|
+
async () => await fetchImplementation(requestUrl, {
|
|
3771
|
+
method: "POST",
|
|
3772
|
+
headers: {
|
|
3773
|
+
"Content-Type": "application/json",
|
|
3774
|
+
Authorization: `Bearer ${apiToken}`
|
|
3775
|
+
},
|
|
3776
|
+
body: JSON.stringify(requestBody),
|
|
3777
|
+
signal: input.abortSignal
|
|
3778
|
+
})
|
|
3779
|
+
);
|
|
3780
|
+
const latencyMs = Date.now() - startedAt;
|
|
3781
|
+
if (!response.ok) {
|
|
3782
|
+
throw buildProviderStatusError("Cloudflare Workers AI", response.status);
|
|
3783
|
+
}
|
|
3784
|
+
const parseResult = CloudflareWorkersAiChatCompletionResponseSchema.safeParse(
|
|
3785
|
+
await response.json()
|
|
3786
|
+
);
|
|
3787
|
+
if (!parseResult.success) {
|
|
3788
|
+
throw buildProviderInvalidResponseError(
|
|
3789
|
+
"Cloudflare Workers AI",
|
|
3790
|
+
"chat completion"
|
|
3791
|
+
);
|
|
3792
|
+
}
|
|
3793
|
+
return mapCloudflareWorkersAiResponseToChatCompletionResult(
|
|
3794
|
+
parseResult.data,
|
|
3795
|
+
latencyMs
|
|
3796
|
+
);
|
|
3797
|
+
}
|
|
3798
|
+
function mapCloudflareWorkersAiResponseToChatCompletionResult(response, latencyMs) {
|
|
3799
|
+
const toolCalls = extractCloudflareWorkersAiToolCalls(response);
|
|
3800
|
+
const result = {
|
|
3801
|
+
content: extractCloudflareWorkersAiMessageContent(
|
|
3802
|
+
response,
|
|
3803
|
+
toolCalls.length > 0
|
|
3804
|
+
),
|
|
3805
|
+
tokenUsage: mapCloudflareWorkersAiUsageToTokenUsage(response),
|
|
3806
|
+
latencyMs
|
|
3807
|
+
};
|
|
3808
|
+
const finishReason = response.choices[0]?.finish_reason;
|
|
3809
|
+
if (toolCalls.length > 0) {
|
|
3810
|
+
result.toolCalls = toolCalls;
|
|
3811
|
+
}
|
|
3812
|
+
if (finishReason !== null && finishReason !== void 0) {
|
|
3813
|
+
result.stopReason = normalizeCloudflareWorkersAiFinishReason(finishReason);
|
|
3814
|
+
}
|
|
3815
|
+
return result;
|
|
3816
|
+
}
|
|
3817
|
+
function extractCloudflareWorkersAiToolCalls(response) {
|
|
3818
|
+
const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
|
|
3819
|
+
return responseToolCalls.map((responseToolCall) => ({
|
|
3820
|
+
id: responseToolCall.id,
|
|
3821
|
+
toolName: responseToolCall.function.name,
|
|
3822
|
+
input: parseCloudflareWorkersAiToolArgumentsJson(
|
|
3823
|
+
responseToolCall.function.arguments
|
|
3824
|
+
)
|
|
3825
|
+
}));
|
|
3826
|
+
}
|
|
3827
|
+
function parseCloudflareWorkersAiToolArgumentsJson(argumentsJsonText) {
|
|
3828
|
+
if (argumentsJsonText.trim().length === 0) {
|
|
3829
|
+
return {};
|
|
3830
|
+
}
|
|
3831
|
+
try {
|
|
3832
|
+
return import_json11.JsonValueSchema.parse(JSON.parse(argumentsJsonText));
|
|
3833
|
+
} catch (error) {
|
|
3834
|
+
throw new import_errors39.AppError({
|
|
3835
|
+
code: import_errors38.AppErrorCode.ValidationFailed,
|
|
3836
|
+
message: "Cloudflare Workers AI tool call arguments were not valid JSON",
|
|
3837
|
+
statusCode: 502,
|
|
3838
|
+
cause: error instanceof Error ? error : void 0
|
|
3839
|
+
});
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
function normalizeCloudflareWorkersAiFinishReason(finishReason) {
|
|
3843
|
+
if (finishReason === "tool_calls") {
|
|
3844
|
+
return "tool_use";
|
|
3845
|
+
}
|
|
3846
|
+
if (finishReason === "length") {
|
|
3847
|
+
return "max_tokens";
|
|
3848
|
+
}
|
|
3849
|
+
return "end_turn";
|
|
3850
|
+
}
|
|
3851
|
+
function extractCloudflareWorkersAiMessageContent(response, allowEmptyContent) {
|
|
3852
|
+
const content = response.choices[0]?.message.content;
|
|
3853
|
+
if (content === void 0 || content === null) {
|
|
3854
|
+
if (allowEmptyContent) {
|
|
3855
|
+
return "";
|
|
3856
|
+
}
|
|
3857
|
+
throw new import_errors39.AppError({
|
|
3858
|
+
code: import_errors38.AppErrorCode.ValidationFailed,
|
|
3859
|
+
message: "Cloudflare Workers AI response contained no message content",
|
|
3860
|
+
statusCode: 502
|
|
3861
|
+
});
|
|
3862
|
+
}
|
|
3863
|
+
return content;
|
|
3864
|
+
}
|
|
3865
|
+
function mapCloudflareWorkersAiUsageToTokenUsage(response) {
|
|
3866
|
+
if (response.usage === void 0) {
|
|
3867
|
+
return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
3868
|
+
}
|
|
3869
|
+
return {
|
|
3870
|
+
inputTokens: response.usage.prompt_tokens,
|
|
3871
|
+
outputTokens: response.usage.completion_tokens,
|
|
3872
|
+
totalTokens: response.usage.total_tokens
|
|
3873
|
+
};
|
|
3874
|
+
}
|
|
3451
3875
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3452
3876
|
0 && (module.exports = {
|
|
3453
3877
|
AnthropicMessagesResponseSchema,
|
|
@@ -3474,11 +3898,13 @@ ${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
|
|
|
3474
3898
|
buildAzureOpenAiChatRequestBody,
|
|
3475
3899
|
buildBedrockInvokeModelRequestBody,
|
|
3476
3900
|
buildBedrockInvokeModelUrl,
|
|
3901
|
+
buildCloudflareWorkersAiChatCompletionsUrl,
|
|
3477
3902
|
buildGeminiResponseSchema,
|
|
3478
3903
|
buildOpenAiRequestBody,
|
|
3479
3904
|
buildOpenAiStructuredOutputJsonSchema,
|
|
3480
3905
|
buildProviderCanceledError,
|
|
3481
3906
|
calculateProviderRetryDelayMs,
|
|
3907
|
+
cloudflareWorkersAi,
|
|
3482
3908
|
convertZodSchemaToJsonSchema,
|
|
3483
3909
|
createAnthropicBatchClient,
|
|
3484
3910
|
defaultAnthropicBaseUrl,
|
|
@@ -3487,8 +3913,10 @@ ${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
|
|
|
3487
3913
|
defaultAnthropicMaxOutputTokens,
|
|
3488
3914
|
defaultAzureOpenAiApiVersion,
|
|
3489
3915
|
defaultBedrockMaxOutputTokens,
|
|
3916
|
+
defaultCloudflareApiBaseUrl,
|
|
3490
3917
|
defaultGeminiBaseUrl,
|
|
3491
3918
|
defaultOpenAiBaseUrl,
|
|
3919
|
+
defaultOpenRouterBaseUrl,
|
|
3492
3920
|
defaultProviderRetryInitialDelayMs,
|
|
3493
3921
|
defaultProviderRetryMaxAttempts,
|
|
3494
3922
|
defaultProviderRetryMaxDelayMs,
|
|
@@ -3522,6 +3950,7 @@ ${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
|
|
|
3522
3950
|
normalizeAzureOpenAiFinishReason,
|
|
3523
3951
|
openAiStructuredOutputSchemaName,
|
|
3524
3952
|
openai,
|
|
3953
|
+
openrouter,
|
|
3525
3954
|
parseAnthropicBatchStructuredContent,
|
|
3526
3955
|
parseAnthropicStreamEvents,
|
|
3527
3956
|
parseAnthropicToolInputJson,
|
package/dist/index.d.cts
CHANGED
|
@@ -806,4 +806,39 @@ declare function buildBedrockInvokeModelUrl(region: string, modelId: string): st
|
|
|
806
806
|
declare function resolveBedrockCredentials(options: BedrockAdapterOptions): BedrockCredentials;
|
|
807
807
|
declare function buildBedrockInvokeModelRequestBody(input: AnthropicRequestInput): BedrockInvokeModelRequestBody;
|
|
808
808
|
|
|
809
|
-
|
|
809
|
+
declare const defaultOpenRouterBaseUrl = "https://openrouter.ai/api/v1";
|
|
810
|
+
type OpenRouterAdapterOptions = {
|
|
811
|
+
model: string;
|
|
812
|
+
baseURL?: string;
|
|
813
|
+
apiKey?: string;
|
|
814
|
+
apiKeyName?: string;
|
|
815
|
+
fetchImplementation?: typeof fetch;
|
|
816
|
+
temperature?: number;
|
|
817
|
+
maxOutputTokens?: number;
|
|
818
|
+
reasoningModel?: boolean;
|
|
819
|
+
retry?: ProviderRetryOptions;
|
|
820
|
+
fallbackModel?: string;
|
|
821
|
+
extraBody?: Record<string, JsonValue>;
|
|
822
|
+
appUrl?: string;
|
|
823
|
+
appName?: string;
|
|
824
|
+
};
|
|
825
|
+
declare function openrouter(options: OpenRouterAdapterOptions): ModelAdapter;
|
|
826
|
+
|
|
827
|
+
declare const defaultCloudflareApiBaseUrl = "https://api.cloudflare.com/client/v4";
|
|
828
|
+
type CloudflareWorkersAiAdapterOptions = {
|
|
829
|
+
model: string;
|
|
830
|
+
accountId?: string;
|
|
831
|
+
baseURL?: string;
|
|
832
|
+
apiKey?: string;
|
|
833
|
+
apiKeyName?: string;
|
|
834
|
+
fetchImplementation?: typeof fetch;
|
|
835
|
+
temperature?: number;
|
|
836
|
+
maxOutputTokens?: number;
|
|
837
|
+
retry?: ProviderRetryOptions;
|
|
838
|
+
fallbackModel?: string;
|
|
839
|
+
extraBody?: Record<string, JsonValue>;
|
|
840
|
+
};
|
|
841
|
+
declare function cloudflareWorkersAi(options: CloudflareWorkersAiAdapterOptions): ModelAdapter;
|
|
842
|
+
declare function buildCloudflareWorkersAiChatCompletionsUrl(options: CloudflareWorkersAiAdapterOptions): string;
|
|
843
|
+
|
|
844
|
+
export { type AnthropicAdapterOptions, type AnthropicBatchApiRequest, type AnthropicBatchApiRequestMessage, type AnthropicBatchApiRequestParams, type AnthropicBatchCanceledOutcome, type AnthropicBatchClient, type AnthropicBatchClientOptions, type AnthropicBatchErroredOutcome, type AnthropicBatchExpiredOutcome, type AnthropicBatchMessageRequest, type AnthropicBatchPromptCachingMode, type AnthropicBatchResult, type AnthropicBatchResultOutcome, type AnthropicBatchSubmittedRequestSummary, type AnthropicBatchSucceededOutcome, type AnthropicBatchSystemContentBlock, type AnthropicBatchTraceEventHandler, type AnthropicBatchWaitOptions, type AnthropicCacheControl, type AnthropicCacheTtl, type AnthropicMessageBatch, type AnthropicMessageBatchProcessingStatus, type AnthropicMessageBatchRequestCounts, type AnthropicMessagesResponse, AnthropicMessagesResponseSchema, type AnthropicOutputConfig, type AnthropicPromptCachingMode, type AnthropicPromptCachingOptions, type AnthropicPromptCachingSettings, type AnthropicRequestBody, type AnthropicRequestContentBlock, type AnthropicRequestInput, type AnthropicRequestMessage, type AnthropicRequestSettings, type AnthropicStreamEvent, AnthropicStreamEventSchema, type AnthropicStreamRequestInput, type AnthropicStreamStartUsage, type AnthropicSystemContentBlock, type AnthropicThinkingOptions, type AnthropicToolChoice, type AnthropicToolDefinition, type AnthropicUsage, type AwsCredentials, type AwsSigV4SigningInput, type AzureOpenAiAdapterOptions, type AzureOpenAiChatCompletionResponse, AzureOpenAiChatCompletionResponseSchema, type AzureOpenAiChatRequestBody, type AzureOpenAiStreamRequestBody, type AzureOpenAiStreamRequestInput, type AzureOpenAiUsage, type BedrockAdapterOptions, type BedrockCredentials, type BedrockInvokeModelRequestBody, type ChatCompletionRequest, type ChatCompletionResult, type ChatMessage, type ChatMessageCacheControl, ChatMessageCacheControlSchema, type ChatMessageRole, ChatMessageRoleSchema, ChatMessageSchema, type ChatStopReason, ChatStopReasonSchema, type ChatStreamEvent, type CloudflareWorkersAiAdapterOptions, type GeminiAdapterOptions, type MessageContentBlock, MessageContentBlockSchema, type MockModelOptions, type ModelAdapter, type ModelPricingUsdPerMillionTokens, type ModelToolCall, ModelToolCallSchema, type ModelToolChoice, type ModelToolDefinition, type OpenAiAdapterOptions, type OpenAiCallInput, type OpenAiContentPart, type OpenAiRequestBody, type OpenAiRequestMessage, type OpenAiRequestToolCall, type OpenAiResponseFormat, type OpenAiStructuredOutputMode, type OpenAiToolChoice, type OpenAiToolDefinition, type OpenRouterAdapterOptions, type ProviderExtraBody, type ProviderRetryOptions, type ResolveProviderApiKeyInput, type StructuredOutputRequest, type StructuredOutputResult, anthropic, anthropicBatchJsonOnlySystemInstruction, anthropicBatchTraceWorkflowName, applyCacheControlToLastContentBlock, awsSigV4Algorithm, azureOpenai, bedrock, bedrockAnthropicVersion, buildAnthropicCacheControl, buildAnthropicRequestBody, buildAnthropicStructuredOutputJsonSchema, buildAzureOpenAiChatCompletionsUrl, buildAzureOpenAiChatRequestBody, buildBedrockInvokeModelRequestBody, buildBedrockInvokeModelUrl, buildCloudflareWorkersAiChatCompletionsUrl, buildGeminiResponseSchema, buildOpenAiRequestBody, buildOpenAiStructuredOutputJsonSchema, buildProviderCanceledError, calculateProviderRetryDelayMs, cloudflareWorkersAi, convertZodSchemaToJsonSchema, createAnthropicBatchClient, defaultAnthropicBaseUrl, defaultAnthropicBatchPollIntervalMs, defaultAnthropicBatchTimeoutMs, defaultAnthropicMaxOutputTokens, defaultAzureOpenAiApiVersion, defaultBedrockMaxOutputTokens, defaultCloudflareApiBaseUrl, defaultGeminiBaseUrl, defaultOpenAiBaseUrl, defaultOpenRouterBaseUrl, defaultProviderRetryInitialDelayMs, defaultProviderRetryMaxAttempts, defaultProviderRetryMaxDelayMs, estimateModelCallCostUsd, executeAbortableProviderFetch, executeProviderCallWithModelFallback, executeProviderCallWithRetry, extractAnthropicTextContent, extractAnthropicThinkingText, extractAnthropicToolCalls, extractMessageText, gemini, isAbortError, isOpenAiReasoningModel, isRetryableProviderAppError, isZodV4Schema, joinSystemMessageText, mapAnthropicResponseToChatCompletionResult, mapAnthropicUsageToTokenUsage, mapAzureOpenAiResponseToChatCompletionResult, mapAzureOpenAiUsageToTokenUsage, mapChatMessageToAnthropicRequestMessage, mapChatMessageToOpenAiRequestMessage, mapModelToolChoiceToAnthropicToolChoice, mapModelToolChoiceToOpenAiToolChoice, mapModelToolDefinitionToOpenAiTool, mapModelToolDefinitionsToAnthropicTools, mergeProviderRequestExtraBody, mockModel, normalizeAnthropicStopReason, normalizeAzureOpenAiFinishReason, openAiStructuredOutputSchemaName, openai, openrouter, parseAnthropicBatchStructuredContent, parseAnthropicStreamEvents, parseAnthropicToolInputJson, parseAzureOpenAiStreamEvents, parseAzureOpenAiToolArgumentsJson, prependStructuredOutputJsonOnlySystemMessage, resolveAnthropicPromptCachingSettings, resolveBedrockCredentials, resolveOpenAiStructuredOutputMode, resolveProviderApiKey, sanitizeJsonSchemaForAnthropicStructuredOutput, sanitizeJsonSchemaForGeminiResponseSchema, sanitizeJsonSchemaForOpenAiStructuredOutput, signAwsRequestWithSigV4, streamAnthropicChatCompletion, streamAzureOpenAiChatCompletion, structuredOutputJsonOnlySystemInstruction, structuredOutputJsonOnlySystemMessage };
|
package/dist/index.d.ts
CHANGED
|
@@ -806,4 +806,39 @@ declare function buildBedrockInvokeModelUrl(region: string, modelId: string): st
|
|
|
806
806
|
declare function resolveBedrockCredentials(options: BedrockAdapterOptions): BedrockCredentials;
|
|
807
807
|
declare function buildBedrockInvokeModelRequestBody(input: AnthropicRequestInput): BedrockInvokeModelRequestBody;
|
|
808
808
|
|
|
809
|
-
|
|
809
|
+
declare const defaultOpenRouterBaseUrl = "https://openrouter.ai/api/v1";
|
|
810
|
+
type OpenRouterAdapterOptions = {
|
|
811
|
+
model: string;
|
|
812
|
+
baseURL?: string;
|
|
813
|
+
apiKey?: string;
|
|
814
|
+
apiKeyName?: string;
|
|
815
|
+
fetchImplementation?: typeof fetch;
|
|
816
|
+
temperature?: number;
|
|
817
|
+
maxOutputTokens?: number;
|
|
818
|
+
reasoningModel?: boolean;
|
|
819
|
+
retry?: ProviderRetryOptions;
|
|
820
|
+
fallbackModel?: string;
|
|
821
|
+
extraBody?: Record<string, JsonValue>;
|
|
822
|
+
appUrl?: string;
|
|
823
|
+
appName?: string;
|
|
824
|
+
};
|
|
825
|
+
declare function openrouter(options: OpenRouterAdapterOptions): ModelAdapter;
|
|
826
|
+
|
|
827
|
+
declare const defaultCloudflareApiBaseUrl = "https://api.cloudflare.com/client/v4";
|
|
828
|
+
type CloudflareWorkersAiAdapterOptions = {
|
|
829
|
+
model: string;
|
|
830
|
+
accountId?: string;
|
|
831
|
+
baseURL?: string;
|
|
832
|
+
apiKey?: string;
|
|
833
|
+
apiKeyName?: string;
|
|
834
|
+
fetchImplementation?: typeof fetch;
|
|
835
|
+
temperature?: number;
|
|
836
|
+
maxOutputTokens?: number;
|
|
837
|
+
retry?: ProviderRetryOptions;
|
|
838
|
+
fallbackModel?: string;
|
|
839
|
+
extraBody?: Record<string, JsonValue>;
|
|
840
|
+
};
|
|
841
|
+
declare function cloudflareWorkersAi(options: CloudflareWorkersAiAdapterOptions): ModelAdapter;
|
|
842
|
+
declare function buildCloudflareWorkersAiChatCompletionsUrl(options: CloudflareWorkersAiAdapterOptions): string;
|
|
843
|
+
|
|
844
|
+
export { type AnthropicAdapterOptions, type AnthropicBatchApiRequest, type AnthropicBatchApiRequestMessage, type AnthropicBatchApiRequestParams, type AnthropicBatchCanceledOutcome, type AnthropicBatchClient, type AnthropicBatchClientOptions, type AnthropicBatchErroredOutcome, type AnthropicBatchExpiredOutcome, type AnthropicBatchMessageRequest, type AnthropicBatchPromptCachingMode, type AnthropicBatchResult, type AnthropicBatchResultOutcome, type AnthropicBatchSubmittedRequestSummary, type AnthropicBatchSucceededOutcome, type AnthropicBatchSystemContentBlock, type AnthropicBatchTraceEventHandler, type AnthropicBatchWaitOptions, type AnthropicCacheControl, type AnthropicCacheTtl, type AnthropicMessageBatch, type AnthropicMessageBatchProcessingStatus, type AnthropicMessageBatchRequestCounts, type AnthropicMessagesResponse, AnthropicMessagesResponseSchema, type AnthropicOutputConfig, type AnthropicPromptCachingMode, type AnthropicPromptCachingOptions, type AnthropicPromptCachingSettings, type AnthropicRequestBody, type AnthropicRequestContentBlock, type AnthropicRequestInput, type AnthropicRequestMessage, type AnthropicRequestSettings, type AnthropicStreamEvent, AnthropicStreamEventSchema, type AnthropicStreamRequestInput, type AnthropicStreamStartUsage, type AnthropicSystemContentBlock, type AnthropicThinkingOptions, type AnthropicToolChoice, type AnthropicToolDefinition, type AnthropicUsage, type AwsCredentials, type AwsSigV4SigningInput, type AzureOpenAiAdapterOptions, type AzureOpenAiChatCompletionResponse, AzureOpenAiChatCompletionResponseSchema, type AzureOpenAiChatRequestBody, type AzureOpenAiStreamRequestBody, type AzureOpenAiStreamRequestInput, type AzureOpenAiUsage, type BedrockAdapterOptions, type BedrockCredentials, type BedrockInvokeModelRequestBody, type ChatCompletionRequest, type ChatCompletionResult, type ChatMessage, type ChatMessageCacheControl, ChatMessageCacheControlSchema, type ChatMessageRole, ChatMessageRoleSchema, ChatMessageSchema, type ChatStopReason, ChatStopReasonSchema, type ChatStreamEvent, type CloudflareWorkersAiAdapterOptions, type GeminiAdapterOptions, type MessageContentBlock, MessageContentBlockSchema, type MockModelOptions, type ModelAdapter, type ModelPricingUsdPerMillionTokens, type ModelToolCall, ModelToolCallSchema, type ModelToolChoice, type ModelToolDefinition, type OpenAiAdapterOptions, type OpenAiCallInput, type OpenAiContentPart, type OpenAiRequestBody, type OpenAiRequestMessage, type OpenAiRequestToolCall, type OpenAiResponseFormat, type OpenAiStructuredOutputMode, type OpenAiToolChoice, type OpenAiToolDefinition, type OpenRouterAdapterOptions, type ProviderExtraBody, type ProviderRetryOptions, type ResolveProviderApiKeyInput, type StructuredOutputRequest, type StructuredOutputResult, anthropic, anthropicBatchJsonOnlySystemInstruction, anthropicBatchTraceWorkflowName, applyCacheControlToLastContentBlock, awsSigV4Algorithm, azureOpenai, bedrock, bedrockAnthropicVersion, buildAnthropicCacheControl, buildAnthropicRequestBody, buildAnthropicStructuredOutputJsonSchema, buildAzureOpenAiChatCompletionsUrl, buildAzureOpenAiChatRequestBody, buildBedrockInvokeModelRequestBody, buildBedrockInvokeModelUrl, buildCloudflareWorkersAiChatCompletionsUrl, buildGeminiResponseSchema, buildOpenAiRequestBody, buildOpenAiStructuredOutputJsonSchema, buildProviderCanceledError, calculateProviderRetryDelayMs, cloudflareWorkersAi, convertZodSchemaToJsonSchema, createAnthropicBatchClient, defaultAnthropicBaseUrl, defaultAnthropicBatchPollIntervalMs, defaultAnthropicBatchTimeoutMs, defaultAnthropicMaxOutputTokens, defaultAzureOpenAiApiVersion, defaultBedrockMaxOutputTokens, defaultCloudflareApiBaseUrl, defaultGeminiBaseUrl, defaultOpenAiBaseUrl, defaultOpenRouterBaseUrl, defaultProviderRetryInitialDelayMs, defaultProviderRetryMaxAttempts, defaultProviderRetryMaxDelayMs, estimateModelCallCostUsd, executeAbortableProviderFetch, executeProviderCallWithModelFallback, executeProviderCallWithRetry, extractAnthropicTextContent, extractAnthropicThinkingText, extractAnthropicToolCalls, extractMessageText, gemini, isAbortError, isOpenAiReasoningModel, isRetryableProviderAppError, isZodV4Schema, joinSystemMessageText, mapAnthropicResponseToChatCompletionResult, mapAnthropicUsageToTokenUsage, mapAzureOpenAiResponseToChatCompletionResult, mapAzureOpenAiUsageToTokenUsage, mapChatMessageToAnthropicRequestMessage, mapChatMessageToOpenAiRequestMessage, mapModelToolChoiceToAnthropicToolChoice, mapModelToolChoiceToOpenAiToolChoice, mapModelToolDefinitionToOpenAiTool, mapModelToolDefinitionsToAnthropicTools, mergeProviderRequestExtraBody, mockModel, normalizeAnthropicStopReason, normalizeAzureOpenAiFinishReason, openAiStructuredOutputSchemaName, openai, openrouter, parseAnthropicBatchStructuredContent, parseAnthropicStreamEvents, parseAnthropicToolInputJson, parseAzureOpenAiStreamEvents, parseAzureOpenAiToolArgumentsJson, prependStructuredOutputJsonOnlySystemMessage, resolveAnthropicPromptCachingSettings, resolveBedrockCredentials, resolveOpenAiStructuredOutputMode, resolveProviderApiKey, sanitizeJsonSchemaForAnthropicStructuredOutput, sanitizeJsonSchemaForGeminiResponseSchema, sanitizeJsonSchemaForOpenAiStructuredOutput, signAwsRequestWithSigV4, streamAnthropicChatCompletion, streamAzureOpenAiChatCompletion, structuredOutputJsonOnlySystemInstruction, structuredOutputJsonOnlySystemMessage };
|
package/dist/index.js
CHANGED
|
@@ -3340,6 +3340,425 @@ JSON Schema:
|
|
|
3340
3340
|
${JSON.stringify(convertZodSchemaToJsonSchema(schema))}`
|
|
3341
3341
|
};
|
|
3342
3342
|
}
|
|
3343
|
+
|
|
3344
|
+
// src/openrouter-adapter.ts
|
|
3345
|
+
import { z as z12 } from "zod";
|
|
3346
|
+
import { AppErrorCode as AppErrorCode18 } from "@assemble-dev/shared-types/errors";
|
|
3347
|
+
import { JsonValueSchema as JsonValueSchema9 } from "@assemble-dev/shared-types/json";
|
|
3348
|
+
import { AppError as AppError19 } from "@assemble-dev/shared-utils/errors";
|
|
3349
|
+
var defaultOpenRouterBaseUrl = "https://openrouter.ai/api/v1";
|
|
3350
|
+
var OpenRouterResponseToolCallSchema = z12.object({
|
|
3351
|
+
id: z12.string(),
|
|
3352
|
+
function: z12.object({
|
|
3353
|
+
name: z12.string(),
|
|
3354
|
+
arguments: z12.string()
|
|
3355
|
+
})
|
|
3356
|
+
});
|
|
3357
|
+
var OpenRouterChatCompletionResponseSchema = z12.object({
|
|
3358
|
+
choices: z12.array(
|
|
3359
|
+
z12.object({
|
|
3360
|
+
message: z12.object({
|
|
3361
|
+
content: z12.string().nullable(),
|
|
3362
|
+
tool_calls: z12.array(OpenRouterResponseToolCallSchema).optional()
|
|
3363
|
+
}),
|
|
3364
|
+
finish_reason: z12.string().nullable().optional()
|
|
3365
|
+
})
|
|
3366
|
+
).min(1),
|
|
3367
|
+
usage: z12.object({
|
|
3368
|
+
prompt_tokens: z12.number().int().nonnegative(),
|
|
3369
|
+
completion_tokens: z12.number().int().nonnegative(),
|
|
3370
|
+
total_tokens: z12.number().int().nonnegative()
|
|
3371
|
+
})
|
|
3372
|
+
});
|
|
3373
|
+
function openrouter(options) {
|
|
3374
|
+
return {
|
|
3375
|
+
name: `openrouter:${options.model}`,
|
|
3376
|
+
async generateChatCompletion(request) {
|
|
3377
|
+
return await executeOpenRouterAdapterCall(options, {
|
|
3378
|
+
messages: request.messages,
|
|
3379
|
+
temperature: request.temperature ?? options.temperature,
|
|
3380
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3381
|
+
reasoningModel: options.reasoningModel,
|
|
3382
|
+
tools: request.tools,
|
|
3383
|
+
toolChoice: request.toolChoice,
|
|
3384
|
+
abortSignal: request.abortSignal,
|
|
3385
|
+
extraBody: request.extraBody
|
|
3386
|
+
});
|
|
3387
|
+
},
|
|
3388
|
+
async generateStructuredOutput(request) {
|
|
3389
|
+
const completion = await executeOpenRouterAdapterCall(options, {
|
|
3390
|
+
...resolveOpenAiStructuredOutputMode(request.messages, request.schema),
|
|
3391
|
+
temperature: request.temperature ?? options.temperature,
|
|
3392
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3393
|
+
reasoningModel: options.reasoningModel,
|
|
3394
|
+
abortSignal: request.abortSignal
|
|
3395
|
+
});
|
|
3396
|
+
return {
|
|
3397
|
+
value: parseStructuredJsonText(completion.content, request.schema),
|
|
3398
|
+
tokenUsage: completion.tokenUsage,
|
|
3399
|
+
latencyMs: completion.latencyMs
|
|
3400
|
+
};
|
|
3401
|
+
}
|
|
3402
|
+
};
|
|
3403
|
+
}
|
|
3404
|
+
async function executeOpenRouterAdapterCall(options, input) {
|
|
3405
|
+
return await executeProviderCallWithModelFallback(
|
|
3406
|
+
options.fallbackModel,
|
|
3407
|
+
async () => await executeProviderCallWithRetry(
|
|
3408
|
+
options.retry,
|
|
3409
|
+
async () => await requestOpenRouterChatCompletion(options, input)
|
|
3410
|
+
),
|
|
3411
|
+
async (fallbackModelId) => await requestOpenRouterChatCompletion(
|
|
3412
|
+
{ ...options, model: fallbackModelId },
|
|
3413
|
+
input
|
|
3414
|
+
)
|
|
3415
|
+
);
|
|
3416
|
+
}
|
|
3417
|
+
function buildOpenRouterRequestHeaders(options, apiKey) {
|
|
3418
|
+
const headers = {
|
|
3419
|
+
"Content-Type": "application/json",
|
|
3420
|
+
Authorization: `Bearer ${apiKey}`
|
|
3421
|
+
};
|
|
3422
|
+
if (options.appUrl !== void 0) {
|
|
3423
|
+
headers["HTTP-Referer"] = options.appUrl;
|
|
3424
|
+
}
|
|
3425
|
+
if (options.appName !== void 0) {
|
|
3426
|
+
headers["X-Title"] = options.appName;
|
|
3427
|
+
}
|
|
3428
|
+
return headers;
|
|
3429
|
+
}
|
|
3430
|
+
async function requestOpenRouterChatCompletion(options, input) {
|
|
3431
|
+
const apiKey = resolveProviderApiKey({
|
|
3432
|
+
providerLabel: "OpenRouter",
|
|
3433
|
+
adapterFunctionName: "openrouter()",
|
|
3434
|
+
baseEnvVarName: "OPENROUTER_API_KEY",
|
|
3435
|
+
apiKey: options.apiKey,
|
|
3436
|
+
apiKeyName: options.apiKeyName
|
|
3437
|
+
});
|
|
3438
|
+
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
3439
|
+
const baseUrl = options.baseURL ?? defaultOpenRouterBaseUrl;
|
|
3440
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
3441
|
+
buildOpenAiRequestBody(options.model, input),
|
|
3442
|
+
options.extraBody,
|
|
3443
|
+
input.extraBody
|
|
3444
|
+
);
|
|
3445
|
+
const startedAt = Date.now();
|
|
3446
|
+
const response = await executeAbortableProviderFetch(
|
|
3447
|
+
"OpenRouter",
|
|
3448
|
+
async () => await fetchImplementation(`${baseUrl}/chat/completions`, {
|
|
3449
|
+
method: "POST",
|
|
3450
|
+
headers: buildOpenRouterRequestHeaders(options, apiKey),
|
|
3451
|
+
body: JSON.stringify(requestBody),
|
|
3452
|
+
signal: input.abortSignal
|
|
3453
|
+
})
|
|
3454
|
+
);
|
|
3455
|
+
const latencyMs = Date.now() - startedAt;
|
|
3456
|
+
if (!response.ok) {
|
|
3457
|
+
throw buildProviderStatusError("OpenRouter", response.status);
|
|
3458
|
+
}
|
|
3459
|
+
const parseResult = OpenRouterChatCompletionResponseSchema.safeParse(
|
|
3460
|
+
await response.json()
|
|
3461
|
+
);
|
|
3462
|
+
if (!parseResult.success) {
|
|
3463
|
+
throw buildProviderInvalidResponseError("OpenRouter", "chat completion");
|
|
3464
|
+
}
|
|
3465
|
+
return mapOpenRouterResponseToChatCompletionResult(
|
|
3466
|
+
parseResult.data,
|
|
3467
|
+
latencyMs
|
|
3468
|
+
);
|
|
3469
|
+
}
|
|
3470
|
+
function mapOpenRouterResponseToChatCompletionResult(response, latencyMs) {
|
|
3471
|
+
const toolCalls = extractOpenRouterToolCalls(response);
|
|
3472
|
+
const result = {
|
|
3473
|
+
content: extractOpenRouterMessageContent(response, toolCalls.length > 0),
|
|
3474
|
+
tokenUsage: mapOpenRouterUsageToTokenUsage(response),
|
|
3475
|
+
latencyMs
|
|
3476
|
+
};
|
|
3477
|
+
const finishReason = response.choices[0]?.finish_reason;
|
|
3478
|
+
if (toolCalls.length > 0) {
|
|
3479
|
+
result.toolCalls = toolCalls;
|
|
3480
|
+
}
|
|
3481
|
+
if (finishReason !== null && finishReason !== void 0) {
|
|
3482
|
+
result.stopReason = normalizeOpenRouterFinishReason(finishReason);
|
|
3483
|
+
}
|
|
3484
|
+
return result;
|
|
3485
|
+
}
|
|
3486
|
+
function extractOpenRouterToolCalls(response) {
|
|
3487
|
+
const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
|
|
3488
|
+
return responseToolCalls.map((responseToolCall) => ({
|
|
3489
|
+
id: responseToolCall.id,
|
|
3490
|
+
toolName: responseToolCall.function.name,
|
|
3491
|
+
input: parseOpenRouterToolArgumentsJson(
|
|
3492
|
+
responseToolCall.function.arguments
|
|
3493
|
+
)
|
|
3494
|
+
}));
|
|
3495
|
+
}
|
|
3496
|
+
function parseOpenRouterToolArgumentsJson(argumentsJsonText) {
|
|
3497
|
+
if (argumentsJsonText.trim().length === 0) {
|
|
3498
|
+
return {};
|
|
3499
|
+
}
|
|
3500
|
+
try {
|
|
3501
|
+
return JsonValueSchema9.parse(JSON.parse(argumentsJsonText));
|
|
3502
|
+
} catch (error) {
|
|
3503
|
+
throw new AppError19({
|
|
3504
|
+
code: AppErrorCode18.ValidationFailed,
|
|
3505
|
+
message: "OpenRouter tool call arguments were not valid JSON",
|
|
3506
|
+
statusCode: 502,
|
|
3507
|
+
cause: error instanceof Error ? error : void 0
|
|
3508
|
+
});
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3511
|
+
function normalizeOpenRouterFinishReason(finishReason) {
|
|
3512
|
+
if (finishReason === "tool_calls") {
|
|
3513
|
+
return "tool_use";
|
|
3514
|
+
}
|
|
3515
|
+
if (finishReason === "length") {
|
|
3516
|
+
return "max_tokens";
|
|
3517
|
+
}
|
|
3518
|
+
return "end_turn";
|
|
3519
|
+
}
|
|
3520
|
+
function extractOpenRouterMessageContent(response, allowEmptyContent) {
|
|
3521
|
+
const content = response.choices[0]?.message.content;
|
|
3522
|
+
if (content === void 0 || content === null) {
|
|
3523
|
+
if (allowEmptyContent) {
|
|
3524
|
+
return "";
|
|
3525
|
+
}
|
|
3526
|
+
throw new AppError19({
|
|
3527
|
+
code: AppErrorCode18.ValidationFailed,
|
|
3528
|
+
message: "OpenRouter response contained no message content",
|
|
3529
|
+
statusCode: 502
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3532
|
+
return content;
|
|
3533
|
+
}
|
|
3534
|
+
function mapOpenRouterUsageToTokenUsage(response) {
|
|
3535
|
+
return {
|
|
3536
|
+
inputTokens: response.usage.prompt_tokens,
|
|
3537
|
+
outputTokens: response.usage.completion_tokens,
|
|
3538
|
+
totalTokens: response.usage.total_tokens
|
|
3539
|
+
};
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
// src/cloudflare-workers-ai-adapter.ts
|
|
3543
|
+
import { z as z13 } from "zod";
|
|
3544
|
+
import { AppErrorCode as AppErrorCode19 } from "@assemble-dev/shared-types/errors";
|
|
3545
|
+
import { JsonValueSchema as JsonValueSchema10 } from "@assemble-dev/shared-types/json";
|
|
3546
|
+
import { AppError as AppError20 } from "@assemble-dev/shared-utils/errors";
|
|
3547
|
+
var defaultCloudflareApiBaseUrl = "https://api.cloudflare.com/client/v4";
|
|
3548
|
+
var cloudflareAccountIdEnvVarName = "CLOUDFLARE_ACCOUNT_ID";
|
|
3549
|
+
var CloudflareWorkersAiResponseToolCallSchema = z13.object({
|
|
3550
|
+
id: z13.string(),
|
|
3551
|
+
function: z13.object({
|
|
3552
|
+
name: z13.string(),
|
|
3553
|
+
arguments: z13.string()
|
|
3554
|
+
})
|
|
3555
|
+
});
|
|
3556
|
+
var CloudflareWorkersAiChatCompletionResponseSchema = z13.object({
|
|
3557
|
+
choices: z13.array(
|
|
3558
|
+
z13.object({
|
|
3559
|
+
message: z13.object({
|
|
3560
|
+
content: z13.string().nullable(),
|
|
3561
|
+
tool_calls: z13.array(CloudflareWorkersAiResponseToolCallSchema).optional()
|
|
3562
|
+
}),
|
|
3563
|
+
finish_reason: z13.string().nullable().optional()
|
|
3564
|
+
})
|
|
3565
|
+
).min(1),
|
|
3566
|
+
usage: z13.object({
|
|
3567
|
+
prompt_tokens: z13.number().int().nonnegative(),
|
|
3568
|
+
completion_tokens: z13.number().int().nonnegative(),
|
|
3569
|
+
total_tokens: z13.number().int().nonnegative()
|
|
3570
|
+
}).optional()
|
|
3571
|
+
});
|
|
3572
|
+
function cloudflareWorkersAi(options) {
|
|
3573
|
+
return {
|
|
3574
|
+
name: `cloudflare-workers-ai:${options.model}`,
|
|
3575
|
+
async generateChatCompletion(request) {
|
|
3576
|
+
return await executeCloudflareWorkersAiAdapterCall(options, {
|
|
3577
|
+
messages: request.messages,
|
|
3578
|
+
temperature: request.temperature ?? options.temperature,
|
|
3579
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3580
|
+
tools: request.tools,
|
|
3581
|
+
toolChoice: request.toolChoice,
|
|
3582
|
+
abortSignal: request.abortSignal,
|
|
3583
|
+
extraBody: request.extraBody
|
|
3584
|
+
});
|
|
3585
|
+
},
|
|
3586
|
+
async generateStructuredOutput(request) {
|
|
3587
|
+
const completion = await executeCloudflareWorkersAiAdapterCall(options, {
|
|
3588
|
+
...resolveOpenAiStructuredOutputMode(request.messages, request.schema),
|
|
3589
|
+
temperature: request.temperature ?? options.temperature,
|
|
3590
|
+
maxOutputTokens: request.maxOutputTokens ?? options.maxOutputTokens,
|
|
3591
|
+
abortSignal: request.abortSignal
|
|
3592
|
+
});
|
|
3593
|
+
return {
|
|
3594
|
+
value: parseStructuredJsonText(completion.content, request.schema),
|
|
3595
|
+
tokenUsage: completion.tokenUsage,
|
|
3596
|
+
latencyMs: completion.latencyMs
|
|
3597
|
+
};
|
|
3598
|
+
}
|
|
3599
|
+
};
|
|
3600
|
+
}
|
|
3601
|
+
function buildCloudflareWorkersAiChatCompletionsUrl(options) {
|
|
3602
|
+
if (options.baseURL !== void 0 && options.baseURL.length > 0) {
|
|
3603
|
+
return `${options.baseURL.replace(/\/+$/, "")}/chat/completions`;
|
|
3604
|
+
}
|
|
3605
|
+
const accountId = resolveCloudflareWorkersAiAccountId(options);
|
|
3606
|
+
return `${defaultCloudflareApiBaseUrl}/accounts/${encodeURIComponent(accountId)}/ai/v1/chat/completions`;
|
|
3607
|
+
}
|
|
3608
|
+
function resolveCloudflareWorkersAiAccountId(options) {
|
|
3609
|
+
if (options.accountId !== void 0 && options.accountId.length > 0) {
|
|
3610
|
+
return options.accountId;
|
|
3611
|
+
}
|
|
3612
|
+
const envAccountId = readEnvironmentVariable2(cloudflareAccountIdEnvVarName);
|
|
3613
|
+
if (envAccountId !== void 0 && envAccountId.length > 0) {
|
|
3614
|
+
return envAccountId;
|
|
3615
|
+
}
|
|
3616
|
+
throw new AppError20({
|
|
3617
|
+
code: AppErrorCode19.BadRequest,
|
|
3618
|
+
message: "Cloudflare Workers AI account is missing. Pass accountId or baseURL to cloudflareWorkersAi() or set the CLOUDFLARE_ACCOUNT_ID environment variable.",
|
|
3619
|
+
statusCode: 400
|
|
3620
|
+
});
|
|
3621
|
+
}
|
|
3622
|
+
function readEnvironmentVariable2(envVarName) {
|
|
3623
|
+
const parsedEnv = z13.object({ [envVarName]: z13.string().optional() }).parse(process.env);
|
|
3624
|
+
return parsedEnv[envVarName];
|
|
3625
|
+
}
|
|
3626
|
+
async function executeCloudflareWorkersAiAdapterCall(options, input) {
|
|
3627
|
+
return await executeProviderCallWithModelFallback(
|
|
3628
|
+
options.fallbackModel,
|
|
3629
|
+
async () => await executeProviderCallWithRetry(
|
|
3630
|
+
options.retry,
|
|
3631
|
+
async () => await requestCloudflareWorkersAiChatCompletion(options, input)
|
|
3632
|
+
),
|
|
3633
|
+
async (fallbackModelId) => await requestCloudflareWorkersAiChatCompletion(
|
|
3634
|
+
{ ...options, model: fallbackModelId },
|
|
3635
|
+
input
|
|
3636
|
+
)
|
|
3637
|
+
);
|
|
3638
|
+
}
|
|
3639
|
+
async function requestCloudflareWorkersAiChatCompletion(options, input) {
|
|
3640
|
+
const apiToken = resolveProviderApiKey({
|
|
3641
|
+
providerLabel: "Cloudflare Workers AI",
|
|
3642
|
+
adapterFunctionName: "cloudflareWorkersAi()",
|
|
3643
|
+
baseEnvVarName: "CLOUDFLARE_API_TOKEN",
|
|
3644
|
+
apiKey: options.apiKey,
|
|
3645
|
+
apiKeyName: options.apiKeyName
|
|
3646
|
+
});
|
|
3647
|
+
const fetchImplementation = options.fetchImplementation ?? fetch;
|
|
3648
|
+
const requestUrl = buildCloudflareWorkersAiChatCompletionsUrl(options);
|
|
3649
|
+
const requestBody = mergeProviderRequestExtraBody(
|
|
3650
|
+
buildOpenAiRequestBody(options.model, input),
|
|
3651
|
+
options.extraBody,
|
|
3652
|
+
input.extraBody
|
|
3653
|
+
);
|
|
3654
|
+
const startedAt = Date.now();
|
|
3655
|
+
const response = await executeAbortableProviderFetch(
|
|
3656
|
+
"Cloudflare Workers AI",
|
|
3657
|
+
async () => await fetchImplementation(requestUrl, {
|
|
3658
|
+
method: "POST",
|
|
3659
|
+
headers: {
|
|
3660
|
+
"Content-Type": "application/json",
|
|
3661
|
+
Authorization: `Bearer ${apiToken}`
|
|
3662
|
+
},
|
|
3663
|
+
body: JSON.stringify(requestBody),
|
|
3664
|
+
signal: input.abortSignal
|
|
3665
|
+
})
|
|
3666
|
+
);
|
|
3667
|
+
const latencyMs = Date.now() - startedAt;
|
|
3668
|
+
if (!response.ok) {
|
|
3669
|
+
throw buildProviderStatusError("Cloudflare Workers AI", response.status);
|
|
3670
|
+
}
|
|
3671
|
+
const parseResult = CloudflareWorkersAiChatCompletionResponseSchema.safeParse(
|
|
3672
|
+
await response.json()
|
|
3673
|
+
);
|
|
3674
|
+
if (!parseResult.success) {
|
|
3675
|
+
throw buildProviderInvalidResponseError(
|
|
3676
|
+
"Cloudflare Workers AI",
|
|
3677
|
+
"chat completion"
|
|
3678
|
+
);
|
|
3679
|
+
}
|
|
3680
|
+
return mapCloudflareWorkersAiResponseToChatCompletionResult(
|
|
3681
|
+
parseResult.data,
|
|
3682
|
+
latencyMs
|
|
3683
|
+
);
|
|
3684
|
+
}
|
|
3685
|
+
function mapCloudflareWorkersAiResponseToChatCompletionResult(response, latencyMs) {
|
|
3686
|
+
const toolCalls = extractCloudflareWorkersAiToolCalls(response);
|
|
3687
|
+
const result = {
|
|
3688
|
+
content: extractCloudflareWorkersAiMessageContent(
|
|
3689
|
+
response,
|
|
3690
|
+
toolCalls.length > 0
|
|
3691
|
+
),
|
|
3692
|
+
tokenUsage: mapCloudflareWorkersAiUsageToTokenUsage(response),
|
|
3693
|
+
latencyMs
|
|
3694
|
+
};
|
|
3695
|
+
const finishReason = response.choices[0]?.finish_reason;
|
|
3696
|
+
if (toolCalls.length > 0) {
|
|
3697
|
+
result.toolCalls = toolCalls;
|
|
3698
|
+
}
|
|
3699
|
+
if (finishReason !== null && finishReason !== void 0) {
|
|
3700
|
+
result.stopReason = normalizeCloudflareWorkersAiFinishReason(finishReason);
|
|
3701
|
+
}
|
|
3702
|
+
return result;
|
|
3703
|
+
}
|
|
3704
|
+
function extractCloudflareWorkersAiToolCalls(response) {
|
|
3705
|
+
const responseToolCalls = response.choices[0]?.message.tool_calls ?? [];
|
|
3706
|
+
return responseToolCalls.map((responseToolCall) => ({
|
|
3707
|
+
id: responseToolCall.id,
|
|
3708
|
+
toolName: responseToolCall.function.name,
|
|
3709
|
+
input: parseCloudflareWorkersAiToolArgumentsJson(
|
|
3710
|
+
responseToolCall.function.arguments
|
|
3711
|
+
)
|
|
3712
|
+
}));
|
|
3713
|
+
}
|
|
3714
|
+
function parseCloudflareWorkersAiToolArgumentsJson(argumentsJsonText) {
|
|
3715
|
+
if (argumentsJsonText.trim().length === 0) {
|
|
3716
|
+
return {};
|
|
3717
|
+
}
|
|
3718
|
+
try {
|
|
3719
|
+
return JsonValueSchema10.parse(JSON.parse(argumentsJsonText));
|
|
3720
|
+
} catch (error) {
|
|
3721
|
+
throw new AppError20({
|
|
3722
|
+
code: AppErrorCode19.ValidationFailed,
|
|
3723
|
+
message: "Cloudflare Workers AI tool call arguments were not valid JSON",
|
|
3724
|
+
statusCode: 502,
|
|
3725
|
+
cause: error instanceof Error ? error : void 0
|
|
3726
|
+
});
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
function normalizeCloudflareWorkersAiFinishReason(finishReason) {
|
|
3730
|
+
if (finishReason === "tool_calls") {
|
|
3731
|
+
return "tool_use";
|
|
3732
|
+
}
|
|
3733
|
+
if (finishReason === "length") {
|
|
3734
|
+
return "max_tokens";
|
|
3735
|
+
}
|
|
3736
|
+
return "end_turn";
|
|
3737
|
+
}
|
|
3738
|
+
function extractCloudflareWorkersAiMessageContent(response, allowEmptyContent) {
|
|
3739
|
+
const content = response.choices[0]?.message.content;
|
|
3740
|
+
if (content === void 0 || content === null) {
|
|
3741
|
+
if (allowEmptyContent) {
|
|
3742
|
+
return "";
|
|
3743
|
+
}
|
|
3744
|
+
throw new AppError20({
|
|
3745
|
+
code: AppErrorCode19.ValidationFailed,
|
|
3746
|
+
message: "Cloudflare Workers AI response contained no message content",
|
|
3747
|
+
statusCode: 502
|
|
3748
|
+
});
|
|
3749
|
+
}
|
|
3750
|
+
return content;
|
|
3751
|
+
}
|
|
3752
|
+
function mapCloudflareWorkersAiUsageToTokenUsage(response) {
|
|
3753
|
+
if (response.usage === void 0) {
|
|
3754
|
+
return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
|
|
3755
|
+
}
|
|
3756
|
+
return {
|
|
3757
|
+
inputTokens: response.usage.prompt_tokens,
|
|
3758
|
+
outputTokens: response.usage.completion_tokens,
|
|
3759
|
+
totalTokens: response.usage.total_tokens
|
|
3760
|
+
};
|
|
3761
|
+
}
|
|
3343
3762
|
export {
|
|
3344
3763
|
AnthropicMessagesResponseSchema,
|
|
3345
3764
|
AnthropicStreamEventSchema,
|
|
@@ -3365,11 +3784,13 @@ export {
|
|
|
3365
3784
|
buildAzureOpenAiChatRequestBody,
|
|
3366
3785
|
buildBedrockInvokeModelRequestBody,
|
|
3367
3786
|
buildBedrockInvokeModelUrl,
|
|
3787
|
+
buildCloudflareWorkersAiChatCompletionsUrl,
|
|
3368
3788
|
buildGeminiResponseSchema,
|
|
3369
3789
|
buildOpenAiRequestBody,
|
|
3370
3790
|
buildOpenAiStructuredOutputJsonSchema,
|
|
3371
3791
|
buildProviderCanceledError,
|
|
3372
3792
|
calculateProviderRetryDelayMs,
|
|
3793
|
+
cloudflareWorkersAi,
|
|
3373
3794
|
convertZodSchemaToJsonSchema,
|
|
3374
3795
|
createAnthropicBatchClient,
|
|
3375
3796
|
defaultAnthropicBaseUrl,
|
|
@@ -3378,8 +3799,10 @@ export {
|
|
|
3378
3799
|
defaultAnthropicMaxOutputTokens,
|
|
3379
3800
|
defaultAzureOpenAiApiVersion,
|
|
3380
3801
|
defaultBedrockMaxOutputTokens,
|
|
3802
|
+
defaultCloudflareApiBaseUrl,
|
|
3381
3803
|
defaultGeminiBaseUrl,
|
|
3382
3804
|
defaultOpenAiBaseUrl,
|
|
3805
|
+
defaultOpenRouterBaseUrl,
|
|
3383
3806
|
defaultProviderRetryInitialDelayMs,
|
|
3384
3807
|
defaultProviderRetryMaxAttempts,
|
|
3385
3808
|
defaultProviderRetryMaxDelayMs,
|
|
@@ -3413,6 +3836,7 @@ export {
|
|
|
3413
3836
|
normalizeAzureOpenAiFinishReason,
|
|
3414
3837
|
openAiStructuredOutputSchemaName,
|
|
3415
3838
|
openai,
|
|
3839
|
+
openrouter,
|
|
3416
3840
|
parseAnthropicBatchStructuredContent,
|
|
3417
3841
|
parseAnthropicStreamEvents,
|
|
3418
3842
|
parseAnthropicToolInputJson,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assemble-dev/providers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"description": "Model provider adapters for the Assemble SDK",
|
|
6
6
|
"repository": {
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"zod": "^4.1.13",
|
|
30
|
-
"@assemble-dev/shared-types": "0.
|
|
31
|
-
"@assemble-dev/shared-utils": "0.
|
|
30
|
+
"@assemble-dev/shared-types": "0.4.1",
|
|
31
|
+
"@assemble-dev/shared-utils": "0.4.1"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/node": "^20.19.0",
|