open-agents-ai 0.103.37 → 0.103.39
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 +113 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12607,30 +12607,78 @@ async function handleCmd(cmd) {
|
|
|
12607
12607
|
dlog('expose: auth key configured (' + exposeAuthKey.length + ' chars)');
|
|
12608
12608
|
}
|
|
12609
12609
|
|
|
12610
|
-
//
|
|
12611
|
-
|
|
12610
|
+
// Passthrough mode: forward from a remote /endpoint (Chutes, Groq, etc.)
|
|
12611
|
+
var isPassthrough = args.passthrough === 'true';
|
|
12612
|
+
var endpointAuth = args.endpoint_auth || '';
|
|
12613
|
+
if (isPassthrough) {
|
|
12614
|
+
dlog('expose: PASSTHROUGH mode \u2014 forwarding from upstream endpoint');
|
|
12615
|
+
}
|
|
12616
|
+
|
|
12617
|
+
// Query models from the backend
|
|
12618
|
+
var rawUrl = args.ollama_url || process.env.OLLAMA_URL || 'http://localhost:11434';
|
|
12619
|
+
// For passthrough: normalize URL \u2014 strip /v1/chat/completions, /v1, etc. so we can append our own paths
|
|
12620
|
+
const ollamaUrl = isPassthrough
|
|
12621
|
+
? rawUrl.replace(/\\/+$/, '').replace(/\\/chat\\/completions$/, '').replace(/\\/completions$/, '').replace(/\\/models(\\/.*)?$/, '').replace(/\\/v1$/, '').replace(/\\/+$/, '')
|
|
12622
|
+
: rawUrl;
|
|
12612
12623
|
let models = [];
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
|
|
12623
|
-
|
|
12624
|
+
|
|
12625
|
+
if (isPassthrough) {
|
|
12626
|
+
// Passthrough: query /v1/models from the upstream endpoint (OpenAI-compatible)
|
|
12627
|
+
try {
|
|
12628
|
+
var modelsHeaders = { 'Content-Type': 'application/json' };
|
|
12629
|
+
if (endpointAuth) modelsHeaders['Authorization'] = 'Bearer ' + endpointAuth;
|
|
12630
|
+
var modelsUrl = ollamaUrl.replace(/\\/+$/, '') + '/v1/models';
|
|
12631
|
+
dlog('expose: passthrough querying models from ' + modelsUrl);
|
|
12632
|
+
const modelsResp = await fetch(modelsUrl, { headers: modelsHeaders });
|
|
12633
|
+
if (modelsResp.ok) {
|
|
12634
|
+
const modelsData = await modelsResp.json();
|
|
12635
|
+
var modelList = modelsData.data || modelsData.models || [];
|
|
12636
|
+
models = modelList.map(function(m) {
|
|
12637
|
+
return {
|
|
12638
|
+
name: m.id || m.name || 'unknown',
|
|
12639
|
+
size: 0,
|
|
12640
|
+
parameterSize: '',
|
|
12641
|
+
family: m.owned_by || '',
|
|
12642
|
+
quantization: '',
|
|
12643
|
+
};
|
|
12644
|
+
});
|
|
12645
|
+
} else {
|
|
12646
|
+
var errText = '';
|
|
12647
|
+
try { errText = await modelsResp.text(); } catch {}
|
|
12648
|
+
writeResp(id, { ok: false, output: 'Upstream /v1/models returned ' + modelsResp.status + ': ' + errText.slice(0, 200) });
|
|
12649
|
+
return;
|
|
12650
|
+
}
|
|
12651
|
+
} catch (e) {
|
|
12652
|
+
writeResp(id, { ok: false, output: 'Cannot reach upstream endpoint at ' + ollamaUrl + ': ' + e.message });
|
|
12653
|
+
return;
|
|
12654
|
+
}
|
|
12655
|
+
} else {
|
|
12656
|
+
// Local Ollama: query /api/tags
|
|
12657
|
+
try {
|
|
12658
|
+
const tagsResp = await fetch(ollamaUrl + '/api/tags');
|
|
12659
|
+
if (tagsResp.ok) {
|
|
12660
|
+
const tagsData = await tagsResp.json();
|
|
12661
|
+
models = (tagsData.models || []).map(function(m) {
|
|
12662
|
+
return {
|
|
12663
|
+
name: m.name,
|
|
12664
|
+
size: m.size || 0,
|
|
12665
|
+
parameterSize: m.details ? m.details.parameter_size || '' : '',
|
|
12666
|
+
family: m.details ? m.details.family || '' : '',
|
|
12667
|
+
quantization: m.details ? m.details.quantization_level || '' : '',
|
|
12668
|
+
};
|
|
12669
|
+
});
|
|
12670
|
+
}
|
|
12671
|
+
} catch (e) {
|
|
12672
|
+
writeResp(id, { ok: false, output: 'Cannot reach Ollama at ' + ollamaUrl + ': ' + e.message });
|
|
12673
|
+
return;
|
|
12624
12674
|
}
|
|
12625
|
-
} catch (e) {
|
|
12626
|
-
writeResp(id, { ok: false, output: 'Cannot reach Ollama at ' + ollamaUrl + ': ' + e.message });
|
|
12627
|
-
return;
|
|
12628
12675
|
}
|
|
12629
12676
|
|
|
12630
12677
|
if (models.length === 0) {
|
|
12631
|
-
writeResp(id, { ok: false, output: 'No models found on Ollama. Pull a model first.' });
|
|
12678
|
+
writeResp(id, { ok: false, output: isPassthrough ? 'No models found on upstream endpoint.' : 'No models found on Ollama. Pull a model first.' });
|
|
12632
12679
|
return;
|
|
12633
12680
|
}
|
|
12681
|
+
dlog('expose: found ' + models.length + ' models' + (isPassthrough ? ' (passthrough)' : ''));
|
|
12634
12682
|
|
|
12635
12683
|
// Fetch market rates from OpenRouter (free, no auth)
|
|
12636
12684
|
let marketRates = {};
|
|
@@ -12782,10 +12830,12 @@ async function handleCmd(cmd) {
|
|
|
12782
12830
|
if (parsedReq.temperature !== undefined) chatBody.temperature = parsedReq.temperature;
|
|
12783
12831
|
if (parsedReq.max_tokens) chatBody.max_tokens = parsedReq.max_tokens;
|
|
12784
12832
|
|
|
12785
|
-
|
|
12833
|
+
var chatHeaders = { 'Content-Type': 'application/json' };
|
|
12834
|
+
if (isPassthrough && endpointAuth) chatHeaders['Authorization'] = 'Bearer ' + endpointAuth;
|
|
12835
|
+
dlog('expose: calling /v1/chat/completions with ' + chatBody.messages.length + ' messages, tools=' + (chatBody.tools ? chatBody.tools.length : 0) + (isPassthrough ? ' (passthrough)' : ''));
|
|
12786
12836
|
genResp = await fetch(ollamaUrl + '/v1/chat/completions', {
|
|
12787
12837
|
method: 'POST',
|
|
12788
|
-
headers:
|
|
12838
|
+
headers: chatHeaders,
|
|
12789
12839
|
body: JSON.stringify(chatBody),
|
|
12790
12840
|
});
|
|
12791
12841
|
genData = await genResp.json();
|
|
@@ -12816,8 +12866,36 @@ async function handleCmd(cmd) {
|
|
|
12816
12866
|
usage: { input_tokens: inputTokens, output_tokens: outputTokens },
|
|
12817
12867
|
pricing: entry.pricing,
|
|
12818
12868
|
};
|
|
12869
|
+
} else if (isPassthrough) {
|
|
12870
|
+
// Passthrough flat prompt \u2014 convert to /v1/chat/completions (upstream has no /api/generate)
|
|
12871
|
+
var flatPrompt = parsedReq && parsedReq.prompt ? parsedReq.prompt : (prompt || 'Hello');
|
|
12872
|
+
var ptHeaders = { 'Content-Type': 'application/json' };
|
|
12873
|
+
if (endpointAuth) ptHeaders['Authorization'] = 'Bearer ' + endpointAuth;
|
|
12874
|
+
genResp = await fetch(ollamaUrl + '/v1/chat/completions', {
|
|
12875
|
+
method: 'POST',
|
|
12876
|
+
headers: ptHeaders,
|
|
12877
|
+
body: JSON.stringify({
|
|
12878
|
+
model: model.name,
|
|
12879
|
+
messages: [{ role: 'user', content: flatPrompt }],
|
|
12880
|
+
stream: false,
|
|
12881
|
+
}),
|
|
12882
|
+
});
|
|
12883
|
+
genData = await genResp.json();
|
|
12884
|
+
var ptChoices = genData.choices || [];
|
|
12885
|
+
var ptMsg = (ptChoices[0] || {}).message || {};
|
|
12886
|
+
output = (ptMsg.content || '').replace(/<think>[\\s\\S]*?<\\/think>/g, '').trim();
|
|
12887
|
+
inputTokens = (genData.usage || {}).prompt_tokens || 0;
|
|
12888
|
+
outputTokens = (genData.usage || {}).completion_tokens || 0;
|
|
12889
|
+
|
|
12890
|
+
responsePayload = {
|
|
12891
|
+
model: model.name,
|
|
12892
|
+
response: output,
|
|
12893
|
+
choices: ptChoices,
|
|
12894
|
+
usage: { input_tokens: inputTokens, output_tokens: outputTokens },
|
|
12895
|
+
pricing: entry.pricing,
|
|
12896
|
+
};
|
|
12819
12897
|
} else {
|
|
12820
|
-
// Flat prompt \u2014 use /api/generate (
|
|
12898
|
+
// Flat prompt \u2014 use /api/generate (local Ollama)
|
|
12821
12899
|
var flatPrompt = parsedReq && parsedReq.prompt ? parsedReq.prompt : (prompt || 'Hello');
|
|
12822
12900
|
genResp = await fetch(ollamaUrl + '/api/generate', {
|
|
12823
12901
|
method: 'POST',
|
|
@@ -28358,6 +28436,7 @@ ${this.formatConnectionInfo()}`);
|
|
|
28358
28436
|
_margin;
|
|
28359
28437
|
_passthrough = false;
|
|
28360
28438
|
_loadbalance = false;
|
|
28439
|
+
_endpointAuth;
|
|
28361
28440
|
_pollTimer = null;
|
|
28362
28441
|
_stats = {
|
|
28363
28442
|
status: "standby",
|
|
@@ -28402,6 +28481,7 @@ ${this.formatConnectionInfo()}`);
|
|
|
28402
28481
|
this._margin = options.margin ?? 0.5;
|
|
28403
28482
|
this._passthrough = options.passthrough ?? false;
|
|
28404
28483
|
this._loadbalance = options.loadbalance ?? false;
|
|
28484
|
+
this._endpointAuth = options.endpointAuth;
|
|
28405
28485
|
this._onInfo = options.onInfo;
|
|
28406
28486
|
this._onError = options.onError;
|
|
28407
28487
|
if (options.authKey === void 0 || options.authKey === "") {
|
|
@@ -28421,21 +28501,23 @@ ${this.formatConnectionInfo()}`);
|
|
|
28421
28501
|
throw new Error(`Nexus daemon connect failed: ${connectResult.error}`);
|
|
28422
28502
|
}
|
|
28423
28503
|
await new Promise((r) => setTimeout(r, 500));
|
|
28424
|
-
this._onInfo?.("Registering inference capabilities...");
|
|
28425
|
-
|
|
28504
|
+
this._onInfo?.(this._passthrough ? `Registering passthrough capabilities (\u2192 ${this._targetUrl})...` : "Registering inference capabilities...");
|
|
28505
|
+
const exposeArgs = {
|
|
28426
28506
|
action: "expose",
|
|
28427
28507
|
ollama_url: this._targetUrl,
|
|
28428
28508
|
margin: String(this._margin),
|
|
28429
28509
|
auth_key: this._authKey
|
|
28430
|
-
}
|
|
28510
|
+
};
|
|
28511
|
+
if (this._passthrough) {
|
|
28512
|
+
exposeArgs.passthrough = "true";
|
|
28513
|
+
if (this._endpointAuth) {
|
|
28514
|
+
exposeArgs.endpoint_auth = this._endpointAuth;
|
|
28515
|
+
}
|
|
28516
|
+
}
|
|
28517
|
+
let exposeResult = await this._nexusTool.execute(exposeArgs);
|
|
28431
28518
|
if (!exposeResult.success && exposeResult.error?.includes("not running")) {
|
|
28432
28519
|
await new Promise((r) => setTimeout(r, 1500));
|
|
28433
|
-
exposeResult = await this._nexusTool.execute(
|
|
28434
|
-
action: "expose",
|
|
28435
|
-
ollama_url: this._targetUrl,
|
|
28436
|
-
margin: String(this._margin),
|
|
28437
|
-
auth_key: this._authKey
|
|
28438
|
-
});
|
|
28520
|
+
exposeResult = await this._nexusTool.execute(exposeArgs);
|
|
28439
28521
|
}
|
|
28440
28522
|
if (!exposeResult.success) {
|
|
28441
28523
|
throw new Error(`Expose failed: ${exposeResult.error}`);
|
|
@@ -46888,7 +46970,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
46888
46970
|
let targetUrl;
|
|
46889
46971
|
if (kindOrUrl === "passthrough" || passthrough) {
|
|
46890
46972
|
kind = "custom";
|
|
46891
|
-
targetUrl = config.backendUrl;
|
|
46973
|
+
targetUrl = normalizeBaseUrl(config.backendUrl);
|
|
46892
46974
|
passthrough = true;
|
|
46893
46975
|
} else if (knownKinds.includes(kindOrUrl)) {
|
|
46894
46976
|
kind = kindOrUrl;
|
|
@@ -46917,6 +46999,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
46917
46999
|
stateDir: join50(repoRoot, ".oa"),
|
|
46918
47000
|
passthrough: passthrough ?? false,
|
|
46919
47001
|
loadbalance: loadbalance ?? false,
|
|
47002
|
+
endpointAuth: passthrough ? config.apiKey : void 0,
|
|
46920
47003
|
onInfo: (msg) => {
|
|
46921
47004
|
exposeSpinnerMsg = msg;
|
|
46922
47005
|
},
|
package/package.json
CHANGED