open-agents-ai 0.184.53 → 0.184.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +143 -54
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -62035,6 +62035,102 @@ function getVersion3() {
|
|
|
62035
62035
|
}
|
|
62036
62036
|
return "0.0.0";
|
|
62037
62037
|
}
|
|
62038
|
+
async function refreshEndpointRegistry() {
|
|
62039
|
+
endpointRegistry.length = 0;
|
|
62040
|
+
modelRouteMap.clear();
|
|
62041
|
+
const config = loadConfig();
|
|
62042
|
+
const primaryLabel = (() => {
|
|
62043
|
+
if (config.backendUrl.includes("127.0.0.1") || config.backendUrl.includes("localhost"))
|
|
62044
|
+
return "local";
|
|
62045
|
+
try {
|
|
62046
|
+
return new URL(config.backendUrl).hostname.split(".")[0];
|
|
62047
|
+
} catch {
|
|
62048
|
+
return "primary";
|
|
62049
|
+
}
|
|
62050
|
+
})();
|
|
62051
|
+
endpointRegistry.push({
|
|
62052
|
+
label: primaryLabel,
|
|
62053
|
+
url: config.backendUrl,
|
|
62054
|
+
type: config.backendType || "ollama",
|
|
62055
|
+
authKey: config.apiKey
|
|
62056
|
+
});
|
|
62057
|
+
try {
|
|
62058
|
+
const resp = await fetch("https://openagents.nexus/api/v1/sponsors", {
|
|
62059
|
+
signal: AbortSignal.timeout(5e3)
|
|
62060
|
+
});
|
|
62061
|
+
if (resp.ok) {
|
|
62062
|
+
const data = await resp.json();
|
|
62063
|
+
for (const sp of (data.sponsors || []).filter((s) => s.status === "active" && s.tunnelUrl)) {
|
|
62064
|
+
if (sp.tunnelUrl === config.backendUrl)
|
|
62065
|
+
continue;
|
|
62066
|
+
const label = sp.name.replace(/[^a-zA-Z0-9]/g, "").slice(0, 12).toLowerCase() || "sponsor";
|
|
62067
|
+
endpointRegistry.push({
|
|
62068
|
+
label,
|
|
62069
|
+
url: sp.tunnelUrl,
|
|
62070
|
+
type: "vllm",
|
|
62071
|
+
authKey: sp.authKey
|
|
62072
|
+
});
|
|
62073
|
+
}
|
|
62074
|
+
}
|
|
62075
|
+
} catch {
|
|
62076
|
+
}
|
|
62077
|
+
}
|
|
62078
|
+
async function fetchAggregatedModels() {
|
|
62079
|
+
const allModels = [];
|
|
62080
|
+
modelRouteMap.clear();
|
|
62081
|
+
const fetches = endpointRegistry.map(async (ep) => {
|
|
62082
|
+
try {
|
|
62083
|
+
const isOllama = ep.type === "ollama";
|
|
62084
|
+
const modelsPath = isOllama ? "/api/tags" : "/v1/models";
|
|
62085
|
+
const result = await ollamaRequest(ep.url, modelsPath, "GET");
|
|
62086
|
+
if (result.status !== 200)
|
|
62087
|
+
return;
|
|
62088
|
+
const body = JSON.parse(result.body);
|
|
62089
|
+
if (isOllama) {
|
|
62090
|
+
const models = body.models ?? [];
|
|
62091
|
+
for (const m of models) {
|
|
62092
|
+
const prefixed = `${ep.label}/${m.name}`;
|
|
62093
|
+
modelRouteMap.set(prefixed, { endpoint: ep, originalId: m.name });
|
|
62094
|
+
allModels.push({
|
|
62095
|
+
id: prefixed,
|
|
62096
|
+
object: "model",
|
|
62097
|
+
created: m.modified_at ? Math.floor(new Date(m.modified_at).getTime() / 1e3) : 0,
|
|
62098
|
+
owned_by: ep.label
|
|
62099
|
+
});
|
|
62100
|
+
}
|
|
62101
|
+
} else {
|
|
62102
|
+
const models = body.data ?? [];
|
|
62103
|
+
for (const m of models) {
|
|
62104
|
+
const originalId = m.id || m.name;
|
|
62105
|
+
const prefixed = `${ep.label}/${originalId}`;
|
|
62106
|
+
modelRouteMap.set(prefixed, { endpoint: ep, originalId });
|
|
62107
|
+
allModels.push({
|
|
62108
|
+
id: prefixed,
|
|
62109
|
+
object: "model",
|
|
62110
|
+
created: m.created || 0,
|
|
62111
|
+
owned_by: ep.label
|
|
62112
|
+
});
|
|
62113
|
+
}
|
|
62114
|
+
}
|
|
62115
|
+
} catch {
|
|
62116
|
+
}
|
|
62117
|
+
});
|
|
62118
|
+
await Promise.allSettled(fetches);
|
|
62119
|
+
return allModels.sort((a, b) => a.id.localeCompare(b.id));
|
|
62120
|
+
}
|
|
62121
|
+
function resolveModelEndpoint(modelId) {
|
|
62122
|
+
const exact = modelRouteMap.get(modelId);
|
|
62123
|
+
if (exact)
|
|
62124
|
+
return exact;
|
|
62125
|
+
for (const [prefixed, route] of modelRouteMap) {
|
|
62126
|
+
if (route.originalId === modelId)
|
|
62127
|
+
return route;
|
|
62128
|
+
}
|
|
62129
|
+
if (endpointRegistry.length > 0) {
|
|
62130
|
+
return { endpoint: endpointRegistry[0], originalId: modelId };
|
|
62131
|
+
}
|
|
62132
|
+
return null;
|
|
62133
|
+
}
|
|
62038
62134
|
function recordMetric(method, path, status) {
|
|
62039
62135
|
const key = `${method}|${path}|${status}`;
|
|
62040
62136
|
const existing = metrics.requests.get(key);
|
|
@@ -62104,10 +62200,10 @@ async function parseJsonBody(req) {
|
|
|
62104
62200
|
return null;
|
|
62105
62201
|
}
|
|
62106
62202
|
}
|
|
62107
|
-
function backendAuthHeaders() {
|
|
62108
|
-
const
|
|
62109
|
-
if (
|
|
62110
|
-
return { Authorization: `Bearer ${
|
|
62203
|
+
function backendAuthHeaders(endpoint) {
|
|
62204
|
+
const key = endpoint?.authKey ?? loadConfig().apiKey;
|
|
62205
|
+
if (key)
|
|
62206
|
+
return { Authorization: `Bearer ${key}` };
|
|
62111
62207
|
return {};
|
|
62112
62208
|
}
|
|
62113
62209
|
function ollamaRequest(ollamaUrl, path, method, body) {
|
|
@@ -62285,33 +62381,15 @@ function handleMetrics(res) {
|
|
|
62285
62381
|
}
|
|
62286
62382
|
async function handleV1Models(res, ollamaUrl) {
|
|
62287
62383
|
try {
|
|
62288
|
-
const
|
|
62289
|
-
|
|
62290
|
-
|
|
62291
|
-
|
|
62292
|
-
|
|
62293
|
-
|
|
62294
|
-
return;
|
|
62295
|
-
}
|
|
62296
|
-
jsonResponse(res, 200, JSON.parse(result2.body));
|
|
62297
|
-
return;
|
|
62298
|
-
}
|
|
62299
|
-
const result = await ollamaRequest(ollamaUrl, "/api/tags", "GET");
|
|
62300
|
-
if (result.status !== 200) {
|
|
62301
|
-
jsonResponse(res, result.status, { error: "Failed to fetch models from backend" });
|
|
62302
|
-
return;
|
|
62303
|
-
}
|
|
62304
|
-
const ollamaBody = JSON.parse(result.body);
|
|
62305
|
-
const models = (ollamaBody.models ?? []).map((m) => ({
|
|
62306
|
-
id: m.name,
|
|
62307
|
-
object: "model",
|
|
62308
|
-
created: m.modified_at ? Math.floor(new Date(m.modified_at).getTime() / 1e3) : 0,
|
|
62309
|
-
owned_by: "local"
|
|
62310
|
-
}));
|
|
62311
|
-
jsonResponse(res, 200, { object: "list", data: models });
|
|
62384
|
+
const models = await fetchAggregatedModels();
|
|
62385
|
+
jsonResponse(res, 200, {
|
|
62386
|
+
object: "list",
|
|
62387
|
+
data: models,
|
|
62388
|
+
_endpoints: endpointRegistry.map((e) => ({ label: e.label, url: e.url, type: e.type }))
|
|
62389
|
+
});
|
|
62312
62390
|
} catch (err) {
|
|
62313
62391
|
jsonResponse(res, 502, {
|
|
62314
|
-
error: "Failed to
|
|
62392
|
+
error: "Failed to fetch models",
|
|
62315
62393
|
message: err instanceof Error ? err.message : String(err)
|
|
62316
62394
|
});
|
|
62317
62395
|
}
|
|
@@ -62325,10 +62403,13 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
62325
62403
|
const requestBody = body;
|
|
62326
62404
|
const stream = requestBody["stream"] === true;
|
|
62327
62405
|
const model = requestBody["model"] || "unknown";
|
|
62328
|
-
const
|
|
62329
|
-
const
|
|
62330
|
-
|
|
62331
|
-
|
|
62406
|
+
const route = resolveModelEndpoint(model);
|
|
62407
|
+
const targetUrl = route?.endpoint.url ?? ollamaUrl;
|
|
62408
|
+
const targetType = route?.endpoint.type ?? loadConfig().backendType ?? "ollama";
|
|
62409
|
+
const originalModel = route?.originalId ?? model;
|
|
62410
|
+
const routedBody = { ...requestBody, model: originalModel };
|
|
62411
|
+
if (targetType === "vllm" || targetType === "openai") {
|
|
62412
|
+
const payload = JSON.stringify(routedBody);
|
|
62332
62413
|
if (stream) {
|
|
62333
62414
|
res.writeHead(200, {
|
|
62334
62415
|
"Content-Type": "text/event-stream",
|
|
@@ -62338,7 +62419,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
62338
62419
|
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
62339
62420
|
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
|
62340
62421
|
});
|
|
62341
|
-
ollamaStream(
|
|
62422
|
+
ollamaStream(targetUrl, "/v1/chat/completions", "POST", payload, (chunk) => {
|
|
62342
62423
|
res.write(chunk);
|
|
62343
62424
|
}, () => {
|
|
62344
62425
|
res.end();
|
|
@@ -62353,7 +62434,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
62353
62434
|
});
|
|
62354
62435
|
} else {
|
|
62355
62436
|
try {
|
|
62356
|
-
const result = await ollamaRequest(
|
|
62437
|
+
const result = await ollamaRequest(targetUrl, "/v1/chat/completions", "POST", payload);
|
|
62357
62438
|
if (result.status !== 200) {
|
|
62358
62439
|
jsonResponse(res, result.status, { error: "Backend request failed", details: result.body });
|
|
62359
62440
|
return;
|
|
@@ -62371,7 +62452,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
62371
62452
|
return;
|
|
62372
62453
|
}
|
|
62373
62454
|
const ollamaPayload = JSON.stringify({
|
|
62374
|
-
...
|
|
62455
|
+
...routedBody,
|
|
62375
62456
|
stream,
|
|
62376
62457
|
think: false
|
|
62377
62458
|
});
|
|
@@ -62386,7 +62467,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
62386
62467
|
});
|
|
62387
62468
|
const chatId = `chatcmpl-${randomBytes16(12).toString("hex")}`;
|
|
62388
62469
|
let buffer = "";
|
|
62389
|
-
ollamaStream(
|
|
62470
|
+
ollamaStream(targetUrl, "/api/chat", "POST", ollamaPayload, (chunk) => {
|
|
62390
62471
|
buffer += chunk;
|
|
62391
62472
|
const lines = buffer.split("\n");
|
|
62392
62473
|
buffer = lines.pop() ?? "";
|
|
@@ -62476,7 +62557,7 @@ async function handleV1ChatCompletions(req, res, ollamaUrl) {
|
|
|
62476
62557
|
});
|
|
62477
62558
|
} else {
|
|
62478
62559
|
try {
|
|
62479
|
-
const result = await ollamaRequest(
|
|
62560
|
+
const result = await ollamaRequest(targetUrl, "/api/chat", "POST", ollamaPayload);
|
|
62480
62561
|
if (result.status !== 200) {
|
|
62481
62562
|
jsonResponse(res, result.status, {
|
|
62482
62563
|
error: "Ollama request failed",
|
|
@@ -63149,29 +63230,35 @@ function startApiServer(options = {}) {
|
|
|
63149
63230
|
`);
|
|
63150
63231
|
}
|
|
63151
63232
|
});
|
|
63152
|
-
|
|
63153
|
-
|
|
63154
|
-
|
|
63233
|
+
refreshEndpointRegistry().catch(() => {
|
|
63234
|
+
}).then(() => {
|
|
63235
|
+
server.listen(port, host, () => {
|
|
63236
|
+
const version = getVersion3();
|
|
63237
|
+
process.stderr.write(`
|
|
63155
63238
|
open-agents API server v${version}
|
|
63156
63239
|
`);
|
|
63157
|
-
|
|
63240
|
+
process.stderr.write(` Listening on http://${host}:${port}
|
|
63158
63241
|
`);
|
|
63159
|
-
|
|
63160
|
-
process.stderr.write(` Backend (${beType}): ${ollamaUrl}
|
|
63242
|
+
process.stderr.write(` Endpoints: ${endpointRegistry.length} registered
|
|
63161
63243
|
`);
|
|
63162
|
-
|
|
63163
|
-
|
|
63164
|
-
process.stderr.write(` Auth: ${keyCount} scoped key(s) (read/run/admin)
|
|
63244
|
+
for (const ep of endpointRegistry) {
|
|
63245
|
+
process.stderr.write(` ${ep.label}: ${ep.url} (${ep.type})${ep.authKey ? " [auth]" : ""}
|
|
63165
63246
|
`);
|
|
63166
|
-
|
|
63167
|
-
process.
|
|
63247
|
+
}
|
|
63248
|
+
if (process.env["OA_API_KEYS"]) {
|
|
63249
|
+
const keyCount = process.env["OA_API_KEYS"].split(",").length;
|
|
63250
|
+
process.stderr.write(` Auth: ${keyCount} scoped key(s) (read/run/admin)
|
|
63168
63251
|
`);
|
|
63169
|
-
|
|
63170
|
-
|
|
63252
|
+
} else if (process.env["OA_API_KEY"]) {
|
|
63253
|
+
process.stderr.write(` Auth: single Bearer token (admin scope)
|
|
63171
63254
|
`);
|
|
63172
|
-
|
|
63173
|
-
|
|
63255
|
+
} else {
|
|
63256
|
+
process.stderr.write(` Auth: disabled (set OA_API_KEY or OA_API_KEYS to enable)
|
|
63174
63257
|
`);
|
|
63258
|
+
}
|
|
63259
|
+
process.stderr.write(`
|
|
63260
|
+
`);
|
|
63261
|
+
});
|
|
63175
63262
|
});
|
|
63176
63263
|
const shutdown = () => {
|
|
63177
63264
|
process.stderr.write("\n Shutting down API server...\n");
|
|
@@ -63201,7 +63288,7 @@ async function apiServeCommand(opts, config) {
|
|
|
63201
63288
|
server.on("close", resolve36);
|
|
63202
63289
|
});
|
|
63203
63290
|
}
|
|
63204
|
-
var metrics, startedAt, runningProcesses;
|
|
63291
|
+
var endpointRegistry, modelRouteMap, metrics, startedAt, runningProcesses;
|
|
63205
63292
|
var init_serve = __esm({
|
|
63206
63293
|
"packages/cli/dist/api/serve.js"() {
|
|
63207
63294
|
"use strict";
|
|
@@ -63209,6 +63296,8 @@ var init_serve = __esm({
|
|
|
63209
63296
|
init_oa_directory();
|
|
63210
63297
|
init_render();
|
|
63211
63298
|
init_profiles();
|
|
63299
|
+
endpointRegistry = [];
|
|
63300
|
+
modelRouteMap = /* @__PURE__ */ new Map();
|
|
63212
63301
|
metrics = {
|
|
63213
63302
|
requests: /* @__PURE__ */ new Map(),
|
|
63214
63303
|
totalTokensIn: 0,
|
package/package.json
CHANGED