@vedmalex/ai-connect 0.11.0 → 0.13.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/README.md +54 -0
- package/dist/browser/index.js +120 -48
- package/dist/browser/index.js.map +2 -2
- package/dist/bun/index.js +157 -58
- package/dist/bun/index.js.map +2 -2
- package/dist/bun/local.js +157 -58
- package/dist/bun/local.js.map +2 -2
- package/dist/bun/registry-fs.js +1194 -0
- package/dist/bun/registry-fs.js.map +7 -0
- package/dist/node/index.js +157 -58
- package/dist/node/index.js.map +2 -2
- package/dist/node/local.js +157 -58
- package/dist/node/local.js.map +2 -2
- package/dist/node/registry-fs.js +1194 -0
- package/dist/node/registry-fs.js.map +7 -0
- package/dist/registry/index.js +1119 -0
- package/dist/registry/index.js.map +7 -0
- package/dist/types/acp.d.ts.map +1 -1
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/default-handlers.d.ts.map +1 -1
- package/dist/types/mock-gateway.d.ts +20 -0
- package/dist/types/mock-gateway.d.ts.map +1 -1
- package/dist/types/registry/compile.d.ts +24 -0
- package/dist/types/registry/compile.d.ts.map +1 -0
- package/dist/types/registry/convert-v1.d.ts +21 -0
- package/dist/types/registry/convert-v1.d.ts.map +1 -0
- package/dist/types/registry/fs.d.ts +124 -0
- package/dist/types/registry/fs.d.ts.map +1 -0
- package/dist/types/registry/index.d.ts +15 -0
- package/dist/types/registry/index.d.ts.map +1 -0
- package/dist/types/registry/merge.d.ts +26 -0
- package/dist/types/registry/merge.d.ts.map +1 -0
- package/dist/types/registry/parse.d.ts +26 -0
- package/dist/types/registry/parse.d.ts.map +1 -0
- package/dist/types/registry/save.d.ts +96 -0
- package/dist/types/registry/save.d.ts.map +1 -0
- package/dist/types/registry/types.d.ts +168 -0
- package/dist/types/registry/types.d.ts.map +1 -0
- package/dist/types/router.d.ts.map +1 -1
- package/dist/types/server.d.ts.map +1 -1
- package/dist/types/transport-runtime.d.ts +30 -0
- package/dist/types/transport-runtime.d.ts.map +1 -1
- package/dist/types/types.d.ts +66 -2
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +15 -2
- package/schema/connections.v2.json +395 -0
package/README.md
CHANGED
|
@@ -611,6 +611,60 @@ Three error codes are intentionally **hard-terminal**: they never rotate, retry,
|
|
|
611
611
|
|
|
612
612
|
All other normalized error codes (`rate_limit`, `quota_exhausted`, `temporary_unavailable`, etc.) remain eligible for the rotation/retry/fallback chain you configure under `routing.fallback`.
|
|
613
613
|
|
|
614
|
+
## Connection Registry (`connections.json`)
|
|
615
|
+
|
|
616
|
+
Instead of hand-writing `defineConfig(...)`, you can declare your whole topology — endpoints,
|
|
617
|
+
aliases (ordered failover chains), auth, and defaults — in a single **v2 registry document** and
|
|
618
|
+
compile it into the exact config the client already consumes, plus ready-made `routeHints` per
|
|
619
|
+
alias. It ships as two subpaths: `@vedmalex/ai-connect/registry` (pure, browser-safe:
|
|
620
|
+
`parseRegistry` / `compileRegistry` / `convertV1Registry` / `mergeRegistries`) and
|
|
621
|
+
`@vedmalex/ai-connect/registry/fs` (node/bun loader: `loadConnectionRegistry` / `loadV1Pair`).
|
|
622
|
+
|
|
623
|
+
```json
|
|
624
|
+
{
|
|
625
|
+
"$schema": "https://raw.githubusercontent.com/vedmalex/ai-connect/main/schema/connections.v2.json",
|
|
626
|
+
"version": 2,
|
|
627
|
+
"defaults": { "alias": "fast" },
|
|
628
|
+
"endpoints": [
|
|
629
|
+
{
|
|
630
|
+
"id": "openai-main",
|
|
631
|
+
"provider": "openai",
|
|
632
|
+
"transport": "api",
|
|
633
|
+
"baseUrl": "https://api.openai.com/v1",
|
|
634
|
+
"auth": { "tokenEnv": "OPENAI_API_KEY" },
|
|
635
|
+
"models": ["gpt-4.1"],
|
|
636
|
+
"defaultModel": "gpt-4.1"
|
|
637
|
+
}
|
|
638
|
+
],
|
|
639
|
+
"aliases": [{ "id": "fast", "chain": [{ "endpointId": "openai-main" }] }]
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
```ts
|
|
644
|
+
import { loadConnectionRegistry } from "@vedmalex/ai-connect/registry/fs";
|
|
645
|
+
import { compileRegistry } from "@vedmalex/ai-connect/registry";
|
|
646
|
+
import { createLocalClient } from "@vedmalex/ai-connect";
|
|
647
|
+
|
|
648
|
+
const loaded = await loadConnectionRegistry(); // layered: user → project → AI_CONNECT_CONNECTIONS
|
|
649
|
+
const compiled = compileRegistry(loaded.registry, { env: (name) => process.env[name] });
|
|
650
|
+
const client = createLocalClient(compiled.config);
|
|
651
|
+
|
|
652
|
+
const fast = compiled.aliases["fast"];
|
|
653
|
+
if (!fast?.usable) throw new Error('alias "fast" is not usable'); // never dispatch on usable:false
|
|
654
|
+
|
|
655
|
+
const result = await client.generate({
|
|
656
|
+
messages: [{ role: "user", content: "Summarize this design brief." }],
|
|
657
|
+
routeHints: fast.routeHints, // ordered failover pool
|
|
658
|
+
});
|
|
659
|
+
console.log(result.text);
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
The loader layers `~/.config/ai-connect/connections.json` (user) under
|
|
663
|
+
`<cwd>/.config/ai-connect/connections.json` (project) under `$AI_CONNECT_CONNECTIONS`, each with
|
|
664
|
+
a sibling `connections.secrets.json` overlay, and auto-converts legacy v1 (`rag-endpoints.json` +
|
|
665
|
+
`rag-aliases.json`) pairs. Full format, layering, failure-taxonomy, and v1-migration guide:
|
|
666
|
+
[docs/connection-registry.md](./docs/connection-registry.md).
|
|
667
|
+
|
|
614
668
|
## Cancellation, Pause, and Timeouts
|
|
615
669
|
|
|
616
670
|
`generate(request, opts?)` and `stream(request, opts?)` accept an optional second argument:
|
package/dist/browser/index.js
CHANGED
|
@@ -964,6 +964,13 @@ function normalizeTransport(providerId, input) {
|
|
|
964
964
|
methodId: descriptor.auth.methodId.trim(),
|
|
965
965
|
params: descriptor.auth.params ?? {}
|
|
966
966
|
} : void 0;
|
|
967
|
+
const normalizedHeaders = (() => {
|
|
968
|
+
if (!descriptor.headers) {
|
|
969
|
+
return void 0;
|
|
970
|
+
}
|
|
971
|
+
const entries = Object.entries(descriptor.headers).map(([key, value]) => [key.trim(), value]).filter(([key]) => key.length > 0);
|
|
972
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
973
|
+
})();
|
|
967
974
|
assert(
|
|
968
975
|
descriptor.kind === "api" || descriptor.kind === "acp" || descriptor.kind === "cli" || descriptor.kind === "server",
|
|
969
976
|
`Unsupported transport kind for provider "${providerId}".`
|
|
@@ -973,23 +980,79 @@ function normalizeTransport(providerId, input) {
|
|
|
973
980
|
!normalizedAuth,
|
|
974
981
|
`Transport auth is only supported for ACP routes. Provider "${providerId}" declared auth on a non-ACP transport.`
|
|
975
982
|
);
|
|
983
|
+
}
|
|
984
|
+
if (descriptor.kind === "api") {
|
|
976
985
|
assert(
|
|
977
986
|
!descriptor.launch,
|
|
978
|
-
`Transport launch options are only supported for
|
|
987
|
+
`Transport launch options are only supported for local (acp/cli/server) routes. Provider "${providerId}" declared launch settings on an api transport.`
|
|
979
988
|
);
|
|
980
989
|
}
|
|
990
|
+
const normalizeLaunch = () => {
|
|
991
|
+
const launchInput = descriptor.launch;
|
|
992
|
+
if (!launchInput) {
|
|
993
|
+
return void 0;
|
|
994
|
+
}
|
|
995
|
+
if (descriptor.kind !== "acp") {
|
|
996
|
+
assert(
|
|
997
|
+
launchInput.contextMode === void 0,
|
|
998
|
+
`Transport launch.contextMode is only supported for ACP routes. Provider "${providerId}" declared it on a ${descriptor.kind} transport.`
|
|
999
|
+
);
|
|
1000
|
+
assert(
|
|
1001
|
+
launchInput.skillsMode === void 0,
|
|
1002
|
+
`Transport launch.skillsMode is only supported for ACP routes. Provider "${providerId}" declared it on a ${descriptor.kind} transport.`
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
const contextMode = launchInput.contextMode ?? "workspace";
|
|
1006
|
+
const skillsMode = launchInput.skillsMode ?? "default";
|
|
1007
|
+
assert(
|
|
1008
|
+
contextMode === "workspace" || contextMode === "clean",
|
|
1009
|
+
`Unsupported ACP contextMode "${String(contextMode)}" for provider "${providerId}".`
|
|
1010
|
+
);
|
|
1011
|
+
assert(
|
|
1012
|
+
skillsMode === "default" || skillsMode === "disabled",
|
|
1013
|
+
`Unsupported ACP skillsMode "${String(skillsMode)}" for provider "${providerId}".`
|
|
1014
|
+
);
|
|
1015
|
+
const env = (() => {
|
|
1016
|
+
if (!launchInput.env) {
|
|
1017
|
+
return void 0;
|
|
1018
|
+
}
|
|
1019
|
+
const entries = Object.entries(launchInput.env).map(([key, value]) => [key.trim(), value]).filter(([key]) => key.length > 0);
|
|
1020
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
1021
|
+
})();
|
|
1022
|
+
const envPassthrough = (() => {
|
|
1023
|
+
if (!launchInput.envPassthrough) {
|
|
1024
|
+
return void 0;
|
|
1025
|
+
}
|
|
1026
|
+
const names = launchInput.envPassthrough.map((name) => String(name).trim()).filter((name) => name.length > 0);
|
|
1027
|
+
return names.length > 0 ? names : void 0;
|
|
1028
|
+
})();
|
|
1029
|
+
return {
|
|
1030
|
+
contextMode,
|
|
1031
|
+
skillsMode,
|
|
1032
|
+
...env ? { env } : {},
|
|
1033
|
+
...envPassthrough ? { envPassthrough } : {}
|
|
1034
|
+
};
|
|
1035
|
+
};
|
|
1036
|
+
const normalizedLaunch = normalizeLaunch();
|
|
981
1037
|
if (descriptor.kind !== "cli") {
|
|
982
1038
|
assert(
|
|
983
1039
|
!normalizedCli,
|
|
984
1040
|
`CLI transport options are only supported for CLI routes. Provider "${providerId}" declared cli settings on a non-CLI transport.`
|
|
985
1041
|
);
|
|
986
1042
|
}
|
|
1043
|
+
if (descriptor.kind !== "api") {
|
|
1044
|
+
assert(
|
|
1045
|
+
!normalizedHeaders,
|
|
1046
|
+
`Transport headers are only supported for API routes. Provider "${providerId}" declared headers on a non-API transport.`
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
987
1049
|
if (descriptor.kind === "api") {
|
|
988
1050
|
return {
|
|
989
1051
|
kind: "api",
|
|
990
1052
|
id: descriptor.id?.trim() || "api",
|
|
991
1053
|
...descriptor.command?.trim() ? { command: descriptor.command.trim() } : {},
|
|
992
|
-
...descriptor.baseUrl?.trim() ? { baseUrl: descriptor.baseUrl.trim() } : {}
|
|
1054
|
+
...descriptor.baseUrl?.trim() ? { baseUrl: descriptor.baseUrl.trim() } : {},
|
|
1055
|
+
...normalizedHeaders ? { headers: normalizedHeaders } : {}
|
|
993
1056
|
};
|
|
994
1057
|
}
|
|
995
1058
|
if (descriptor.kind === "cli") {
|
|
@@ -998,7 +1061,8 @@ function normalizeTransport(providerId, input) {
|
|
|
998
1061
|
kind: "cli",
|
|
999
1062
|
id: descriptor.id?.trim() || inferredId2,
|
|
1000
1063
|
...descriptor.command?.trim() ? { command: descriptor.command.trim() } : {},
|
|
1001
|
-
...normalizedCli ? { cli: normalizedCli } : {}
|
|
1064
|
+
...normalizedCli ? { cli: normalizedCli } : {},
|
|
1065
|
+
...normalizedLaunch ? { launch: normalizedLaunch } : {}
|
|
1002
1066
|
};
|
|
1003
1067
|
}
|
|
1004
1068
|
if (descriptor.kind === "server") {
|
|
@@ -1007,26 +1071,11 @@ function normalizeTransport(providerId, input) {
|
|
|
1007
1071
|
kind: "server",
|
|
1008
1072
|
id: descriptor.id?.trim() || inferredId2,
|
|
1009
1073
|
...descriptor.command?.trim() ? { command: descriptor.command.trim() } : {},
|
|
1010
|
-
...descriptor.baseUrl?.trim() ? { baseUrl: descriptor.baseUrl.trim() } : {}
|
|
1074
|
+
...descriptor.baseUrl?.trim() ? { baseUrl: descriptor.baseUrl.trim() } : {},
|
|
1075
|
+
...normalizedLaunch ? { launch: normalizedLaunch } : {}
|
|
1011
1076
|
};
|
|
1012
1077
|
}
|
|
1013
1078
|
const inferredId = ACP_TRANSPORT_ID_BY_PROVIDER[providerId] ?? "acp";
|
|
1014
|
-
const normalizedLaunch = descriptor.launch ? (() => {
|
|
1015
|
-
const contextMode = descriptor.launch?.contextMode ?? "workspace";
|
|
1016
|
-
const skillsMode = descriptor.launch?.skillsMode ?? "default";
|
|
1017
|
-
assert(
|
|
1018
|
-
contextMode === "workspace" || contextMode === "clean",
|
|
1019
|
-
`Unsupported ACP contextMode "${String(contextMode)}" for provider "${providerId}".`
|
|
1020
|
-
);
|
|
1021
|
-
assert(
|
|
1022
|
-
skillsMode === "default" || skillsMode === "disabled",
|
|
1023
|
-
`Unsupported ACP skillsMode "${String(skillsMode)}" for provider "${providerId}".`
|
|
1024
|
-
);
|
|
1025
|
-
return {
|
|
1026
|
-
contextMode,
|
|
1027
|
-
skillsMode
|
|
1028
|
-
};
|
|
1029
|
-
})() : void 0;
|
|
1030
1079
|
return {
|
|
1031
1080
|
kind: "acp",
|
|
1032
1081
|
id: descriptor.id?.trim() || inferredId,
|
|
@@ -1245,12 +1294,16 @@ function normalizeOperationRouting(input, routes, defaultStrategy, resolution) {
|
|
|
1245
1294
|
if (Array.isArray(input)) {
|
|
1246
1295
|
return {
|
|
1247
1296
|
strategy: defaultStrategy,
|
|
1248
|
-
pool: resolveRouteRefs(input, routes, policy)
|
|
1297
|
+
pool: resolveRouteRefs(input, routes, policy),
|
|
1298
|
+
// WU-1: an explicit selector list was supplied iff it is non-empty (an empty list makes
|
|
1299
|
+
// resolveRouteRefs default to all routes — indistinguishable from "no pool given").
|
|
1300
|
+
explicitPool: input.length > 0
|
|
1249
1301
|
};
|
|
1250
1302
|
}
|
|
1251
1303
|
return {
|
|
1252
1304
|
strategy: input?.strategy ?? defaultStrategy,
|
|
1253
|
-
pool: resolveRouteRefs(input?.pool, routes, policy)
|
|
1305
|
+
pool: resolveRouteRefs(input?.pool, routes, policy),
|
|
1306
|
+
explicitPool: Boolean(input?.pool && input.pool.length > 0)
|
|
1254
1307
|
};
|
|
1255
1308
|
}
|
|
1256
1309
|
function finalizeRotationCapabilities(routes) {
|
|
@@ -2398,6 +2451,7 @@ var RouteRegistry = class {
|
|
|
2398
2451
|
)
|
|
2399
2452
|
).map((route) => applyRequestedModel(route, requestedModel)).filter((route) => Boolean(route));
|
|
2400
2453
|
const strategy = request.routeHints?.strategy ?? operationRouting.strategy;
|
|
2454
|
+
const orderedPool = Boolean(request.routeHints?.pool?.length) || operationRouting.explicitPool;
|
|
2401
2455
|
const cursorKey = `${operation}:${strategy}:${eligible.map((route) => route.id).join("|")}`;
|
|
2402
2456
|
const healthyIds = new Set(
|
|
2403
2457
|
eligible.filter((route) => {
|
|
@@ -2410,7 +2464,8 @@ var RouteRegistry = class {
|
|
|
2410
2464
|
eligible,
|
|
2411
2465
|
healthyIds,
|
|
2412
2466
|
request.routeHints?.preferredProviders,
|
|
2413
|
-
cursorKey
|
|
2467
|
+
cursorKey,
|
|
2468
|
+
orderedPool
|
|
2414
2469
|
);
|
|
2415
2470
|
}
|
|
2416
2471
|
recordSuccess(route) {
|
|
@@ -2443,9 +2498,10 @@ var RouteRegistry = class {
|
|
|
2443
2498
|
failureCount
|
|
2444
2499
|
});
|
|
2445
2500
|
}
|
|
2446
|
-
#order(strategy, eligible, healthyIds, preferredProviders, cursorKey) {
|
|
2447
|
-
const
|
|
2448
|
-
const
|
|
2501
|
+
#order(strategy, eligible, healthyIds, preferredProviders, cursorKey, orderedPool) {
|
|
2502
|
+
const honorPoolOrder = strategy === "failover" && orderedPool;
|
|
2503
|
+
const sorted = honorPoolOrder ? eligible : baseSort(eligible, preferredProviders);
|
|
2504
|
+
const orderedFull = !honorPoolOrder && this.config.routing.shuffleOnInit ? this.#shuffle(cursorKey, sorted) : sorted;
|
|
2449
2505
|
const ordered = orderedFull.filter((route) => healthyIds.has(route.id));
|
|
2450
2506
|
const strategyFn = ROUTING_STRATEGIES[strategy];
|
|
2451
2507
|
return strategyFn(ordered, (key, length) => this.#cursor(key, length), cursorKey);
|
|
@@ -5343,6 +5399,22 @@ function extractImagePayloads(...nodes) {
|
|
|
5343
5399
|
|
|
5344
5400
|
// src/default-handlers.ts
|
|
5345
5401
|
var INLINE_ATTACHMENT_TEXT_LIMIT = 16e3;
|
|
5402
|
+
function mergeRouteHeaders(route, builtin) {
|
|
5403
|
+
const routeHeaders = route.transport.headers;
|
|
5404
|
+
if (!routeHeaders || Object.keys(routeHeaders).length === 0) {
|
|
5405
|
+
return builtin;
|
|
5406
|
+
}
|
|
5407
|
+
const builtinKeys = new Set(
|
|
5408
|
+
Object.keys(builtin).map((key) => key.toLowerCase())
|
|
5409
|
+
);
|
|
5410
|
+
const passthrough = {};
|
|
5411
|
+
for (const [key, value] of Object.entries(routeHeaders)) {
|
|
5412
|
+
if (!builtinKeys.has(key.toLowerCase())) {
|
|
5413
|
+
passthrough[key] = value;
|
|
5414
|
+
}
|
|
5415
|
+
}
|
|
5416
|
+
return { ...passthrough, ...builtin };
|
|
5417
|
+
}
|
|
5346
5418
|
function trimTrailingSlash(value) {
|
|
5347
5419
|
return value.replace(/\/+$/, "");
|
|
5348
5420
|
}
|
|
@@ -5967,9 +6039,9 @@ async function discoverOpenAiModels(fetchImpl, context) {
|
|
|
5967
6039
|
discoveryTransportSummary(context, "openai-models", endpoint, "GET");
|
|
5968
6040
|
const response = await fetchImpl(endpoint, {
|
|
5969
6041
|
method: "GET",
|
|
5970
|
-
headers: {
|
|
6042
|
+
headers: mergeRouteHeaders(context.route, {
|
|
5971
6043
|
authorization: `Bearer ${apiKey}`
|
|
5972
|
-
},
|
|
6044
|
+
}),
|
|
5973
6045
|
signal: context.abort.signal
|
|
5974
6046
|
});
|
|
5975
6047
|
const payload = await readPayload(response);
|
|
@@ -5984,10 +6056,10 @@ async function discoverAnthropicModels(fetchImpl, context) {
|
|
|
5984
6056
|
discoveryTransportSummary(context, "anthropic-models", endpoint, "GET");
|
|
5985
6057
|
const response = await fetchImpl(endpoint, {
|
|
5986
6058
|
method: "GET",
|
|
5987
|
-
headers: {
|
|
6059
|
+
headers: mergeRouteHeaders(context.route, {
|
|
5988
6060
|
"x-api-key": apiKey,
|
|
5989
6061
|
"anthropic-version": "2023-06-01"
|
|
5990
|
-
},
|
|
6062
|
+
}),
|
|
5991
6063
|
signal: context.abort.signal
|
|
5992
6064
|
});
|
|
5993
6065
|
const payload = await readPayload(response);
|
|
@@ -6002,7 +6074,7 @@ async function discoverGeminiModels(fetchImpl, context) {
|
|
|
6002
6074
|
discoveryTransportSummary(context, "gemini-models", endpoint, "GET");
|
|
6003
6075
|
const response = await fetchImpl(endpoint, {
|
|
6004
6076
|
method: "GET",
|
|
6005
|
-
headers: geminiApiKeyHeaders(apiKey),
|
|
6077
|
+
headers: mergeRouteHeaders(context.route, geminiApiKeyHeaders(apiKey)),
|
|
6006
6078
|
signal: context.abort.signal
|
|
6007
6079
|
});
|
|
6008
6080
|
const payload = await readPayload(response);
|
|
@@ -6215,11 +6287,11 @@ async function uploadAnthropicFile(payload, uploader) {
|
|
|
6215
6287
|
);
|
|
6216
6288
|
const response = await uploader.fetchImpl(endpoint, {
|
|
6217
6289
|
method: "POST",
|
|
6218
|
-
headers: {
|
|
6290
|
+
headers: mergeRouteHeaders(uploader.context.route, {
|
|
6219
6291
|
"x-api-key": uploader.apiKey,
|
|
6220
6292
|
"anthropic-version": "2023-06-01",
|
|
6221
6293
|
"anthropic-beta": "files-api-2025-04-14"
|
|
6222
|
-
},
|
|
6294
|
+
}),
|
|
6223
6295
|
body: form,
|
|
6224
6296
|
signal: uploader.context.abort.signal
|
|
6225
6297
|
});
|
|
@@ -6253,9 +6325,9 @@ async function uploadOpenAiFile(payload, uploader) {
|
|
|
6253
6325
|
form.append("purpose", "user_data");
|
|
6254
6326
|
const response = await uploader.fetchImpl(endpoint, {
|
|
6255
6327
|
method: "POST",
|
|
6256
|
-
headers: {
|
|
6328
|
+
headers: mergeRouteHeaders(uploader.context.route, {
|
|
6257
6329
|
authorization: `Bearer ${uploader.apiKey}`
|
|
6258
|
-
},
|
|
6330
|
+
}),
|
|
6259
6331
|
body: form,
|
|
6260
6332
|
signal: uploader.context.abort.signal
|
|
6261
6333
|
});
|
|
@@ -6285,12 +6357,12 @@ async function uploadGeminiFile(payload, uploader) {
|
|
|
6285
6357
|
) : "https://generativelanguage.googleapis.com/upload/v1beta/files";
|
|
6286
6358
|
const response = await uploader.fetchImpl(endpoint, {
|
|
6287
6359
|
method: "POST",
|
|
6288
|
-
headers: {
|
|
6360
|
+
headers: mergeRouteHeaders(uploader.context.route, {
|
|
6289
6361
|
...geminiApiKeyHeaders(uploader.apiKey),
|
|
6290
6362
|
"X-Goog-Upload-Protocol": "raw",
|
|
6291
6363
|
"X-Goog-Upload-Header-Content-Type": payload.mimeType,
|
|
6292
6364
|
"content-type": payload.mimeType
|
|
6293
|
-
},
|
|
6365
|
+
}),
|
|
6294
6366
|
body: base64ToBlob(payload.base64, payload.mimeType),
|
|
6295
6367
|
signal: uploader.context.abort.signal
|
|
6296
6368
|
});
|
|
@@ -6872,10 +6944,10 @@ async function runOpenAi(fetchImpl, context) {
|
|
|
6872
6944
|
transportSummary(context, "openai-chat", endpoint, "POST", false, body);
|
|
6873
6945
|
const response = await fetchImpl(endpoint, {
|
|
6874
6946
|
method: "POST",
|
|
6875
|
-
headers: {
|
|
6947
|
+
headers: mergeRouteHeaders(context.route, {
|
|
6876
6948
|
"content-type": "application/json",
|
|
6877
6949
|
authorization: `Bearer ${apiKey}`
|
|
6878
|
-
},
|
|
6950
|
+
}),
|
|
6879
6951
|
body: JSON.stringify(body),
|
|
6880
6952
|
signal: context.abort.signal
|
|
6881
6953
|
});
|
|
@@ -6954,10 +7026,10 @@ async function* runOpenAiStream(fetchImpl, context) {
|
|
|
6954
7026
|
transportSummary(context, "openai-chat", endpoint, "POST", true, body);
|
|
6955
7027
|
const response2 = await fetchImpl(endpoint, {
|
|
6956
7028
|
method: "POST",
|
|
6957
|
-
headers: {
|
|
7029
|
+
headers: mergeRouteHeaders(context.route, {
|
|
6958
7030
|
"content-type": "application/json",
|
|
6959
7031
|
authorization: `Bearer ${apiKey}`
|
|
6960
|
-
},
|
|
7032
|
+
}),
|
|
6961
7033
|
body: JSON.stringify(body),
|
|
6962
7034
|
signal: context.abort.signal
|
|
6963
7035
|
});
|
|
@@ -7162,15 +7234,15 @@ async function runProviderImage(fetchImpl, context, opts) {
|
|
|
7162
7234
|
);
|
|
7163
7235
|
const response = await fetchImpl(endpoint, useEditEndpoint ? {
|
|
7164
7236
|
method: "POST",
|
|
7165
|
-
headers: { ...opts.authHeaders },
|
|
7237
|
+
headers: mergeRouteHeaders(context.route, { ...opts.authHeaders }),
|
|
7166
7238
|
body: await buildImageEditFormData(context, baseFields),
|
|
7167
7239
|
signal: context.abort.signal
|
|
7168
7240
|
} : {
|
|
7169
7241
|
method: "POST",
|
|
7170
|
-
headers: {
|
|
7242
|
+
headers: mergeRouteHeaders(context.route, {
|
|
7171
7243
|
"content-type": "application/json",
|
|
7172
7244
|
...opts.authHeaders
|
|
7173
|
-
},
|
|
7245
|
+
}),
|
|
7174
7246
|
body: JSON.stringify(baseFields),
|
|
7175
7247
|
signal: context.abort.signal
|
|
7176
7248
|
});
|
|
@@ -7225,11 +7297,11 @@ async function runAnthropic(fetchImpl, context) {
|
|
|
7225
7297
|
transportSummary(context, "anthropic-messages", endpoint, "POST", false, requestBody);
|
|
7226
7298
|
const response = await fetchImpl(endpoint, {
|
|
7227
7299
|
method: "POST",
|
|
7228
|
-
headers: {
|
|
7300
|
+
headers: mergeRouteHeaders(context.route, {
|
|
7229
7301
|
"content-type": "application/json",
|
|
7230
7302
|
"x-api-key": apiKey,
|
|
7231
7303
|
"anthropic-version": "2023-06-01"
|
|
7232
|
-
},
|
|
7304
|
+
}),
|
|
7233
7305
|
body: JSON.stringify(requestBody),
|
|
7234
7306
|
signal: context.abort.signal
|
|
7235
7307
|
});
|
|
@@ -7294,10 +7366,10 @@ async function runGemini(fetchImpl, context) {
|
|
|
7294
7366
|
transportSummary(context, "gemini-generate-content", endpoint, "POST", false, requestBody);
|
|
7295
7367
|
const response = await fetchImpl(endpoint, {
|
|
7296
7368
|
method: "POST",
|
|
7297
|
-
headers: {
|
|
7369
|
+
headers: mergeRouteHeaders(context.route, {
|
|
7298
7370
|
...geminiApiKeyHeaders(apiKey),
|
|
7299
7371
|
"content-type": "application/json"
|
|
7300
|
-
},
|
|
7372
|
+
}),
|
|
7301
7373
|
body: JSON.stringify(requestBody),
|
|
7302
7374
|
signal: context.abort.signal
|
|
7303
7375
|
});
|