@jacobbd/relay-ai 0.9.1 → 0.9.3
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/{chunk-Q2FTCICO.js → chunk-NYKVDBQC.js} +2 -2
- package/dist/{chunk-Q2FTCICO.js.map → chunk-NYKVDBQC.js.map} +1 -1
- package/dist/{chunk-MFKBK6YL.js → chunk-PVGAE7HA.js} +693 -144
- package/dist/chunk-PVGAE7HA.js.map +1 -0
- package/dist/cli.js +148 -9
- package/dist/cli.js.map +1 -1
- package/dist/core/index.d.ts +40 -5
- package/dist/core/index.js +976 -28
- package/dist/core/index.js.map +1 -1
- package/dist/{provider-templates-XKNRKAQU.js → provider-templates-CGWE66TD.js} +2 -2
- package/dist/ui/public/app.js +190 -1
- package/dist/{ui-command-ZJBZZZ4X.js → ui-command-JQPEZAMN.js} +59 -7
- package/dist/ui-command-JQPEZAMN.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-MFKBK6YL.js.map +0 -1
- package/dist/ui-command-ZJBZZZ4X.js.map +0 -1
- /package/dist/{provider-templates-XKNRKAQU.js.map → provider-templates-CGWE66TD.js.map} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
getTemplateById,
|
|
4
4
|
init_provider_templates
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NYKVDBQC.js";
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
8
|
import { homedir } from "os";
|
|
@@ -11,7 +11,7 @@ import { join } from "path";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@jacobbd/relay-ai",
|
|
14
|
-
version: "0.9.
|
|
14
|
+
version: "0.9.3",
|
|
15
15
|
publishConfig: {
|
|
16
16
|
access: "public"
|
|
17
17
|
},
|
|
@@ -345,7 +345,320 @@ async function runOpenAiDeviceCodeFlow(onDeviceCode, opts) {
|
|
|
345
345
|
|
|
346
346
|
// src/oauth/responses-websocket.ts
|
|
347
347
|
var RESPONSES_LITE_HEADER = "x-openai-internal-codex-responses-lite";
|
|
348
|
-
var TERMINAL_EVENT_TYPES = /* @__PURE__ */ new Set(["response.completed", "response.failed", "response.incomplete"]);
|
|
348
|
+
var TERMINAL_EVENT_TYPES = /* @__PURE__ */ new Set(["response.completed", "response.failed", "response.incomplete", "error"]);
|
|
349
|
+
function isRecord(value) {
|
|
350
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
351
|
+
}
|
|
352
|
+
function recordKeys(value) {
|
|
353
|
+
return isRecord(value) ? Object.keys(value).sort().join(",") : "";
|
|
354
|
+
}
|
|
355
|
+
function summarizeResponsesLiteEvent(event) {
|
|
356
|
+
if (!isRecord(event)) return `kind=${event == null ? "null" : typeof event}`;
|
|
357
|
+
const parts = [`type=${typeof event.type === "string" ? event.type : "unknown"}`, `keys=${recordKeys(event)}`];
|
|
358
|
+
if (typeof event.delta === "string") parts.push(`deltaChars=${event.delta.length}`);
|
|
359
|
+
if (typeof event.output_index === "number") parts.push(`hasOutputIndex=1`);
|
|
360
|
+
if (typeof event.item_id === "string") parts.push(`hasItemId=1`);
|
|
361
|
+
if (isRecord(event.item)) {
|
|
362
|
+
parts.push(`itemType=${typeof event.item.type === "string" ? event.item.type : "unknown"}`);
|
|
363
|
+
parts.push(`itemKeys=${recordKeys(event.item)}`);
|
|
364
|
+
if (typeof event.item.arguments === "string") parts.push(`argumentsChars=${event.item.arguments.length}`);
|
|
365
|
+
}
|
|
366
|
+
if (isRecord(event.response)) {
|
|
367
|
+
parts.push(`responseKeys=${recordKeys(event.response)}`);
|
|
368
|
+
if (Array.isArray(event.response.output)) {
|
|
369
|
+
parts.push(`outputCount=${event.response.output.length}`);
|
|
370
|
+
parts.push(`outputTypes=${event.response.output.map((item) => isRecord(item) && typeof item.type === "string" ? item.type : "unknown").join(",")}`);
|
|
371
|
+
}
|
|
372
|
+
if (isRecord(event.response.usage)) parts.push(`usageKeys=${recordKeys(event.response.usage)}`);
|
|
373
|
+
if (typeof event.response.status === "string") parts.push(`status=${event.response.status}`);
|
|
374
|
+
}
|
|
375
|
+
if (isRecord(event.error)) {
|
|
376
|
+
parts.push(`errorKeys=${recordKeys(event.error)}`);
|
|
377
|
+
if (typeof event.error.message === "string") parts.push(`messageChars=${event.error.message.length}`);
|
|
378
|
+
}
|
|
379
|
+
return parts.join(" ");
|
|
380
|
+
}
|
|
381
|
+
function createResponsesLiteNormalizeState() {
|
|
382
|
+
return {
|
|
383
|
+
nextId: 1,
|
|
384
|
+
lastOutputIndex: 0,
|
|
385
|
+
textDeltaForwarded: false,
|
|
386
|
+
messageAddedIds: /* @__PURE__ */ new Set(),
|
|
387
|
+
messageDoneIds: /* @__PURE__ */ new Set(),
|
|
388
|
+
functionCalls: []
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function nextId(state, prefix) {
|
|
392
|
+
const id = `${prefix}_${state.nextId}`;
|
|
393
|
+
state.nextId += 1;
|
|
394
|
+
return id;
|
|
395
|
+
}
|
|
396
|
+
function asString(value) {
|
|
397
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
398
|
+
}
|
|
399
|
+
function normalizeErrorEvent(event) {
|
|
400
|
+
const raw = isRecord(event.error) ? event.error : { message: typeof event.error === "string" ? event.error : "upstream error" };
|
|
401
|
+
return {
|
|
402
|
+
type: "error",
|
|
403
|
+
sequence_number: typeof event.sequence_number === "number" ? event.sequence_number : 0,
|
|
404
|
+
error: {
|
|
405
|
+
type: asString(raw.type) ?? "server_error",
|
|
406
|
+
code: asString(raw.code) ?? "unknown",
|
|
407
|
+
message: asString(raw.message) ?? "upstream error",
|
|
408
|
+
...raw.param == null ? {} : { param: raw.param }
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function resolveFunctionCall(state, hint) {
|
|
413
|
+
if (hint.callId) {
|
|
414
|
+
const byCallId = state.functionCalls.find((entry2) => entry2.callId === hint.callId);
|
|
415
|
+
if (byCallId) return byCallId;
|
|
416
|
+
}
|
|
417
|
+
if (hint.itemId) {
|
|
418
|
+
const byItemId = state.functionCalls.find((entry2) => entry2.itemId === hint.itemId);
|
|
419
|
+
if (byItemId) return byItemId;
|
|
420
|
+
}
|
|
421
|
+
if (hint.outputIndex !== void 0) {
|
|
422
|
+
const open4 = [...state.functionCalls].reverse().find((entry2) => entry2.outputIndex === hint.outputIndex && !entry2.done && !(hint.callId && entry2.callId !== hint.callId));
|
|
423
|
+
if (open4) return open4;
|
|
424
|
+
}
|
|
425
|
+
if (hint.callId === void 0 && hint.itemId === void 0 && hint.outputIndex === void 0 && state.lastFunctionCall) {
|
|
426
|
+
return state.lastFunctionCall;
|
|
427
|
+
}
|
|
428
|
+
const entry = {
|
|
429
|
+
itemId: hint.itemId ?? nextId(state, "fc"),
|
|
430
|
+
callId: hint.callId ?? hint.itemId ?? nextId(state, "call"),
|
|
431
|
+
name: "",
|
|
432
|
+
args: "",
|
|
433
|
+
upstream: {},
|
|
434
|
+
outputIndex: hint.outputIndex ?? state.lastOutputIndex,
|
|
435
|
+
added: false,
|
|
436
|
+
deltaForwarded: false,
|
|
437
|
+
doneSeen: false,
|
|
438
|
+
done: false
|
|
439
|
+
};
|
|
440
|
+
state.functionCalls.push(entry);
|
|
441
|
+
return entry;
|
|
442
|
+
}
|
|
443
|
+
function absorbFunctionItem(entry, item, authoritative) {
|
|
444
|
+
entry.upstream = { ...entry.upstream, ...item };
|
|
445
|
+
const name = asString(item.name);
|
|
446
|
+
if (name) entry.name = name;
|
|
447
|
+
const callId = asString(item.call_id);
|
|
448
|
+
if (callId) entry.callId = callId;
|
|
449
|
+
if (authoritative && typeof item.arguments === "string") entry.upstreamArgs = item.arguments;
|
|
450
|
+
}
|
|
451
|
+
function resolveFunctionArgs(entry) {
|
|
452
|
+
if (entry.upstreamArgs) return entry.upstreamArgs;
|
|
453
|
+
if (entry.args) return entry.args;
|
|
454
|
+
return entry.upstreamArgs;
|
|
455
|
+
}
|
|
456
|
+
function functionItemPayload(entry, extra) {
|
|
457
|
+
return {
|
|
458
|
+
...entry.upstream,
|
|
459
|
+
type: "function_call",
|
|
460
|
+
id: entry.itemId,
|
|
461
|
+
call_id: entry.callId,
|
|
462
|
+
name: entry.name,
|
|
463
|
+
...extra
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
function functionAddedEvent(entry) {
|
|
467
|
+
entry.added = true;
|
|
468
|
+
return {
|
|
469
|
+
type: "response.output_item.added",
|
|
470
|
+
output_index: entry.outputIndex,
|
|
471
|
+
item: functionItemPayload(entry, { arguments: "" })
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
function functionDoneEvent(entry, args) {
|
|
475
|
+
entry.done = true;
|
|
476
|
+
return {
|
|
477
|
+
type: "response.output_item.done",
|
|
478
|
+
output_index: entry.outputIndex,
|
|
479
|
+
item: functionItemPayload(entry, { arguments: args, status: "completed" })
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
function completeFunctionCall(entry, args) {
|
|
483
|
+
if (entry.done) return [];
|
|
484
|
+
const events = [];
|
|
485
|
+
if (!entry.added) events.push(functionAddedEvent(entry));
|
|
486
|
+
if (!entry.deltaForwarded && args.length > 0) {
|
|
487
|
+
entry.deltaForwarded = true;
|
|
488
|
+
events.push({
|
|
489
|
+
type: "response.function_call_arguments.delta",
|
|
490
|
+
item_id: entry.itemId,
|
|
491
|
+
output_index: entry.outputIndex,
|
|
492
|
+
delta: args
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
events.push(functionDoneEvent(entry, args));
|
|
496
|
+
return events;
|
|
497
|
+
}
|
|
498
|
+
function messageText(item) {
|
|
499
|
+
if (typeof item.text === "string") return item.text;
|
|
500
|
+
if (!Array.isArray(item.content)) return "";
|
|
501
|
+
let out = "";
|
|
502
|
+
for (const part of item.content) {
|
|
503
|
+
if (isRecord(part) && typeof part.text === "string" && (part.type === "output_text" || part.type === "text")) {
|
|
504
|
+
out += part.text;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return out;
|
|
508
|
+
}
|
|
509
|
+
function synthesizeMessage(item, outputIndex, state) {
|
|
510
|
+
const text4 = messageText(item);
|
|
511
|
+
if (!text4) return [];
|
|
512
|
+
const id = asString(item.id) ?? nextId(state, "msg");
|
|
513
|
+
state.lastMessageItemId = id;
|
|
514
|
+
state.textDeltaForwarded = true;
|
|
515
|
+
state.messageAddedIds.add(id);
|
|
516
|
+
state.messageDoneIds.add(id);
|
|
517
|
+
return [
|
|
518
|
+
{ type: "response.output_item.added", output_index: outputIndex, item: { type: "message", id } },
|
|
519
|
+
{ type: "response.output_text.delta", item_id: id, delta: text4 },
|
|
520
|
+
{ type: "response.output_item.done", output_index: outputIndex, item: { type: "message", id } }
|
|
521
|
+
];
|
|
522
|
+
}
|
|
523
|
+
function synthesizeFunctionCall(item, outputIndex, state) {
|
|
524
|
+
const entry = resolveFunctionCall(state, {
|
|
525
|
+
itemId: asString(item.id),
|
|
526
|
+
callId: asString(item.call_id),
|
|
527
|
+
outputIndex
|
|
528
|
+
});
|
|
529
|
+
absorbFunctionItem(entry, item, true);
|
|
530
|
+
state.lastFunctionCall = entry;
|
|
531
|
+
state.lastOutputIndex = entry.outputIndex;
|
|
532
|
+
const args = resolveFunctionArgs(entry);
|
|
533
|
+
if (args === void 0) {
|
|
534
|
+
entry.doneSeen = true;
|
|
535
|
+
return [];
|
|
536
|
+
}
|
|
537
|
+
return completeFunctionCall(entry, args);
|
|
538
|
+
}
|
|
539
|
+
function recoverFromCompletedOutput(response, state) {
|
|
540
|
+
const recovered = [];
|
|
541
|
+
if (Array.isArray(response.output)) {
|
|
542
|
+
response.output.forEach((item, index) => {
|
|
543
|
+
if (!isRecord(item) || typeof item.type !== "string") return;
|
|
544
|
+
if (item.type === "message" && !state.textDeltaForwarded) {
|
|
545
|
+
recovered.push(...synthesizeMessage(item, index, state));
|
|
546
|
+
} else if (item.type === "function_call") {
|
|
547
|
+
recovered.push(...synthesizeFunctionCall(item, index, state));
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
for (const entry of state.functionCalls) {
|
|
552
|
+
if (entry.done || !entry.doneSeen) continue;
|
|
553
|
+
recovered.push(normalizeErrorEvent({
|
|
554
|
+
error: {
|
|
555
|
+
type: "invalid_response",
|
|
556
|
+
code: "incomplete_function_call",
|
|
557
|
+
message: `Provider ended the response without arguments for function call "${entry.callId}"${entry.name ? ` (${entry.name})` : ""}.`
|
|
558
|
+
}
|
|
559
|
+
}));
|
|
560
|
+
}
|
|
561
|
+
return recovered;
|
|
562
|
+
}
|
|
563
|
+
function normalizeResponsesLiteEvent(event, state) {
|
|
564
|
+
if (!isRecord(event) || typeof event.type !== "string") return [event];
|
|
565
|
+
if (event.type === "error") return [normalizeErrorEvent(event)];
|
|
566
|
+
if (event.type === "response.output_item.added" && isRecord(event.item)) {
|
|
567
|
+
const outputIndex = typeof event.output_index === "number" ? event.output_index : state.lastOutputIndex;
|
|
568
|
+
state.lastOutputIndex = outputIndex;
|
|
569
|
+
if (event.item.type === "message") {
|
|
570
|
+
const id = asString(event.item.id) ?? nextId(state, "msg");
|
|
571
|
+
state.lastMessageItemId = id;
|
|
572
|
+
state.messageAddedIds.add(id);
|
|
573
|
+
return [{ ...event, output_index: outputIndex, item: { ...event.item, id } }];
|
|
574
|
+
}
|
|
575
|
+
if (event.item.type === "function_call") {
|
|
576
|
+
const entry = resolveFunctionCall(state, {
|
|
577
|
+
itemId: asString(event.item.id),
|
|
578
|
+
callId: asString(event.item.call_id),
|
|
579
|
+
outputIndex
|
|
580
|
+
});
|
|
581
|
+
absorbFunctionItem(entry, event.item, false);
|
|
582
|
+
entry.outputIndex = outputIndex;
|
|
583
|
+
entry.added = true;
|
|
584
|
+
state.lastFunctionCall = entry;
|
|
585
|
+
return [{ ...event, output_index: outputIndex, item: functionItemPayload(entry, { arguments: "" }) }];
|
|
586
|
+
}
|
|
587
|
+
return [{ ...event, output_index: outputIndex }];
|
|
588
|
+
}
|
|
589
|
+
if (event.type === "response.output_item.done" && isRecord(event.item)) {
|
|
590
|
+
const outputIndex = typeof event.output_index === "number" ? event.output_index : state.lastOutputIndex;
|
|
591
|
+
if (event.item.type === "function_call") {
|
|
592
|
+
const entry = resolveFunctionCall(state, {
|
|
593
|
+
itemId: asString(event.item.id),
|
|
594
|
+
callId: asString(event.item.call_id),
|
|
595
|
+
outputIndex
|
|
596
|
+
});
|
|
597
|
+
absorbFunctionItem(entry, event.item, true);
|
|
598
|
+
entry.outputIndex = outputIndex;
|
|
599
|
+
entry.doneSeen = true;
|
|
600
|
+
state.lastFunctionCall = entry;
|
|
601
|
+
state.lastOutputIndex = outputIndex;
|
|
602
|
+
const args = resolveFunctionArgs(entry);
|
|
603
|
+
if (args === void 0 || !entry.name) return [];
|
|
604
|
+
if (entry.done) return [];
|
|
605
|
+
const events = [];
|
|
606
|
+
if (!entry.added) events.push(functionAddedEvent(entry));
|
|
607
|
+
events.push({ ...event, output_index: outputIndex, item: functionItemPayload(entry, { arguments: args, status: "completed" }) });
|
|
608
|
+
entry.done = true;
|
|
609
|
+
return events;
|
|
610
|
+
}
|
|
611
|
+
if (event.item.type === "message") {
|
|
612
|
+
const id = asString(event.item.id) ?? state.lastMessageItemId ?? nextId(state, "msg");
|
|
613
|
+
state.lastMessageItemId = id;
|
|
614
|
+
state.messageDoneIds.add(id);
|
|
615
|
+
return [{ ...event, output_index: outputIndex, item: { ...event.item, id } }];
|
|
616
|
+
}
|
|
617
|
+
return [{ ...event, output_index: outputIndex }];
|
|
618
|
+
}
|
|
619
|
+
if (event.type === "response.output_text.delta") {
|
|
620
|
+
const itemId = asString(event.item_id) ?? state.lastMessageItemId ?? nextId(state, "msg");
|
|
621
|
+
state.lastMessageItemId = itemId;
|
|
622
|
+
state.textDeltaForwarded = true;
|
|
623
|
+
const events = [];
|
|
624
|
+
if (!state.messageAddedIds.has(itemId)) {
|
|
625
|
+
events.push({
|
|
626
|
+
type: "response.output_item.added",
|
|
627
|
+
output_index: state.lastOutputIndex,
|
|
628
|
+
item: { type: "message", id: itemId }
|
|
629
|
+
});
|
|
630
|
+
state.messageAddedIds.add(itemId);
|
|
631
|
+
}
|
|
632
|
+
events.push({ ...event, item_id: itemId, delta: typeof event.delta === "string" ? event.delta : "" });
|
|
633
|
+
return events;
|
|
634
|
+
}
|
|
635
|
+
if (event.type === "response.function_call_arguments.delta") {
|
|
636
|
+
const entry = resolveFunctionCall(state, {
|
|
637
|
+
itemId: asString(event.item_id),
|
|
638
|
+
outputIndex: typeof event.output_index === "number" ? event.output_index : void 0
|
|
639
|
+
});
|
|
640
|
+
const delta = typeof event.delta === "string" ? event.delta : "";
|
|
641
|
+
entry.args += delta;
|
|
642
|
+
entry.deltaForwarded = true;
|
|
643
|
+
state.lastFunctionCall = entry;
|
|
644
|
+
state.lastOutputIndex = entry.outputIndex;
|
|
645
|
+
return [{ ...event, item_id: entry.itemId, output_index: entry.outputIndex, delta }];
|
|
646
|
+
}
|
|
647
|
+
if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
648
|
+
const response = isRecord(event.response) ? event.response : {};
|
|
649
|
+
const recovered = recoverFromCompletedOutput(response, state);
|
|
650
|
+
if (state.lastMessageItemId && state.textDeltaForwarded && !state.messageDoneIds.has(state.lastMessageItemId)) {
|
|
651
|
+
recovered.push({
|
|
652
|
+
type: "response.output_item.done",
|
|
653
|
+
output_index: state.lastOutputIndex,
|
|
654
|
+
item: { type: "message", id: state.lastMessageItemId }
|
|
655
|
+
});
|
|
656
|
+
state.messageDoneIds.add(state.lastMessageItemId);
|
|
657
|
+
}
|
|
658
|
+
return [...recovered, event];
|
|
659
|
+
}
|
|
660
|
+
return [event];
|
|
661
|
+
}
|
|
349
662
|
function toHeaderRecord(headers) {
|
|
350
663
|
const out = {};
|
|
351
664
|
if (!headers) return out;
|
|
@@ -403,10 +716,14 @@ function createResponsesWebSocketFetch(wsUrl, log7) {
|
|
|
403
716
|
if (hasResponsesLiteHeader(headers)) {
|
|
404
717
|
payload = applyResponsesLiteShape(payload);
|
|
405
718
|
}
|
|
719
|
+
debug(
|
|
720
|
+
`request type=response.create keys=${Object.keys(payload).sort().join(",")} toolCount=${Array.isArray(payload.tools) ? payload.tools.length : 0} store=${String(payload.store)} parallelToolCalls=${String(payload.parallel_tool_calls)} reasoningKeys=${recordKeys(payload.reasoning)}`
|
|
721
|
+
);
|
|
406
722
|
const outgoing = JSON.stringify({ type: "response.create", ...payload });
|
|
407
723
|
const encoder = new TextEncoder();
|
|
408
724
|
let socket;
|
|
409
725
|
let frameCount = 0;
|
|
726
|
+
const normalizeState = createResponsesLiteNormalizeState();
|
|
410
727
|
const stream = new ReadableStream({
|
|
411
728
|
start(controller) {
|
|
412
729
|
let closed = false;
|
|
@@ -424,13 +741,12 @@ function createResponsesWebSocketFetch(wsUrl, log7) {
|
|
|
424
741
|
};
|
|
425
742
|
const fail = (message) => {
|
|
426
743
|
if (closed) return;
|
|
427
|
-
debug(`fail
|
|
744
|
+
debug(`fail messageChars=${message.length}`);
|
|
428
745
|
try {
|
|
429
|
-
|
|
430
|
-
|
|
746
|
+
const [errorEvent] = normalizeResponsesLiteEvent({ type: "error", error: { message } }, normalizeState);
|
|
747
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}
|
|
431
748
|
|
|
432
|
-
`
|
|
433
|
-
));
|
|
749
|
+
`));
|
|
434
750
|
} catch {
|
|
435
751
|
}
|
|
436
752
|
close();
|
|
@@ -446,28 +762,31 @@ function createResponsesWebSocketFetch(wsUrl, log7) {
|
|
|
446
762
|
socket.on("message", (data) => {
|
|
447
763
|
const text4 = Array.isArray(data) ? Buffer.concat(data).toString("utf8") : data.toString("utf8");
|
|
448
764
|
frameCount += 1;
|
|
449
|
-
if (frameCount <= 3) debug(`frame#${frameCount}: ${text4.slice(0, 200)}`);
|
|
450
765
|
let event;
|
|
451
766
|
try {
|
|
452
767
|
event = JSON.parse(text4);
|
|
453
768
|
} catch {
|
|
769
|
+
debug(`frame#${frameCount} non-json chars=${text4.length}`);
|
|
454
770
|
controller.enqueue(encoder.encode(`data: ${text4.replace(/\r?\n/g, " ")}
|
|
455
771
|
|
|
456
772
|
`));
|
|
457
773
|
return;
|
|
458
774
|
}
|
|
459
|
-
|
|
775
|
+
if (frameCount <= 8) debug(`frame#${frameCount} ${summarizeResponsesLiteEvent(event)}`);
|
|
776
|
+
for (const next of normalizeResponsesLiteEvent(event, normalizeState)) {
|
|
777
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(next)}
|
|
460
778
|
|
|
461
779
|
`));
|
|
462
|
-
|
|
463
|
-
|
|
780
|
+
}
|
|
781
|
+
const type = isRecord(event) && typeof event.type === "string" ? event.type : void 0;
|
|
782
|
+
if (type && TERMINAL_EVENT_TYPES.has(type)) {
|
|
464
783
|
debug(`terminal event: ${type} (after ${frameCount} frames)`);
|
|
465
784
|
close();
|
|
466
785
|
}
|
|
467
786
|
});
|
|
468
787
|
socket.on("error", (err) => fail(err.message));
|
|
469
788
|
socket.on("close", (code, reason) => {
|
|
470
|
-
debug(`close code=${code} frames=${frameCount}${reason?.length ? `
|
|
789
|
+
debug(`close code=${code} frames=${frameCount}${reason?.length ? ` reasonChars=${reason.length}` : ""}`);
|
|
471
790
|
if (closed) return;
|
|
472
791
|
if (code === 1e3 || code === 1005) {
|
|
473
792
|
close();
|
|
@@ -823,10 +1142,11 @@ async function createLanguageModel(spec) {
|
|
|
823
1142
|
return model;
|
|
824
1143
|
}
|
|
825
1144
|
var ANTHROPIC_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
826
|
-
var OPENAI_EFFORT_LEVELS = ["low", "medium", "high"
|
|
1145
|
+
var OPENAI_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
827
1146
|
var GEMINI_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
828
1147
|
var MISTRAL_EFFORT_LEVELS = ["high", "off"];
|
|
829
|
-
var
|
|
1148
|
+
var XAI_CHAT_EFFORT_LEVELS = ["low", "high"];
|
|
1149
|
+
var XAI_RESPONSES_EFFORT_LEVELS = ["low", "medium", "high"];
|
|
830
1150
|
var OPENROUTER_EFFORT_LEVELS = ["none", "minimal", "low", "medium", "high", "xhigh"];
|
|
831
1151
|
var DEEPSEEK_EFFORT_LEVELS = ["high", "max", "off"];
|
|
832
1152
|
var GLM_52_EFFORT_LEVELS = ["high", "xhigh"];
|
|
@@ -997,7 +1317,50 @@ function mapCodexEffortToAnthropic(effort) {
|
|
|
997
1317
|
return void 0;
|
|
998
1318
|
}
|
|
999
1319
|
}
|
|
1000
|
-
|
|
1320
|
+
var OPENAI_MODEL_REASONING = {
|
|
1321
|
+
"gpt-5-pro": { levels: ["high"], defaultLevel: "high" },
|
|
1322
|
+
"gpt-5.1": { levels: ["none", "low", "medium", "high"], defaultLevel: "none" },
|
|
1323
|
+
"gpt-5.1-codex-max": { levels: ["low", "medium", "high", "xhigh"], defaultLevel: "medium" },
|
|
1324
|
+
"gpt-5.2": { levels: ["none", "low", "medium", "high", "xhigh"], defaultLevel: "none" },
|
|
1325
|
+
"gpt-5.2-codex": { levels: ["low", "medium", "high", "xhigh"], defaultLevel: "medium" },
|
|
1326
|
+
"gpt-5.2-pro": { levels: ["medium", "high", "xhigh"], defaultLevel: "medium" },
|
|
1327
|
+
"gpt-5.3-codex": { levels: ["low", "medium", "high", "xhigh"], defaultLevel: "medium" },
|
|
1328
|
+
"gpt-5.4": { levels: ["none", "low", "medium", "high", "xhigh"], defaultLevel: "none" },
|
|
1329
|
+
"gpt-5.4-mini": { levels: ["none", "low", "medium", "high", "xhigh"], defaultLevel: "none" },
|
|
1330
|
+
"gpt-5.4-nano": { levels: ["none", "low", "medium", "high", "xhigh"], defaultLevel: "none" },
|
|
1331
|
+
"gpt-5.4-pro": { levels: ["medium", "high", "xhigh"], defaultLevel: "medium" },
|
|
1332
|
+
"gpt-5.5": { levels: ["none", "low", "medium", "high", "xhigh"], defaultLevel: "medium" },
|
|
1333
|
+
"gpt-5.5-pro": { levels: ["medium", "high", "xhigh"], defaultLevel: "high" },
|
|
1334
|
+
"gpt-5.6": { levels: ["none", "low", "medium", "high", "xhigh", "max"], defaultLevel: "medium" },
|
|
1335
|
+
"gpt-5.6-luna": { levels: ["none", "low", "medium", "high", "xhigh", "max"], defaultLevel: "medium" },
|
|
1336
|
+
"gpt-5.6-sol": { levels: ["none", "low", "medium", "high", "xhigh", "max"], defaultLevel: "medium" },
|
|
1337
|
+
"gpt-5.6-terra": { levels: ["none", "low", "medium", "high", "xhigh", "max"], defaultLevel: "medium" }
|
|
1338
|
+
};
|
|
1339
|
+
var OPENAI_NON_REASONING_MODELS = /* @__PURE__ */ new Set([
|
|
1340
|
+
"chat-latest",
|
|
1341
|
+
"gpt-5-chat-latest",
|
|
1342
|
+
"gpt-5.1-chat-latest",
|
|
1343
|
+
"gpt-5.2-chat-latest",
|
|
1344
|
+
"gpt-5.3-chat-latest"
|
|
1345
|
+
]);
|
|
1346
|
+
var OPENAI_DATED_SNAPSHOT_SUFFIX = /-\d{4}-\d{2}-\d{2}$/;
|
|
1347
|
+
function canonicalOpenAiModelId(modelId, metadata) {
|
|
1348
|
+
return (metadata?.upstreamModelId ?? modelId ?? "").toLowerCase();
|
|
1349
|
+
}
|
|
1350
|
+
function openAiReasoningProfile(modelId, metadata) {
|
|
1351
|
+
const id = canonicalOpenAiModelId(modelId, metadata);
|
|
1352
|
+
if (!id) return void 0;
|
|
1353
|
+
return OPENAI_MODEL_REASONING[id] ?? OPENAI_MODEL_REASONING[id.replace(OPENAI_DATED_SNAPSHOT_SUFFIX, "")];
|
|
1354
|
+
}
|
|
1355
|
+
function openAiModelReasons(modelId, metadata) {
|
|
1356
|
+
const id = canonicalOpenAiModelId(modelId, metadata);
|
|
1357
|
+
if (OPENAI_NON_REASONING_MODELS.has(id.replace(OPENAI_DATED_SNAPSHOT_SUFFIX, ""))) return false;
|
|
1358
|
+
return !!openAiReasoningProfile(modelId, metadata) || modelPrefersResponsesApi(id) || !!metadata?.reasoning;
|
|
1359
|
+
}
|
|
1360
|
+
function mapCodexEffortToOpenAI(effort, allowed) {
|
|
1361
|
+
return allowed.includes(effort) ? effort : void 0;
|
|
1362
|
+
}
|
|
1363
|
+
function mapCodexEffortToOpenAICompatible(effort) {
|
|
1001
1364
|
if (effort === "xhigh") return "high";
|
|
1002
1365
|
const allowed = ["low", "medium", "high"];
|
|
1003
1366
|
return allowed.includes(effort) ? effort : void 0;
|
|
@@ -1013,16 +1376,12 @@ function mapCodexEffortToGlm52(effort) {
|
|
|
1013
1376
|
return void 0;
|
|
1014
1377
|
}
|
|
1015
1378
|
}
|
|
1016
|
-
function mapCodexEffortToXai(effort) {
|
|
1379
|
+
function mapCodexEffortToXai(effort, supportsMedium) {
|
|
1017
1380
|
switch (effort) {
|
|
1018
|
-
case "none":
|
|
1019
|
-
case "minimal":
|
|
1020
|
-
return void 0;
|
|
1021
|
-
// xAI SDK only accepts 'low'|'high'; omit param for 'none'
|
|
1022
1381
|
case "low":
|
|
1023
|
-
case "medium":
|
|
1024
1382
|
return "low";
|
|
1025
|
-
|
|
1383
|
+
case "medium":
|
|
1384
|
+
return supportsMedium ? "medium" : void 0;
|
|
1026
1385
|
case "high":
|
|
1027
1386
|
case "xhigh":
|
|
1028
1387
|
case "max":
|
|
@@ -1054,7 +1413,31 @@ function mapCodexEffortToGeminiBudget(effort) {
|
|
|
1054
1413
|
if (!level) return void 0;
|
|
1055
1414
|
return GEMINI_25_BUDGETS[level];
|
|
1056
1415
|
}
|
|
1416
|
+
function withMappableLevels(caps, npm, modelId, metadata) {
|
|
1417
|
+
if (caps.mode !== "controllable") return caps;
|
|
1418
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1419
|
+
const levels = caps.levels.filter((level) => {
|
|
1420
|
+
const mapped = effortProviderOptions(npm, level, modelId, metadata);
|
|
1421
|
+
if (mapped === void 0) return false;
|
|
1422
|
+
const wire = JSON.stringify(mapped);
|
|
1423
|
+
if (seen.has(wire)) return false;
|
|
1424
|
+
seen.add(wire);
|
|
1425
|
+
return true;
|
|
1426
|
+
});
|
|
1427
|
+
if (levels.length === caps.levels.length) return caps;
|
|
1428
|
+
if (levels.length === 0) {
|
|
1429
|
+
return { ...caps, levels: [], defaultLevel: "", mode: "internal-only" };
|
|
1430
|
+
}
|
|
1431
|
+
return {
|
|
1432
|
+
...caps,
|
|
1433
|
+
levels,
|
|
1434
|
+
defaultLevel: levels.includes(caps.defaultLevel) ? caps.defaultLevel : levels[levels.length - 1]
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1057
1437
|
function getReasoningCapabilities(npm, modelId, metadata) {
|
|
1438
|
+
return withMappableLevels(resolveRawReasoningCapabilities(npm, modelId, metadata), npm, modelId, metadata);
|
|
1439
|
+
}
|
|
1440
|
+
function resolveRawReasoningCapabilities(npm, modelId, metadata) {
|
|
1058
1441
|
const id = modelId.toLowerCase();
|
|
1059
1442
|
if (isOpenRouterRoute(npm, metadata)) {
|
|
1060
1443
|
return openRouterReasoningCapabilities(metadata);
|
|
@@ -1075,15 +1458,18 @@ function getReasoningCapabilities(npm, modelId, metadata) {
|
|
|
1075
1458
|
return EMPTY_REASONING;
|
|
1076
1459
|
}
|
|
1077
1460
|
if (npm === "@ai-sdk/openai" || npm === "@ai-sdk/azure") {
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1461
|
+
const canonicalId = canonicalOpenAiModelId(modelId, metadata);
|
|
1462
|
+
const profile = openAiReasoningProfile(modelId, metadata);
|
|
1463
|
+
const prefersResponses = modelPrefersResponsesApi(canonicalId);
|
|
1464
|
+
if (openAiModelReasons(modelId, metadata) && shouldUseOpenAiResponsesEndpoint(canonicalId)) {
|
|
1465
|
+
const levels = profile?.levels ?? [...OPENAI_EFFORT_LEVELS];
|
|
1080
1466
|
return {
|
|
1081
|
-
levels: [...
|
|
1082
|
-
defaultLevel: "medium",
|
|
1467
|
+
levels: [...levels],
|
|
1468
|
+
defaultLevel: profile?.defaultLevel ?? (levels.includes("medium") ? "medium" : levels[levels.length - 1]),
|
|
1083
1469
|
supportsSummaries: true,
|
|
1470
|
+
source: profile || prefersResponses ? "provider-rule" : "model-metadata",
|
|
1471
|
+
confidence: profile || prefersResponses ? "documented" : "inferred",
|
|
1084
1472
|
mode: "controllable",
|
|
1085
|
-
source: prefersResponses ? "provider-rule" : "model-metadata",
|
|
1086
|
-
confidence: prefersResponses ? "documented" : "inferred",
|
|
1087
1473
|
wireFormat: { kind: "openai-reasoning-effort" }
|
|
1088
1474
|
};
|
|
1089
1475
|
}
|
|
@@ -1119,7 +1505,7 @@ function getReasoningCapabilities(npm, modelId, metadata) {
|
|
|
1119
1505
|
}
|
|
1120
1506
|
if (npm === "@ai-sdk/xai") {
|
|
1121
1507
|
if (isXaiReasoningEffortModel(modelId)) {
|
|
1122
|
-
const levels = modelPrefersResponsesApi(modelId) ? [
|
|
1508
|
+
const levels = modelPrefersResponsesApi(modelId) ? [...XAI_RESPONSES_EFFORT_LEVELS] : [...XAI_CHAT_EFFORT_LEVELS];
|
|
1123
1509
|
return {
|
|
1124
1510
|
levels,
|
|
1125
1511
|
defaultLevel: xaiDefaultReasoningEffort(modelId),
|
|
@@ -1216,13 +1602,15 @@ function effortProviderOptions(npm, effort, modelId, metadata) {
|
|
|
1216
1602
|
return mapped ? { openrouter: { reasoning: { effort: mapped, exclude: false } } } : void 0;
|
|
1217
1603
|
}
|
|
1218
1604
|
if (npm === "@ai-sdk/openai" || npm === "@ai-sdk/azure") {
|
|
1219
|
-
if (!modelId || !
|
|
1220
|
-
|
|
1605
|
+
if (!modelId || !shouldUseOpenAiResponsesEndpoint(canonicalOpenAiModelId(modelId, metadata))) return void 0;
|
|
1606
|
+
if (!openAiModelReasons(modelId, metadata)) return void 0;
|
|
1607
|
+
const allowed = openAiReasoningProfile(modelId, metadata)?.levels ?? OPENAI_EFFORT_LEVELS;
|
|
1608
|
+
const reasoningEffort = mapCodexEffortToOpenAI(effort, allowed);
|
|
1221
1609
|
return reasoningEffort ? { openai: { reasoningEffort } } : void 0;
|
|
1222
1610
|
}
|
|
1223
1611
|
if (npm === "@ai-sdk/xai") {
|
|
1224
1612
|
if (!modelId || !isXaiReasoningEffortModel(modelId)) return void 0;
|
|
1225
|
-
const reasoningEffort = mapCodexEffortToXai(effort);
|
|
1613
|
+
const reasoningEffort = mapCodexEffortToXai(effort, modelPrefersResponsesApi(modelId));
|
|
1226
1614
|
return reasoningEffort ? { xai: { reasoningEffort } } : void 0;
|
|
1227
1615
|
}
|
|
1228
1616
|
if (npm === "@ai-sdk/anthropic" || npm === VERTEX_ANTHROPIC_NPM) {
|
|
@@ -1250,7 +1638,7 @@ function effortProviderOptions(npm, effort, modelId, metadata) {
|
|
|
1250
1638
|
return deepSeekEffortProviderOptions(effort);
|
|
1251
1639
|
}
|
|
1252
1640
|
if (isKimiReasoningModel(modelId)) {
|
|
1253
|
-
const reasoningEffort =
|
|
1641
|
+
const reasoningEffort = mapCodexEffortToOpenAICompatible(effort);
|
|
1254
1642
|
if (reasoningEffort) {
|
|
1255
1643
|
const key = metadata?.providerId ? toCamelCase(metadata.providerId) : "openaiCompatible";
|
|
1256
1644
|
return { [key]: { reasoningEffort } };
|
|
@@ -1266,7 +1654,7 @@ function effortProviderOptions(npm, effort, modelId, metadata) {
|
|
|
1266
1654
|
return void 0;
|
|
1267
1655
|
}
|
|
1268
1656
|
if (hasSupportedParameter(metadata, "reasoning_effort")) {
|
|
1269
|
-
const reasoningEffort =
|
|
1657
|
+
const reasoningEffort = mapCodexEffortToOpenAICompatible(effort);
|
|
1270
1658
|
return reasoningEffort ? { openai: { reasoningEffort }, openaiCompatible: { reasoningEffort } } : void 0;
|
|
1271
1659
|
}
|
|
1272
1660
|
if (hasSupportedParameter(metadata, "reasoning")) {
|
|
@@ -2348,7 +2736,7 @@ var ANTIGRAVITY_BASE_URLS = [
|
|
|
2348
2736
|
"https://cloudcode-pa.googleapis.com",
|
|
2349
2737
|
"https://daily-cloudcode-pa.sandbox.googleapis.com"
|
|
2350
2738
|
];
|
|
2351
|
-
var
|
|
2739
|
+
var ANTIGRAVITY_API_VERSION = "v1internal";
|
|
2352
2740
|
async function buildAntigravityAuthUrl(redirectUri) {
|
|
2353
2741
|
const { verifier, challenge } = await generatePkce();
|
|
2354
2742
|
const state = generateOAuthState();
|
|
@@ -2470,7 +2858,7 @@ function resolveAntigravityOnboardTierId(data) {
|
|
|
2470
2858
|
return pickTierId(sub.currentTier) ?? "legacy-tier";
|
|
2471
2859
|
}
|
|
2472
2860
|
async function loadCodeAssist(accessToken) {
|
|
2473
|
-
const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${
|
|
2861
|
+
const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${ANTIGRAVITY_API_VERSION}:loadCodeAssist`);
|
|
2474
2862
|
const res = await fetchFirstOk(endpoints, {
|
|
2475
2863
|
method: "POST",
|
|
2476
2864
|
headers: apiHeaders(accessToken),
|
|
@@ -2487,7 +2875,7 @@ async function loadCodeAssist(accessToken) {
|
|
|
2487
2875
|
};
|
|
2488
2876
|
}
|
|
2489
2877
|
async function onboardUser(accessToken, tierId, maxAttempts = 10) {
|
|
2490
|
-
const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${
|
|
2878
|
+
const endpoints = ANTIGRAVITY_BASE_URLS.map((b) => `${b}/${ANTIGRAVITY_API_VERSION}:onboardUser`);
|
|
2491
2879
|
let finalProjectId = "";
|
|
2492
2880
|
for (let i = 0; i < maxAttempts; i++) {
|
|
2493
2881
|
const res = await fetchFirstOk(endpoints, {
|
|
@@ -4742,7 +5130,7 @@ var SubagentRouteRegistry = class {
|
|
|
4742
5130
|
// src/subagent-model-routing.ts
|
|
4743
5131
|
var CLAUDE_MODEL_FAMILIES = ["sonnet", "opus", "haiku", "fable"];
|
|
4744
5132
|
var CLAUDE_MODEL_FAMILY_SET = new Set(CLAUDE_MODEL_FAMILIES);
|
|
4745
|
-
function
|
|
5133
|
+
function isRecord2(value) {
|
|
4746
5134
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4747
5135
|
}
|
|
4748
5136
|
function claudeModelFamily(modelId) {
|
|
@@ -4751,10 +5139,10 @@ function claudeModelFamily(modelId) {
|
|
|
4751
5139
|
return CLAUDE_MODEL_FAMILIES.find((family) => normalized.includes(family));
|
|
4752
5140
|
}
|
|
4753
5141
|
function isClaudeAgentTool(tool4) {
|
|
4754
|
-
if (tool4.name !== "Agent" || !
|
|
5142
|
+
if (tool4.name !== "Agent" || !isRecord2(tool4.input_schema)) return false;
|
|
4755
5143
|
const properties = tool4.input_schema.properties;
|
|
4756
|
-
if (!
|
|
4757
|
-
return ["description", "prompt", "subagent_type"].every((name) =>
|
|
5144
|
+
if (!isRecord2(properties)) return false;
|
|
5145
|
+
return ["description", "prompt", "subagent_type"].every((name) => isRecord2(properties[name]));
|
|
4758
5146
|
}
|
|
4759
5147
|
var UnavailableSubagentModelError = class extends Error {
|
|
4760
5148
|
constructor(selector, routing) {
|
|
@@ -4771,7 +5159,7 @@ var UnavailableSubagentModelError = class extends Error {
|
|
|
4771
5159
|
statusCode = 400;
|
|
4772
5160
|
};
|
|
4773
5161
|
function normalizeClaudeAgentInput(input, routing) {
|
|
4774
|
-
const source =
|
|
5162
|
+
const source = isRecord2(input) ? input : {};
|
|
4775
5163
|
const normalized = { ...source };
|
|
4776
5164
|
if (source.subagent_type === "fork") {
|
|
4777
5165
|
return { input: normalized, decision: { kind: "fork" } };
|
|
@@ -4843,9 +5231,9 @@ function prepareClaudeAgentInput(input, routing) {
|
|
|
4843
5231
|
return { input: clientInput, decision };
|
|
4844
5232
|
}
|
|
4845
5233
|
function augmentClaudeAgentTool(tool4, routing) {
|
|
4846
|
-
const inputSchema =
|
|
4847
|
-
const properties =
|
|
4848
|
-
const originalModel =
|
|
5234
|
+
const inputSchema = isRecord2(tool4.input_schema) ? tool4.input_schema : {};
|
|
5235
|
+
const properties = isRecord2(inputSchema.properties) ? inputSchema.properties : {};
|
|
5236
|
+
const originalModel = isRecord2(properties.model) ? properties.model : {};
|
|
4849
5237
|
const smallCatalog = routing.models.length <= MAX_MODEL_CATALOG;
|
|
4850
5238
|
const modelProperty = {
|
|
4851
5239
|
...originalModel,
|
|
@@ -6701,8 +7089,8 @@ function anthropicError(res, status, message) {
|
|
|
6701
7089
|
});
|
|
6702
7090
|
}
|
|
6703
7091
|
function aliasModelId(realId, providerId) {
|
|
6704
|
-
if (realId.startsWith("claude-")) return realId;
|
|
6705
7092
|
const sanitized = providerId.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7093
|
+
if (realId.startsWith("claude-") && !sanitized.startsWith("custom-")) return realId;
|
|
6706
7094
|
return `anthropic-${sanitized}__${realId}`;
|
|
6707
7095
|
}
|
|
6708
7096
|
function buildProxySubagentModelRouting(routes, parentRoute) {
|
|
@@ -9016,6 +9404,80 @@ function goRegistryStub() {
|
|
|
9016
9404
|
};
|
|
9017
9405
|
}
|
|
9018
9406
|
|
|
9407
|
+
// src/registry/fetch-anthropic-models.ts
|
|
9408
|
+
async function fetchAnthropicModels(baseUrl, apiKey, extraHeaders) {
|
|
9409
|
+
const root = baseUrl.replace(/\/v1\/?$/, "").replace(/\/$/, "");
|
|
9410
|
+
const modelsUrl2 = `${root}/v1/models`;
|
|
9411
|
+
const controller = new AbortController();
|
|
9412
|
+
const timer = setTimeout(() => controller.abort(), 1e4);
|
|
9413
|
+
try {
|
|
9414
|
+
const response = await fetch(modelsUrl2, {
|
|
9415
|
+
method: "GET",
|
|
9416
|
+
headers: {
|
|
9417
|
+
"x-api-key": apiKey,
|
|
9418
|
+
"anthropic-version": "2023-06-01",
|
|
9419
|
+
Accept: "application/json",
|
|
9420
|
+
...extraHeaders
|
|
9421
|
+
},
|
|
9422
|
+
redirect: "manual",
|
|
9423
|
+
signal: controller.signal
|
|
9424
|
+
});
|
|
9425
|
+
let logTrace;
|
|
9426
|
+
if (process.env.RELAY_AI_TRACE === "1") {
|
|
9427
|
+
logTrace = makeTraceLogger(getProviderDebugLogPath());
|
|
9428
|
+
}
|
|
9429
|
+
const rawBodyText = await response.text().catch(() => "");
|
|
9430
|
+
if (logTrace) {
|
|
9431
|
+
logTrace(`[fetchAnthropicModels] HTTP ${response.status} from ${modelsUrl2}`);
|
|
9432
|
+
logTrace(`[fetchAnthropicModels] Body: ${rawBodyText}`);
|
|
9433
|
+
}
|
|
9434
|
+
if (response.ok) {
|
|
9435
|
+
let json = {};
|
|
9436
|
+
try {
|
|
9437
|
+
if (rawBodyText.trim()) {
|
|
9438
|
+
json = JSON.parse(rawBodyText);
|
|
9439
|
+
}
|
|
9440
|
+
} catch {
|
|
9441
|
+
}
|
|
9442
|
+
const models = [];
|
|
9443
|
+
for (const row of json.data ?? []) {
|
|
9444
|
+
const id = row.id?.trim();
|
|
9445
|
+
if (!id) continue;
|
|
9446
|
+
models.push({
|
|
9447
|
+
id,
|
|
9448
|
+
name: row.name?.trim() || id,
|
|
9449
|
+
upstreamModelId: id,
|
|
9450
|
+
family: id.split("-")[0] ?? id,
|
|
9451
|
+
brand: deriveBrand(id),
|
|
9452
|
+
contextWindow: resolveContextWindow(id),
|
|
9453
|
+
modelFormat: "anthropic",
|
|
9454
|
+
npm: "@ai-sdk/anthropic",
|
|
9455
|
+
apiUrl: root
|
|
9456
|
+
});
|
|
9457
|
+
}
|
|
9458
|
+
if (models.length > 0) return { models, baseUrl: root };
|
|
9459
|
+
}
|
|
9460
|
+
if (response.status === 401 || response.status === 403) {
|
|
9461
|
+
return { models: [], baseUrl: root, error: "API key was rejected.", hint: "Check your Anthropic-compatible API key." };
|
|
9462
|
+
}
|
|
9463
|
+
return {
|
|
9464
|
+
models: [],
|
|
9465
|
+
baseUrl: root,
|
|
9466
|
+
error: `Could not list models (HTTP ${response.status}).`,
|
|
9467
|
+
hint: "Verify the base URL supports Anthropic-compatible /v1/models or try the OpenAI-compatible option instead."
|
|
9468
|
+
};
|
|
9469
|
+
} catch {
|
|
9470
|
+
return {
|
|
9471
|
+
models: [],
|
|
9472
|
+
baseUrl: root,
|
|
9473
|
+
error: "Could not reach the Anthropic-compatible server.",
|
|
9474
|
+
hint: "Check the base URL and that the server is running."
|
|
9475
|
+
};
|
|
9476
|
+
} finally {
|
|
9477
|
+
clearTimeout(timer);
|
|
9478
|
+
}
|
|
9479
|
+
}
|
|
9480
|
+
|
|
9019
9481
|
// src/registry/fetch-template-models.ts
|
|
9020
9482
|
var TEST_TIMEOUT_MS = 1e4;
|
|
9021
9483
|
function modelFormatForNpm(npm) {
|
|
@@ -9376,77 +9838,28 @@ function npmForKind(kind) {
|
|
|
9376
9838
|
function modelFormatForKind(kind) {
|
|
9377
9839
|
return kind === "anthropic" ? "anthropic" : "openai";
|
|
9378
9840
|
}
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
}
|
|
9400
|
-
const rawBodyText = await response.text().catch(() => "");
|
|
9401
|
-
if (logTrace) {
|
|
9402
|
-
logTrace(`[fetchAnthropicModels] HTTP ${response.status} from ${modelsUrl2}`);
|
|
9403
|
-
logTrace(`[fetchAnthropicModels] Body: ${rawBodyText}`);
|
|
9404
|
-
}
|
|
9405
|
-
if (response.ok) {
|
|
9406
|
-
let json = {};
|
|
9407
|
-
try {
|
|
9408
|
-
if (rawBodyText.trim()) {
|
|
9409
|
-
json = JSON.parse(rawBodyText);
|
|
9410
|
-
}
|
|
9411
|
-
} catch {
|
|
9412
|
-
}
|
|
9413
|
-
const models = [];
|
|
9414
|
-
for (const row of json.data ?? []) {
|
|
9415
|
-
const id = row.id?.trim();
|
|
9416
|
-
if (!id) continue;
|
|
9417
|
-
models.push({
|
|
9418
|
-
id,
|
|
9419
|
-
name: row.name?.trim() || id,
|
|
9420
|
-
upstreamModelId: id,
|
|
9421
|
-
family: id.split("-")[0] ?? id,
|
|
9422
|
-
brand: deriveBrand(id),
|
|
9423
|
-
contextWindow: resolveContextWindow(id),
|
|
9424
|
-
modelFormat: "anthropic",
|
|
9425
|
-
npm: "@ai-sdk/anthropic",
|
|
9426
|
-
apiUrl: root
|
|
9427
|
-
});
|
|
9428
|
-
}
|
|
9429
|
-
if (models.length > 0) return { models, baseUrl: root };
|
|
9430
|
-
}
|
|
9431
|
-
if (response.status === 401 || response.status === 403) {
|
|
9432
|
-
return { models: [], baseUrl: root, error: "API key was rejected.", hint: "Check your Anthropic-compatible API key." };
|
|
9433
|
-
}
|
|
9434
|
-
return {
|
|
9435
|
-
models: [],
|
|
9436
|
-
baseUrl: root,
|
|
9437
|
-
error: `Could not list models (HTTP ${response.status}).`,
|
|
9438
|
-
hint: "Verify the base URL supports Anthropic-compatible /v1/models or try the OpenAI-compatible option instead."
|
|
9439
|
-
};
|
|
9440
|
-
} catch {
|
|
9441
|
-
return {
|
|
9442
|
-
models: [],
|
|
9443
|
-
baseUrl: root,
|
|
9444
|
-
error: "Could not reach the Anthropic-compatible server.",
|
|
9445
|
-
hint: "Check the base URL and that the server is running."
|
|
9446
|
-
};
|
|
9447
|
-
} finally {
|
|
9448
|
-
clearTimeout(timer);
|
|
9841
|
+
function customEndpointKind(provider) {
|
|
9842
|
+
if (provider.templateId === "custom-anthropic") return "anthropic";
|
|
9843
|
+
if (provider.templateId === "custom-openai") return "openai";
|
|
9844
|
+
return null;
|
|
9845
|
+
}
|
|
9846
|
+
function sameHeaders(a, b) {
|
|
9847
|
+
const norm = (h) => JSON.stringify(Object.entries(h ?? {}).sort(([x], [y]) => x.localeCompare(y)));
|
|
9848
|
+
return norm(a) === norm(b);
|
|
9849
|
+
}
|
|
9850
|
+
function compareableUrl(url) {
|
|
9851
|
+
return url.replace(/\/v1\/?$/, "").replace(/\/$/, "");
|
|
9852
|
+
}
|
|
9853
|
+
async function findDuplicateCustomProvider(registry, normalizedUrl, apiKey, headers) {
|
|
9854
|
+
const target = compareableUrl(normalizedUrl);
|
|
9855
|
+
for (const existing of registry.providers) {
|
|
9856
|
+
if (!customEndpointKind(existing)) continue;
|
|
9857
|
+
if (compareableUrl(existing.api.url ?? "") !== target) continue;
|
|
9858
|
+
if (!sameHeaders(existing.api.headers, headers)) continue;
|
|
9859
|
+
const storedKey = await readStoredProviderCredential(existing.authRef);
|
|
9860
|
+
if ((storedKey ?? "") === apiKey) return existing.id;
|
|
9449
9861
|
}
|
|
9862
|
+
return null;
|
|
9450
9863
|
}
|
|
9451
9864
|
function uniqueProviderId(displayName, registry) {
|
|
9452
9865
|
let base = customProviderId(displayName);
|
|
@@ -9461,6 +9874,25 @@ function uniqueProviderId(displayName, registry) {
|
|
|
9461
9874
|
}
|
|
9462
9875
|
return `${base}-${Date.now()}`;
|
|
9463
9876
|
}
|
|
9877
|
+
async function fetchCustomEndpointModels(input) {
|
|
9878
|
+
if (input.kind === "anthropic") {
|
|
9879
|
+
return fetchAnthropicModels(input.normalizedBaseUrl, input.apiKey, input.headers);
|
|
9880
|
+
}
|
|
9881
|
+
return fetchTemplateModels(
|
|
9882
|
+
{
|
|
9883
|
+
id: input.providerId,
|
|
9884
|
+
name: input.displayName,
|
|
9885
|
+
authType: input.apiKey === "local" ? "none" : "api",
|
|
9886
|
+
npm: npmForKind(input.kind),
|
|
9887
|
+
defaultBaseUrl: input.normalizedBaseUrl,
|
|
9888
|
+
modelSource: "api-list",
|
|
9889
|
+
supported: true
|
|
9890
|
+
},
|
|
9891
|
+
input.apiKey,
|
|
9892
|
+
input.normalizedBaseUrl,
|
|
9893
|
+
input.headers
|
|
9894
|
+
);
|
|
9895
|
+
}
|
|
9464
9896
|
async function addCustomEndpointProvider(input) {
|
|
9465
9897
|
const urlCheck = await validateCustomEndpointUrl(input.baseUrl, {
|
|
9466
9898
|
allowInsecureLocal: input.allowInsecureLocal
|
|
@@ -9469,29 +9901,34 @@ async function addCustomEndpointProvider(input) {
|
|
|
9469
9901
|
return { added: false, error: urlCheck.error, hint: urlCheck.hint };
|
|
9470
9902
|
}
|
|
9471
9903
|
const registry = loadRegistry();
|
|
9472
|
-
const providerId = uniqueProviderId(input.displayName.trim(), registry);
|
|
9473
|
-
const npm = npmForKind(input.kind);
|
|
9474
9904
|
const apiKey = input.apiKey.trim() || "local";
|
|
9475
9905
|
const headers = input.headers && Object.keys(input.headers).length > 0 ? input.headers : void 0;
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
} else {
|
|
9480
|
-
fetched = await fetchTemplateModels(
|
|
9481
|
-
{
|
|
9482
|
-
id: providerId,
|
|
9483
|
-
name: input.displayName,
|
|
9484
|
-
authType: apiKey === "local" ? "none" : "api",
|
|
9485
|
-
npm,
|
|
9486
|
-
defaultBaseUrl: urlCheck.normalizedUrl,
|
|
9487
|
-
modelSource: "api-list",
|
|
9488
|
-
supported: true
|
|
9489
|
-
},
|
|
9490
|
-
apiKey,
|
|
9906
|
+
if (!input.confirmDuplicate) {
|
|
9907
|
+
const duplicateOf = await findDuplicateCustomProvider(
|
|
9908
|
+
registry,
|
|
9491
9909
|
urlCheck.normalizedUrl,
|
|
9910
|
+
apiKey,
|
|
9492
9911
|
headers
|
|
9493
9912
|
);
|
|
9913
|
+
if (duplicateOf) {
|
|
9914
|
+
return {
|
|
9915
|
+
added: false,
|
|
9916
|
+
duplicateOf,
|
|
9917
|
+
error: `A backend with the same URL, key and headers already exists (${duplicateOf}).`,
|
|
9918
|
+
hint: "Add it anyway to keep both, or cancel."
|
|
9919
|
+
};
|
|
9920
|
+
}
|
|
9494
9921
|
}
|
|
9922
|
+
const providerId = uniqueProviderId(input.displayName.trim(), registry);
|
|
9923
|
+
const npm = npmForKind(input.kind);
|
|
9924
|
+
const fetched = await fetchCustomEndpointModels({
|
|
9925
|
+
providerId,
|
|
9926
|
+
displayName: input.displayName,
|
|
9927
|
+
kind: input.kind,
|
|
9928
|
+
normalizedBaseUrl: urlCheck.normalizedUrl,
|
|
9929
|
+
apiKey,
|
|
9930
|
+
headers
|
|
9931
|
+
});
|
|
9495
9932
|
if (fetched.error || fetched.models.length === 0) {
|
|
9496
9933
|
return { added: false, error: fetched.error ?? "No models returned.", hint: fetched.hint };
|
|
9497
9934
|
}
|
|
@@ -9528,6 +9965,115 @@ async function addCustomEndpointProvider(input) {
|
|
|
9528
9965
|
saveRegistry(registry);
|
|
9529
9966
|
return { added: true, provider: entry, modelCount: fetched.models.length };
|
|
9530
9967
|
}
|
|
9968
|
+
async function updateCustomEndpointProvider(input) {
|
|
9969
|
+
const registry = loadRegistry();
|
|
9970
|
+
const provider = registry.providers.find((pr) => pr.id === input.providerId);
|
|
9971
|
+
if (!provider) {
|
|
9972
|
+
return { updated: false, error: `Provider not found: ${input.providerId}` };
|
|
9973
|
+
}
|
|
9974
|
+
const kind = customEndpointKind(provider);
|
|
9975
|
+
if (!kind) {
|
|
9976
|
+
return {
|
|
9977
|
+
updated: false,
|
|
9978
|
+
error: "Edit is only available for custom backends.",
|
|
9979
|
+
hint: "Template providers can only change their API key."
|
|
9980
|
+
};
|
|
9981
|
+
}
|
|
9982
|
+
const nextName = input.displayName?.trim();
|
|
9983
|
+
let nextBaseUrl = provider.api.url ?? "";
|
|
9984
|
+
let urlChanged = false;
|
|
9985
|
+
const requestedUrl = input.baseUrl?.trim();
|
|
9986
|
+
if (requestedUrl) {
|
|
9987
|
+
const urlCheck = await validateCustomEndpointUrl(requestedUrl, {
|
|
9988
|
+
allowInsecureLocal: input.allowInsecureLocal
|
|
9989
|
+
});
|
|
9990
|
+
if (!urlCheck.ok || !urlCheck.normalizedUrl) {
|
|
9991
|
+
return { updated: false, error: urlCheck.error, hint: urlCheck.hint };
|
|
9992
|
+
}
|
|
9993
|
+
urlChanged = urlCheck.normalizedUrl !== nextBaseUrl;
|
|
9994
|
+
nextBaseUrl = urlCheck.normalizedUrl;
|
|
9995
|
+
}
|
|
9996
|
+
const newKey = input.apiKey?.trim();
|
|
9997
|
+
const headersChanged = input.headers !== void 0 && !sameHeaders(input.headers, provider.api.headers);
|
|
9998
|
+
const nextHeaders = input.headers !== void 0 ? Object.keys(input.headers).length > 0 ? input.headers : void 0 : provider.api.headers;
|
|
9999
|
+
const nameChanged = Boolean(nextName) && nextName !== provider.name;
|
|
10000
|
+
const needsTest = urlChanged || Boolean(newKey) || headersChanged;
|
|
10001
|
+
if (!needsTest) {
|
|
10002
|
+
if (!nameChanged) return { updated: false, error: "Nothing to change." };
|
|
10003
|
+
provider.name = nextName;
|
|
10004
|
+
saveRegistry(registry);
|
|
10005
|
+
return {
|
|
10006
|
+
updated: true,
|
|
10007
|
+
provider,
|
|
10008
|
+
modelCount: provider.modelsCache?.models.length ?? 0
|
|
10009
|
+
};
|
|
10010
|
+
}
|
|
10011
|
+
const apiKey = newKey || await readStoredProviderCredential(provider.authRef) || "";
|
|
10012
|
+
if (!apiKey) {
|
|
10013
|
+
return {
|
|
10014
|
+
updated: false,
|
|
10015
|
+
error: "No stored API key was found for this backend.",
|
|
10016
|
+
hint: "Enter an API key to continue."
|
|
10017
|
+
};
|
|
10018
|
+
}
|
|
10019
|
+
const fetched = await fetchCustomEndpointModels({
|
|
10020
|
+
providerId: provider.id,
|
|
10021
|
+
displayName: nextName || provider.name,
|
|
10022
|
+
kind,
|
|
10023
|
+
normalizedBaseUrl: nextBaseUrl,
|
|
10024
|
+
apiKey,
|
|
10025
|
+
headers: nextHeaders
|
|
10026
|
+
});
|
|
10027
|
+
const testFailed = Boolean(fetched.error) || fetched.models.length === 0;
|
|
10028
|
+
if (testFailed && !input.saveAnyway) {
|
|
10029
|
+
return {
|
|
10030
|
+
updated: false,
|
|
10031
|
+
error: fetched.error ?? "No models returned.",
|
|
10032
|
+
hint: fetched.hint,
|
|
10033
|
+
canSaveAnyway: true
|
|
10034
|
+
};
|
|
10035
|
+
}
|
|
10036
|
+
if (newKey) {
|
|
10037
|
+
const saved = await saveProviderCredential(provider.authRef, newKey);
|
|
10038
|
+
if (!saved) {
|
|
10039
|
+
return {
|
|
10040
|
+
updated: false,
|
|
10041
|
+
error: "Could not save API key to credential store.",
|
|
10042
|
+
hint: "Grant Keychain access, or ensure RELAY_AI_HOME is writable (file fallback)."
|
|
10043
|
+
};
|
|
10044
|
+
}
|
|
10045
|
+
}
|
|
10046
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
10047
|
+
if (nameChanged) provider.name = nextName;
|
|
10048
|
+
const storedBaseUrl = kind === "anthropic" ? nextBaseUrl.replace(/\/v1\/?$/, "").replace(/\/$/, "") : nextBaseUrl;
|
|
10049
|
+
provider.api.url = testFailed ? storedBaseUrl : fetched.baseUrl || storedBaseUrl;
|
|
10050
|
+
if (nextHeaders) provider.api.headers = nextHeaders;
|
|
10051
|
+
else delete provider.api.headers;
|
|
10052
|
+
if (!testFailed) {
|
|
10053
|
+
provider.modelsCache = {
|
|
10054
|
+
fetchedAt: now,
|
|
10055
|
+
models: fetched.models.map((m) => ({
|
|
10056
|
+
...m,
|
|
10057
|
+
modelFormat: modelFormatForKind(kind),
|
|
10058
|
+
npm: npmForKind(kind),
|
|
10059
|
+
apiUrl: fetched.baseUrl || storedBaseUrl
|
|
10060
|
+
}))
|
|
10061
|
+
};
|
|
10062
|
+
provider.refreshedAt = now;
|
|
10063
|
+
} else if (provider.modelsCache) {
|
|
10064
|
+
provider.modelsCache = {
|
|
10065
|
+
...provider.modelsCache,
|
|
10066
|
+
models: provider.modelsCache.models.map((m) => ({ ...m, apiUrl: storedBaseUrl }))
|
|
10067
|
+
};
|
|
10068
|
+
}
|
|
10069
|
+
saveRegistry(registry);
|
|
10070
|
+
return {
|
|
10071
|
+
updated: true,
|
|
10072
|
+
provider,
|
|
10073
|
+
modelCount: provider.modelsCache?.models.length ?? 0,
|
|
10074
|
+
...testFailed ? { modelsStale: true } : {}
|
|
10075
|
+
};
|
|
10076
|
+
}
|
|
9531
10077
|
|
|
9532
10078
|
// src/registry/fetch-cline-pass-models.ts
|
|
9533
10079
|
var REQUEST_TIMEOUT_MS = 1e4;
|
|
@@ -10055,7 +10601,7 @@ async function refreshApiListProvider(provider, apiKey) {
|
|
|
10055
10601
|
const templateDefault = catalogTemplate?.defaultBaseUrl?.trim();
|
|
10056
10602
|
if (configuredUrl && configuredUrl !== templateDefault) {
|
|
10057
10603
|
const urlCheck = await validateCustomEndpointUrl(baseUrl, {
|
|
10058
|
-
allowInsecureLocal: catalogTemplate?.apiKeyOptional === true
|
|
10604
|
+
allowInsecureLocal: catalogTemplate?.apiKeyOptional === true || customEndpointKind(provider) !== null
|
|
10059
10605
|
});
|
|
10060
10606
|
if (!urlCheck.ok || !urlCheck.normalizedUrl) {
|
|
10061
10607
|
return { models: [], error: `${urlCheck.error ?? "Invalid API base URL."} ${urlCheck.hint ?? ""}`.trim() };
|
|
@@ -10063,8 +10609,9 @@ async function refreshApiListProvider(provider, apiKey) {
|
|
|
10063
10609
|
safeBaseUrl = urlCheck.normalizedUrl;
|
|
10064
10610
|
}
|
|
10065
10611
|
const template = catalogTemplate ?? syntheticTemplate(provider, safeBaseUrl);
|
|
10612
|
+
const extraHeaders = provider.api.headers && Object.keys(provider.api.headers).length > 0 ? provider.api.headers : void 0;
|
|
10066
10613
|
if (npm === "@ai-sdk/anthropic") {
|
|
10067
|
-
const fetched2 = await fetchAnthropicModels(safeBaseUrl, apiKey);
|
|
10614
|
+
const fetched2 = await fetchAnthropicModels(safeBaseUrl, apiKey, extraHeaders);
|
|
10068
10615
|
if (fetched2.error || fetched2.models.length === 0) {
|
|
10069
10616
|
return { models: [], error: fetched2.error ?? "No models returned.", baseUrl: fetched2.baseUrl };
|
|
10070
10617
|
}
|
|
@@ -10073,7 +10620,7 @@ async function refreshApiListProvider(provider, apiKey) {
|
|
|
10073
10620
|
baseUrl: fetched2.baseUrl
|
|
10074
10621
|
};
|
|
10075
10622
|
}
|
|
10076
|
-
const fetched = await fetchTemplateModels(template, apiKey, safeBaseUrl);
|
|
10623
|
+
const fetched = await fetchTemplateModels(template, apiKey, safeBaseUrl, extraHeaders);
|
|
10077
10624
|
if (fetched.error || fetched.models.length === 0) {
|
|
10078
10625
|
return { models: [], error: fetched.error ?? "No models returned." };
|
|
10079
10626
|
}
|
|
@@ -12006,7 +12553,7 @@ function removeFavorite(list, fav) {
|
|
|
12006
12553
|
// src/favorite-provider-display.ts
|
|
12007
12554
|
var OAUTH_FAVORITE_NAMES = {
|
|
12008
12555
|
"claude-code": "Claude Code OAuth (Anthropic subscription)",
|
|
12009
|
-
antigravity: "
|
|
12556
|
+
antigravity: "Cloud Code Assist OAuth (Google)",
|
|
12010
12557
|
"openai-oauth": "OpenAI OAuth (ChatGPT)",
|
|
12011
12558
|
"xai-oauth": "xAI OAuth (SuperGrok)"
|
|
12012
12559
|
};
|
|
@@ -12209,7 +12756,7 @@ var PROVIDER_DISPLAY = {
|
|
|
12209
12756
|
"openai-oauth": OPENAI_DISPLAY,
|
|
12210
12757
|
"github-copilot": "GitHub Copilot",
|
|
12211
12758
|
"claude-code": "Claude Code (Anthropic subscription)",
|
|
12212
|
-
antigravity: "
|
|
12759
|
+
antigravity: "Cloud Code Assist OAuth (Google)",
|
|
12213
12760
|
"cline-pass": "ClinePass"
|
|
12214
12761
|
};
|
|
12215
12762
|
function openBrowser(url) {
|
|
@@ -12312,7 +12859,7 @@ async function runNativeBrowserOAuth(providerId) {
|
|
|
12312
12859
|
p5.log.info(`Opening: ${pc6.cyan(url)}`);
|
|
12313
12860
|
spinner3.start("Waiting for authorization\u2026");
|
|
12314
12861
|
});
|
|
12315
|
-
spinner3.stop(pc6.green("Signed in to
|
|
12862
|
+
spinner3.stop(pc6.green("Signed in to Cloud Code Assist"));
|
|
12316
12863
|
const providerData = {};
|
|
12317
12864
|
if (projectId) providerData.projectId = projectId;
|
|
12318
12865
|
if (tierId) providerData.tier = tierId;
|
|
@@ -13186,14 +13733,13 @@ export {
|
|
|
13186
13733
|
makeTraceLogger,
|
|
13187
13734
|
writeSecureLogLine,
|
|
13188
13735
|
printTraceLog,
|
|
13189
|
-
fetchTemplateModels,
|
|
13190
|
-
validateCustomEndpointUrl,
|
|
13191
13736
|
fetchAnthropicModels,
|
|
13192
|
-
|
|
13737
|
+
fetchTemplateModels,
|
|
13193
13738
|
resolveProviderTemplate,
|
|
13194
13739
|
effectiveProviderBaseUrl,
|
|
13195
13740
|
syntheticTemplate,
|
|
13196
13741
|
resolveModelSource,
|
|
13742
|
+
validateCustomEndpointUrl,
|
|
13197
13743
|
readBody,
|
|
13198
13744
|
extractApiKey,
|
|
13199
13745
|
sendJson,
|
|
@@ -13248,6 +13794,9 @@ export {
|
|
|
13248
13794
|
routableModelsForTarget,
|
|
13249
13795
|
providersForTarget,
|
|
13250
13796
|
providersForCodexSubagents,
|
|
13797
|
+
customEndpointKind,
|
|
13798
|
+
addCustomEndpointProvider,
|
|
13799
|
+
updateCustomEndpointProvider,
|
|
13251
13800
|
refreshProviderModels,
|
|
13252
13801
|
refreshAllProviderModels,
|
|
13253
13802
|
removeProviderFromRegistry,
|
|
@@ -13292,4 +13841,4 @@ export {
|
|
|
13292
13841
|
supportsClaudeTransparentMode,
|
|
13293
13842
|
buildHttpProxyRoutes
|
|
13294
13843
|
};
|
|
13295
|
-
//# sourceMappingURL=chunk-
|
|
13844
|
+
//# sourceMappingURL=chunk-PVGAE7HA.js.map
|