anygate 0.5.7 → 0.5.8
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-BCPX3QLK.js → chunk-APLGXZWQ.js} +262 -40
- package/dist/chunk-APLGXZWQ.js.map +1 -0
- package/dist/cli.js +88 -33
- package/dist/cli.js.map +1 -1
- package/dist/{command-E7O6ZQWJ.js → command-O6JD4567.js} +292 -2
- package/dist/command-O6JD4567.js.map +1 -0
- package/dist/ui/dist/assets/index-3Jrdu_6p.js +6 -0
- package/dist/ui/dist/assets/{index-C4xd3r4v.css → index-DtRr0Wrk.css} +1 -1
- package/dist/ui/dist/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-BCPX3QLK.js.map +0 -1
- package/dist/command-E7O6ZQWJ.js.map +0 -1
- package/dist/ui/dist/assets/index-3sdSv_1I.js +0 -5
|
@@ -10,7 +10,7 @@ import { join } from "path";
|
|
|
10
10
|
// package.json
|
|
11
11
|
var package_default = {
|
|
12
12
|
name: "anygate",
|
|
13
|
-
version: "0.5.
|
|
13
|
+
version: "0.5.8",
|
|
14
14
|
publishConfig: {
|
|
15
15
|
access: "public"
|
|
16
16
|
},
|
|
@@ -5081,13 +5081,13 @@ async function collectCloudCodeToAnthropic(upstreamRes, model, log7) {
|
|
|
5081
5081
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5082
5082
|
|
|
5083
5083
|
// src/gateway/sdk-adapter.ts
|
|
5084
|
-
import { streamText, generateText, tool as
|
|
5084
|
+
import { streamText, generateText, tool as tool3, jsonSchema as jsonSchema3, stepCountIs } from "ai";
|
|
5085
5085
|
|
|
5086
5086
|
// src/agents/shared/tool-search.ts
|
|
5087
5087
|
var TOOL_SEARCH_TYPE_PREFIX = "tool_search_tool";
|
|
5088
|
-
function isToolSearchTool(
|
|
5089
|
-
if (typeof
|
|
5090
|
-
const name =
|
|
5088
|
+
function isToolSearchTool(tool5) {
|
|
5089
|
+
if (typeof tool5.type === "string" && tool5.type.startsWith(TOOL_SEARCH_TYPE_PREFIX)) return true;
|
|
5090
|
+
const name = tool5.name ?? "";
|
|
5091
5091
|
return name.includes("tool_search") || name === "ToolSearch";
|
|
5092
5092
|
}
|
|
5093
5093
|
function extractReferencedToolNames(messages) {
|
|
@@ -5126,20 +5126,207 @@ function resolveUpstreamTools(tools, messages) {
|
|
|
5126
5126
|
if (!tools?.length) return [];
|
|
5127
5127
|
const referenced = extractReferencedToolNames(messages);
|
|
5128
5128
|
const upstream = [];
|
|
5129
|
-
for (const
|
|
5130
|
-
if (isToolSearchTool(
|
|
5131
|
-
upstream.push(
|
|
5129
|
+
for (const tool5 of tools) {
|
|
5130
|
+
if (isToolSearchTool(tool5)) {
|
|
5131
|
+
upstream.push(tool5);
|
|
5132
5132
|
continue;
|
|
5133
5133
|
}
|
|
5134
|
-
if (
|
|
5135
|
-
if (referenced.has(
|
|
5134
|
+
if (tool5.defer_loading === true) {
|
|
5135
|
+
if (referenced.has(tool5.name)) upstream.push(tool5);
|
|
5136
5136
|
continue;
|
|
5137
5137
|
}
|
|
5138
|
-
upstream.push(
|
|
5138
|
+
upstream.push(tool5);
|
|
5139
5139
|
}
|
|
5140
5140
|
return upstream;
|
|
5141
5141
|
}
|
|
5142
5142
|
|
|
5143
|
+
// src/gateway/web-search/tool.ts
|
|
5144
|
+
import { tool as tool2, jsonSchema as jsonSchema2 } from "ai";
|
|
5145
|
+
|
|
5146
|
+
// src/gateway/web-search/constants.ts
|
|
5147
|
+
var WEB_SEARCH_ENV = {
|
|
5148
|
+
enabled: "ANYGATE_WEB_SEARCH",
|
|
5149
|
+
provider: "ANYGATE_WEB_SEARCH_PROVIDER",
|
|
5150
|
+
searxngUrl: "ANYGATE_SEARXNG_URL",
|
|
5151
|
+
apiKey: "ANYGATE_SEARCH_API_KEY",
|
|
5152
|
+
maxResults: "ANYGATE_WEB_SEARCH_MAX_RESULTS"
|
|
5153
|
+
};
|
|
5154
|
+
var DEFAULT_MAX_RESULTS = 5;
|
|
5155
|
+
var MAX_WEB_SEARCH_STEPS = 5;
|
|
5156
|
+
|
|
5157
|
+
// src/gateway/web-search/duckduckgo.ts
|
|
5158
|
+
var DDG_HTML_URL = "https://html.duckduckgo.com/html/";
|
|
5159
|
+
function decodeDdgUrl(href) {
|
|
5160
|
+
try {
|
|
5161
|
+
const url = new URL(href, DDG_HTML_URL);
|
|
5162
|
+
const uddg = url.searchParams.get("uddg");
|
|
5163
|
+
if (uddg) return decodeURIComponent(uddg);
|
|
5164
|
+
return url.href;
|
|
5165
|
+
} catch {
|
|
5166
|
+
return href;
|
|
5167
|
+
}
|
|
5168
|
+
}
|
|
5169
|
+
function stripHtml(s) {
|
|
5170
|
+
return s.replace(/<[^>]+>/g, "").replace(/&/g, "&").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/\s+/g, " ").trim();
|
|
5171
|
+
}
|
|
5172
|
+
function parseDdgHtml(html, max) {
|
|
5173
|
+
const results = [];
|
|
5174
|
+
const linkRe = /<a[^>]*class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
5175
|
+
let m;
|
|
5176
|
+
while ((m = linkRe.exec(html)) !== null && results.length < max) {
|
|
5177
|
+
const href = decodeDdgUrl(m[1]);
|
|
5178
|
+
const title = stripHtml(m[2]);
|
|
5179
|
+
const after = html.slice(m.index + m[0].length);
|
|
5180
|
+
const snipMatch = after.match(/class="result__snippet"[^>]*>([\s\S]*?)<\/a>/i);
|
|
5181
|
+
const snippet = snipMatch ? stripHtml(snipMatch[1]) : "";
|
|
5182
|
+
if (title && href) results.push({ title, url: href, snippet });
|
|
5183
|
+
}
|
|
5184
|
+
return results;
|
|
5185
|
+
}
|
|
5186
|
+
async function searchDuckDuckGo(query, opts) {
|
|
5187
|
+
const max = opts?.maxResults ?? 5;
|
|
5188
|
+
const body = new URLSearchParams({ q: query }).toString();
|
|
5189
|
+
const res = await fetch(DDG_HTML_URL, {
|
|
5190
|
+
method: "POST",
|
|
5191
|
+
headers: {
|
|
5192
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
5193
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"
|
|
5194
|
+
},
|
|
5195
|
+
body
|
|
5196
|
+
});
|
|
5197
|
+
if (!res.ok) throw new Error(`DuckDuckGo search failed: ${res.status}`);
|
|
5198
|
+
const html = await res.text();
|
|
5199
|
+
return parseDdgHtml(html, max);
|
|
5200
|
+
}
|
|
5201
|
+
|
|
5202
|
+
// src/gateway/web-search/searxng.ts
|
|
5203
|
+
async function searchSearXNG(query, baseUrl, opts) {
|
|
5204
|
+
const max = opts?.maxResults ?? 5;
|
|
5205
|
+
const url = new URL("/search", baseUrl.replace(/\/+$/, ""));
|
|
5206
|
+
url.searchParams.set("format", "json");
|
|
5207
|
+
url.searchParams.set("q", query);
|
|
5208
|
+
const res = await fetch(url, { headers: { Accept: "application/json" } });
|
|
5209
|
+
if (!res.ok) throw new Error(`SearXNG search failed: ${res.status}`);
|
|
5210
|
+
const data = await res.json();
|
|
5211
|
+
return (Array.isArray(data) ? data : []).filter((r) => r.url && r.title).slice(0, max).map((r) => ({ title: r.title ?? "", url: r.url ?? "", snippet: r.content ?? "" }));
|
|
5212
|
+
}
|
|
5213
|
+
|
|
5214
|
+
// src/gateway/web-search/brave.ts
|
|
5215
|
+
async function searchBrave(query, apiKey, opts) {
|
|
5216
|
+
const max = opts?.maxResults ?? 5;
|
|
5217
|
+
const url = new URL("https://api.search.brave.com/res/v1/web/search");
|
|
5218
|
+
url.searchParams.set("q", query);
|
|
5219
|
+
url.searchParams.set("count", String(max));
|
|
5220
|
+
if (opts?.allowedDomains?.length) url.searchParams.set("site", opts.allowedDomains.join(","));
|
|
5221
|
+
const res = await fetch(url, {
|
|
5222
|
+
headers: { Accept: "application/json", "X-Subscription-Token": apiKey }
|
|
5223
|
+
});
|
|
5224
|
+
if (!res.ok) throw new Error(`Brave search failed: ${res.status}`);
|
|
5225
|
+
const data = await res.json();
|
|
5226
|
+
return (data.web?.results ?? []).filter((r) => r.url && r.title).slice(0, max).map((r) => ({ title: r.title ?? "", url: r.url ?? "", snippet: r.description ?? "" }));
|
|
5227
|
+
}
|
|
5228
|
+
|
|
5229
|
+
// src/gateway/web-search/tavily.ts
|
|
5230
|
+
async function searchTavily(query, apiKey, opts) {
|
|
5231
|
+
const max = opts?.maxResults ?? 5;
|
|
5232
|
+
const res = await fetch("https://api.tavily.com/search", {
|
|
5233
|
+
method: "POST",
|
|
5234
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
5235
|
+
body: JSON.stringify({
|
|
5236
|
+
query,
|
|
5237
|
+
max_results: max,
|
|
5238
|
+
include_domains: opts?.allowedDomains,
|
|
5239
|
+
exclude_domains: opts?.blockedDomains
|
|
5240
|
+
})
|
|
5241
|
+
});
|
|
5242
|
+
if (!res.ok) throw new Error(`Tavily search failed: ${res.status}`);
|
|
5243
|
+
const data = await res.json();
|
|
5244
|
+
return (data.results ?? []).filter((r) => r.url && r.title).slice(0, max).map((r) => ({ title: r.title ?? "", url: r.url ?? "", snippet: r.content ?? "" }));
|
|
5245
|
+
}
|
|
5246
|
+
|
|
5247
|
+
// src/gateway/web-search/index.ts
|
|
5248
|
+
var PROVIDERS = ["duckduckgo", "searxng", "brave", "tavily"];
|
|
5249
|
+
function resolveWebSearchConfig(env = process.env) {
|
|
5250
|
+
const enabled = (env[WEB_SEARCH_ENV.enabled] ?? "on").toLowerCase() !== "off";
|
|
5251
|
+
const providerRaw = (env[WEB_SEARCH_ENV.provider] ?? "duckduckgo").toLowerCase();
|
|
5252
|
+
const provider = PROVIDERS.includes(providerRaw) ? providerRaw : "duckduckgo";
|
|
5253
|
+
const maxRaw = parseInt(env[WEB_SEARCH_ENV.maxResults] ?? "", 10);
|
|
5254
|
+
const maxResults = Number.isFinite(maxRaw) && maxRaw > 0 ? maxRaw : DEFAULT_MAX_RESULTS;
|
|
5255
|
+
return {
|
|
5256
|
+
enabled,
|
|
5257
|
+
provider,
|
|
5258
|
+
searxngUrl: env[WEB_SEARCH_ENV.searxngUrl] || void 0,
|
|
5259
|
+
apiKey: env[WEB_SEARCH_ENV.apiKey] || void 0,
|
|
5260
|
+
maxResults
|
|
5261
|
+
};
|
|
5262
|
+
}
|
|
5263
|
+
async function searchWeb(query, opts, config) {
|
|
5264
|
+
const cfg = config ?? resolveWebSearchConfig();
|
|
5265
|
+
if (!cfg.enabled) return [];
|
|
5266
|
+
const searchOpts = { maxResults: cfg.maxResults, ...opts };
|
|
5267
|
+
switch (cfg.provider) {
|
|
5268
|
+
case "searxng":
|
|
5269
|
+
if (!cfg.searxngUrl) throw new Error("ANYGATE_SEARXNG_URL is required for the searxng web search provider");
|
|
5270
|
+
return searchSearXNG(query, cfg.searxngUrl, searchOpts);
|
|
5271
|
+
case "brave":
|
|
5272
|
+
if (!cfg.apiKey) throw new Error("ANYGATE_SEARCH_API_KEY is required for the brave web search provider");
|
|
5273
|
+
return searchBrave(query, cfg.apiKey, searchOpts);
|
|
5274
|
+
case "tavily":
|
|
5275
|
+
if (!cfg.apiKey) throw new Error("ANYGATE_SEARCH_API_KEY is required for the tavily web search provider");
|
|
5276
|
+
return searchTavily(query, cfg.apiKey, searchOpts);
|
|
5277
|
+
case "duckduckgo":
|
|
5278
|
+
default:
|
|
5279
|
+
return searchDuckDuckGo(query, searchOpts);
|
|
5280
|
+
}
|
|
5281
|
+
}
|
|
5282
|
+
function formatSearchResults(results) {
|
|
5283
|
+
if (!results.length) return "No web search results were found.";
|
|
5284
|
+
const lines = results.map((r, i) => `${i + 1}. ${r.title}
|
|
5285
|
+
URL: ${r.url}
|
|
5286
|
+
${r.snippet}`);
|
|
5287
|
+
return `Web search results:
|
|
5288
|
+
${lines.join("\n")}`;
|
|
5289
|
+
}
|
|
5290
|
+
|
|
5291
|
+
// src/gateway/web-search/tool.ts
|
|
5292
|
+
var WEB_SEARCH_INPUT_SCHEMA = {
|
|
5293
|
+
type: "object",
|
|
5294
|
+
properties: {
|
|
5295
|
+
query: { type: "string", description: "The search query to use." },
|
|
5296
|
+
allowed_domains: {
|
|
5297
|
+
type: "array",
|
|
5298
|
+
items: { type: "string" },
|
|
5299
|
+
description: "Only include search results from these domains."
|
|
5300
|
+
},
|
|
5301
|
+
blocked_domains: {
|
|
5302
|
+
type: "array",
|
|
5303
|
+
items: { type: "string" },
|
|
5304
|
+
description: "Never include search results from these domains."
|
|
5305
|
+
},
|
|
5306
|
+
max_uses: { type: "integer", description: "Maximum number of searches the model may perform." }
|
|
5307
|
+
},
|
|
5308
|
+
required: ["query"]
|
|
5309
|
+
};
|
|
5310
|
+
function isWebSearchTool(t) {
|
|
5311
|
+
if (typeof t.name === "string" && /web[_-]?search/i.test(t.name)) return true;
|
|
5312
|
+
if (typeof t.type === "string" && t.type.startsWith("web_search")) return true;
|
|
5313
|
+
return false;
|
|
5314
|
+
}
|
|
5315
|
+
function makeWebSearchTool(name) {
|
|
5316
|
+
return tool2({
|
|
5317
|
+
description: "Search the web for current information. Use this whenever the user asks about recent events, current facts, news, or anything that may need up-to-date information beyond your training data.",
|
|
5318
|
+
inputSchema: jsonSchema2(WEB_SEARCH_INPUT_SCHEMA),
|
|
5319
|
+
execute: async (input) => {
|
|
5320
|
+
const params = input;
|
|
5321
|
+
const results = await searchWeb(params.query, {
|
|
5322
|
+
allowedDomains: params.allowed_domains,
|
|
5323
|
+
blockedDomains: params.blocked_domains
|
|
5324
|
+
});
|
|
5325
|
+
return formatSearchResults(results);
|
|
5326
|
+
}
|
|
5327
|
+
});
|
|
5328
|
+
}
|
|
5329
|
+
|
|
5143
5330
|
// src/gateway/context-fit.ts
|
|
5144
5331
|
var CHARS_PER_TOKEN = 4;
|
|
5145
5332
|
var RESERVE_TOKENS = 256;
|
|
@@ -5352,8 +5539,13 @@ function translateTools3(anthropicTools) {
|
|
|
5352
5539
|
if (!anthropicTools?.length) return void 0;
|
|
5353
5540
|
const tools = {};
|
|
5354
5541
|
for (const t of anthropicTools) {
|
|
5355
|
-
if (!t.name
|
|
5356
|
-
|
|
5542
|
+
if (!t.name) continue;
|
|
5543
|
+
if (isWebSearchTool(t)) {
|
|
5544
|
+
tools[t.name] = makeWebSearchTool(t.name);
|
|
5545
|
+
continue;
|
|
5546
|
+
}
|
|
5547
|
+
if (!t.input_schema) continue;
|
|
5548
|
+
tools[t.name] = tool3({ description: t.description ?? "", inputSchema: jsonSchema3(t.input_schema) });
|
|
5357
5549
|
}
|
|
5358
5550
|
return Object.keys(tools).length ? tools : void 0;
|
|
5359
5551
|
}
|
|
@@ -5398,6 +5590,7 @@ function translateRequest2(body, npm, options) {
|
|
|
5398
5590
|
if (options?.maxTools !== void 0 && upstreamTools.length > options.maxTools) {
|
|
5399
5591
|
upstreamTools = upstreamTools.slice(0, options.maxTools);
|
|
5400
5592
|
}
|
|
5593
|
+
const webSearchTool = upstreamTools.find((t) => isWebSearchTool(t));
|
|
5401
5594
|
const effort = anthropicEffortFromRequest(body) ?? options?.defaultEffort;
|
|
5402
5595
|
let providerOptions = deepMergeProviderOptions(
|
|
5403
5596
|
thinkingProviderOptions(npm),
|
|
@@ -5415,16 +5608,18 @@ function translateRequest2(body, npm, options) {
|
|
|
5415
5608
|
toolChoice: translateToolChoice(body.tool_choice),
|
|
5416
5609
|
maxOutputTokens: options?.openAiOAuth ? void 0 : maxOutput,
|
|
5417
5610
|
temperature: body.temperature,
|
|
5418
|
-
providerOptions
|
|
5611
|
+
providerOptions,
|
|
5612
|
+
webSearchToolName: webSearchTool?.name
|
|
5419
5613
|
};
|
|
5420
5614
|
}
|
|
5421
|
-
async function writeAnthropicStream(fullStream, modelId, write, log7) {
|
|
5615
|
+
async function writeAnthropicStream(fullStream, modelId, write, log7, hiddenToolName) {
|
|
5422
5616
|
const messageId = "msg_" + Date.now();
|
|
5423
5617
|
let blockIndex = -1;
|
|
5424
5618
|
let started = false;
|
|
5425
5619
|
let openType = null;
|
|
5426
5620
|
let pendingThinkingSig;
|
|
5427
5621
|
const idToBlock = /* @__PURE__ */ new Map();
|
|
5622
|
+
const hiddenIds = /* @__PURE__ */ new Set();
|
|
5428
5623
|
let finishReason = "end_turn";
|
|
5429
5624
|
let usage = { input_tokens: 0, output_tokens: 0 };
|
|
5430
5625
|
const emit = (event, data) => write(sseChunk(event, data));
|
|
@@ -5499,6 +5694,10 @@ async function writeAnthropicStream(fullStream, modelId, write, log7) {
|
|
|
5499
5694
|
case "text-end":
|
|
5500
5695
|
break;
|
|
5501
5696
|
case "tool-input-start": {
|
|
5697
|
+
if (part.toolName && part.toolName === hiddenToolName) {
|
|
5698
|
+
hiddenIds.add(part.id ?? "");
|
|
5699
|
+
break;
|
|
5700
|
+
}
|
|
5502
5701
|
const sig = grabRoundTripSignature(part);
|
|
5503
5702
|
openBlock("tool", {
|
|
5504
5703
|
type: "tool_use",
|
|
@@ -5510,6 +5709,7 @@ async function writeAnthropicStream(fullStream, modelId, write, log7) {
|
|
|
5510
5709
|
break;
|
|
5511
5710
|
}
|
|
5512
5711
|
case "tool-input-delta":
|
|
5712
|
+
if (hiddenIds.has(part.id ?? "")) break;
|
|
5513
5713
|
emit("content_block_delta", {
|
|
5514
5714
|
type: "content_block_delta",
|
|
5515
5715
|
index: idToBlock.get(part.id ?? "") ?? blockIndex,
|
|
@@ -5519,6 +5719,10 @@ async function writeAnthropicStream(fullStream, modelId, write, log7) {
|
|
|
5519
5719
|
case "tool-input-end":
|
|
5520
5720
|
break;
|
|
5521
5721
|
case "tool-call": {
|
|
5722
|
+
if (part.toolName && part.toolName === hiddenToolName || hiddenIds.has(part.toolCallId ?? "")) {
|
|
5723
|
+
hiddenIds.add(part.toolCallId ?? "");
|
|
5724
|
+
break;
|
|
5725
|
+
}
|
|
5522
5726
|
finishReason = "tool_use";
|
|
5523
5727
|
if (!idToBlock.has(part.toolCallId ?? "") && openType !== "tool") {
|
|
5524
5728
|
const sig = grabRoundTripSignature(part);
|
|
@@ -5567,7 +5771,12 @@ async function writeAnthropicStream(fullStream, modelId, write, log7) {
|
|
|
5567
5771
|
return { inputTokens: usage.input_tokens, outputTokens: usage.output_tokens };
|
|
5568
5772
|
}
|
|
5569
5773
|
async function streamAnthropicResponse(model, params, modelId, write, log7) {
|
|
5570
|
-
const
|
|
5774
|
+
const { webSearchToolName, ...callParams } = params;
|
|
5775
|
+
if (webSearchToolName) {
|
|
5776
|
+
log7?.(() => `gateway web_search: executing locally via DuckDuckGo (provider-agnostic)`);
|
|
5777
|
+
}
|
|
5778
|
+
const stopWhen = webSearchToolName ? stepCountIs(MAX_WEB_SEARCH_STEPS) : void 0;
|
|
5779
|
+
const result = streamText({ model, ...callParams, stopWhen, onError: () => {
|
|
5571
5780
|
} });
|
|
5572
5781
|
Promise.resolve(result.text).catch(() => {
|
|
5573
5782
|
});
|
|
@@ -5579,21 +5788,23 @@ async function streamAnthropicResponse(model, params, modelId, write, log7) {
|
|
|
5579
5788
|
});
|
|
5580
5789
|
Promise.resolve(result.usage).catch(() => {
|
|
5581
5790
|
});
|
|
5582
|
-
return await writeAnthropicStream(result.fullStream, modelId, write, log7);
|
|
5791
|
+
return await writeAnthropicStream(result.fullStream, modelId, write, log7, webSearchToolName);
|
|
5583
5792
|
}
|
|
5584
5793
|
async function generateAnthropicResponse(model, params, modelId, options) {
|
|
5585
5794
|
let text4;
|
|
5586
5795
|
let toolCalls;
|
|
5587
5796
|
let finishReason;
|
|
5588
5797
|
let usage;
|
|
5798
|
+
const { webSearchToolName, ...callParams } = params;
|
|
5799
|
+
const stopWhen = webSearchToolName ? stepCountIs(MAX_WEB_SEARCH_STEPS) : void 0;
|
|
5589
5800
|
if (options?.forceStream) {
|
|
5590
|
-
const r = streamText({ model, ...
|
|
5801
|
+
const r = streamText({ model, ...callParams, stopWhen, onError: () => {
|
|
5591
5802
|
} });
|
|
5592
5803
|
Promise.resolve(r.toolResults).catch(() => {
|
|
5593
5804
|
});
|
|
5594
5805
|
[text4, toolCalls, finishReason, usage] = await Promise.all([r.text, r.toolCalls, r.finishReason, r.usage]);
|
|
5595
5806
|
} else {
|
|
5596
|
-
const r = await generateText({ model, ...
|
|
5807
|
+
const r = await generateText({ model, ...callParams, stopWhen });
|
|
5597
5808
|
({ text: text4, toolCalls, finishReason, usage } = r);
|
|
5598
5809
|
}
|
|
5599
5810
|
return {
|
|
@@ -5603,7 +5814,7 @@ async function generateAnthropicResponse(model, params, modelId, options) {
|
|
|
5603
5814
|
model: modelId,
|
|
5604
5815
|
content: [
|
|
5605
5816
|
...text4 ? [{ type: "text", text: text4 }] : [],
|
|
5606
|
-
...toolCalls.map((tc) => ({
|
|
5817
|
+
...toolCalls.filter((tc) => tc.toolName !== webSearchToolName).map((tc) => ({
|
|
5607
5818
|
type: "tool_use",
|
|
5608
5819
|
id: encodeToolUseId(tc.toolCallId, grabRoundTripSignature(tc)),
|
|
5609
5820
|
name: tc.toolName,
|
|
@@ -5860,6 +6071,13 @@ function aliasModelId(realId, providerId) {
|
|
|
5860
6071
|
const safeRealId = realId.replace(/[\/\s:()]+/g, "-");
|
|
5861
6072
|
return `anthropic-${sanitized}__${safeRealId}`;
|
|
5862
6073
|
}
|
|
6074
|
+
function resolveRoute(byAlias, id, defaultRoute, plog) {
|
|
6075
|
+
const direct = lookupRoute(byAlias, id);
|
|
6076
|
+
if (direct) return direct;
|
|
6077
|
+
quietErrorLog(`resolveRoute: model '${id}' not in catalog, remapping to default route '${defaultRoute.aliasId}'`);
|
|
6078
|
+
plog(() => `resolveRoute: model '${id}' not in catalog, remapping to default route '${defaultRoute.aliasId}'`);
|
|
6079
|
+
return defaultRoute;
|
|
6080
|
+
}
|
|
5863
6081
|
function lookupRoute(byAlias, id) {
|
|
5864
6082
|
for (const key of routeLookupIds(id)) {
|
|
5865
6083
|
const route = byAlias.get(key);
|
|
@@ -5900,15 +6118,12 @@ function startProxyCatalog(routes, defaultAliasId, debug = false) {
|
|
|
5900
6118
|
const modelPathMatch = req.url.match(/^\/v1\/models\/([^?]+)/);
|
|
5901
6119
|
if (modelPathMatch) {
|
|
5902
6120
|
const id = decodeURIComponent(modelPathMatch[1]);
|
|
5903
|
-
const route =
|
|
5904
|
-
if (route) {
|
|
5905
|
-
|
|
5906
|
-
res.end(JSON.stringify(formatAnthropicModelEntry(route.aliasId, route.displayName, route.contextWindow, route.inputTypes)));
|
|
5907
|
-
} else {
|
|
5908
|
-
quietErrorLog(`GET /v1/models/${id} - model not found`);
|
|
5909
|
-
res.writeHead(404, { "Content-Type": "application/json" });
|
|
5910
|
-
res.end(JSON.stringify({ error: { type: "not_found_error", message: `Model '${id}' not found` } }));
|
|
6121
|
+
const route = resolveRoute(byAlias, id, defaultRoute, plog);
|
|
6122
|
+
if (route === defaultRoute && id !== defaultRoute.aliasId) {
|
|
6123
|
+
quietErrorLog(`GET /v1/models/${id} - model not found, returning default route '${defaultRoute.aliasId}'`);
|
|
5911
6124
|
}
|
|
6125
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
6126
|
+
res.end(JSON.stringify(formatAnthropicModelEntry(route.aliasId, route.displayName, route.contextWindow, route.inputTypes)));
|
|
5912
6127
|
} else {
|
|
5913
6128
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
5914
6129
|
res.end(modelsPayload);
|
|
@@ -5931,7 +6146,7 @@ function startProxyCatalog(routes, defaultAliasId, debug = false) {
|
|
|
5931
6146
|
}
|
|
5932
6147
|
const originalModel = anthropicBody.model;
|
|
5933
6148
|
const clientWantsStream = Boolean(anthropicBody.stream);
|
|
5934
|
-
const route =
|
|
6149
|
+
const route = resolveRoute(byAlias, originalModel, defaultRoute, plog);
|
|
5935
6150
|
if (route === defaultRoute && originalModel !== defaultRoute.aliasId) {
|
|
5936
6151
|
quietErrorLog(`POST /v1/messages - model alias '${originalModel}' not found, falling back to default route '${defaultRoute.aliasId}'`);
|
|
5937
6152
|
}
|
|
@@ -7032,10 +7247,10 @@ function makeRouteResolver(localProviders) {
|
|
|
7032
7247
|
return provider && model ? localModelToRoute(provider, model) ?? void 0 : void 0;
|
|
7033
7248
|
};
|
|
7034
7249
|
}
|
|
7035
|
-
function buildCatalogRoutes(startingRoute, favorites,
|
|
7250
|
+
function buildCatalogRoutes(startingRoute, favorites, resolveRoute2, max = MAX_MODEL_CATALOG) {
|
|
7036
7251
|
const droppedFavorites = [];
|
|
7037
7252
|
const tail = favorites.map((fav) => {
|
|
7038
|
-
const route =
|
|
7253
|
+
const route = resolveRoute2(fav.providerId, fav.modelId);
|
|
7039
7254
|
if (!route) droppedFavorites.push(fav);
|
|
7040
7255
|
return route;
|
|
7041
7256
|
}).filter((route) => route !== void 0);
|
|
@@ -7260,7 +7475,7 @@ async function askSaveServerPassword() {
|
|
|
7260
7475
|
import { createServer as createServer2 } from "http";
|
|
7261
7476
|
|
|
7262
7477
|
// src/gateway/openai-adapter.ts
|
|
7263
|
-
import { tool as
|
|
7478
|
+
import { tool as tool4, jsonSchema as jsonSchema4, streamText as streamText2, generateText as generateText2 } from "ai";
|
|
7264
7479
|
function translateOpenAiRequest(body) {
|
|
7265
7480
|
const toolNameById = /* @__PURE__ */ new Map();
|
|
7266
7481
|
for (const msg of body.messages) {
|
|
@@ -7325,10 +7540,10 @@ function translateOpenAiRequest(body) {
|
|
|
7325
7540
|
tools = {};
|
|
7326
7541
|
for (const t of body.tools) {
|
|
7327
7542
|
if (t.type === "function" && t.function.name) {
|
|
7328
|
-
const schema = t.function.parameters ?
|
|
7329
|
-
tools[t.function.name] =
|
|
7543
|
+
const schema = t.function.parameters ? jsonSchema4(t.function.parameters) : void 0;
|
|
7544
|
+
tools[t.function.name] = tool4({
|
|
7330
7545
|
description: t.function.description ?? "",
|
|
7331
|
-
inputSchema: schema ??
|
|
7546
|
+
inputSchema: schema ?? jsonSchema4({ type: "object", properties: {} })
|
|
7332
7547
|
});
|
|
7333
7548
|
}
|
|
7334
7549
|
}
|
|
@@ -7628,7 +7843,7 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog) {
|
|
|
7628
7843
|
sendJson(res, 400, { error: { message: "Invalid JSON body" } });
|
|
7629
7844
|
return;
|
|
7630
7845
|
}
|
|
7631
|
-
const model = lookupModel(res, options.catalog, body.model);
|
|
7846
|
+
const model = lookupModel(res, options.catalog, body.model, plog);
|
|
7632
7847
|
if (!model) {
|
|
7633
7848
|
plog(`model not found: ${body.model}`);
|
|
7634
7849
|
return;
|
|
@@ -7760,7 +7975,7 @@ async function handleOpenAIChatCompletions(req, res, options, modelCache, plog)
|
|
|
7760
7975
|
sendJson(res, 400, { error: { message: "Invalid JSON body" } });
|
|
7761
7976
|
return;
|
|
7762
7977
|
}
|
|
7763
|
-
const model = lookupModel(res, options.catalog, body.model);
|
|
7978
|
+
const model = lookupModel(res, options.catalog, body.model, plog);
|
|
7764
7979
|
if (!model) return;
|
|
7765
7980
|
if (supportsDirectOpenAIChatCompletions(model)) {
|
|
7766
7981
|
if (model.completionsUrl && !/^https?:\/\//i.test(model.completionsUrl)) {
|
|
@@ -7831,12 +8046,19 @@ data: ${JSON.stringify({ type: "error", error: { type: errorType, message } })}
|
|
|
7831
8046
|
}
|
|
7832
8047
|
}
|
|
7833
8048
|
}
|
|
7834
|
-
function lookupModel(res, catalog, modelId) {
|
|
8049
|
+
function lookupModel(res, catalog, modelId, plog) {
|
|
7835
8050
|
if (typeof modelId !== "string") {
|
|
7836
8051
|
sendJson(res, 400, { error: { message: "Request body must include a model string" } });
|
|
7837
8052
|
return null;
|
|
7838
8053
|
}
|
|
7839
|
-
|
|
8054
|
+
let model = catalog.get(modelId);
|
|
8055
|
+
if (!model) {
|
|
8056
|
+
const defaultModel = catalog.list()[0];
|
|
8057
|
+
if (defaultModel) {
|
|
8058
|
+
plog(`model '${modelId}' unknown \u2014 remapping to default '${defaultModel.id}'`);
|
|
8059
|
+
model = defaultModel;
|
|
8060
|
+
}
|
|
8061
|
+
}
|
|
7840
8062
|
if (!model) {
|
|
7841
8063
|
sendJson(res, 400, { error: { message: `Unknown model: ${modelId}` } });
|
|
7842
8064
|
return null;
|
|
@@ -11016,4 +11238,4 @@ export {
|
|
|
11016
11238
|
quitClaudeAppGracefully,
|
|
11017
11239
|
launchOrRestartClaudeApp
|
|
11018
11240
|
};
|
|
11019
|
-
//# sourceMappingURL=chunk-
|
|
11241
|
+
//# sourceMappingURL=chunk-APLGXZWQ.js.map
|