open-agents-ai 0.184.69 → 0.184.70
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 +111 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28399,21 +28399,35 @@ ${transcript}`
|
|
|
28399
28399
|
thinking;
|
|
28400
28400
|
/** Abort signal — set by the runner so /stop can cancel in-flight requests */
|
|
28401
28401
|
_abortSignal = null;
|
|
28402
|
+
/** Multi-key pool — round-robin rotation per request for load distribution */
|
|
28403
|
+
_keyPool = [];
|
|
28404
|
+
_keyIndex = 0;
|
|
28402
28405
|
constructor(baseUrl, model, apiKey, thinking) {
|
|
28403
28406
|
this.baseUrl = normalizeBaseUrl(baseUrl);
|
|
28404
28407
|
this.model = model;
|
|
28405
28408
|
this.apiKey = apiKey ?? "";
|
|
28406
28409
|
this.thinking = thinking ?? true;
|
|
28407
28410
|
}
|
|
28411
|
+
/** Set multiple API keys for round-robin rotation per request */
|
|
28412
|
+
setKeyPool(keys) {
|
|
28413
|
+
this._keyPool = keys.filter((k) => k.length > 0);
|
|
28414
|
+
this._keyIndex = 0;
|
|
28415
|
+
}
|
|
28408
28416
|
/** Set the abort signal from the runner (called at run start) */
|
|
28409
28417
|
setAbortSignal(signal) {
|
|
28410
28418
|
this._abortSignal = signal;
|
|
28411
28419
|
}
|
|
28412
|
-
/** Build auth headers — all providers use standard Bearer token auth.
|
|
28420
|
+
/** Build auth headers — all providers use standard Bearer token auth.
|
|
28421
|
+
* When a key pool is set, round-robins through keys per request. */
|
|
28413
28422
|
authHeaders() {
|
|
28414
28423
|
const headers = { "Content-Type": "application/json" };
|
|
28415
|
-
|
|
28416
|
-
|
|
28424
|
+
let key = this.apiKey;
|
|
28425
|
+
if (this._keyPool.length > 0) {
|
|
28426
|
+
key = this._keyPool[this._keyIndex % this._keyPool.length];
|
|
28427
|
+
this._keyIndex++;
|
|
28428
|
+
}
|
|
28429
|
+
if (key) {
|
|
28430
|
+
headers["Authorization"] = `Bearer ${key}`;
|
|
28417
28431
|
}
|
|
28418
28432
|
return headers;
|
|
28419
28433
|
}
|
|
@@ -49969,6 +49983,85 @@ async function handleEndpoint(arg, ctx, local = false) {
|
|
|
49969
49983
|
await handleSponsoredEndpoint(ctx, local);
|
|
49970
49984
|
return;
|
|
49971
49985
|
}
|
|
49986
|
+
if (arg.startsWith("add ")) {
|
|
49987
|
+
const addArg = arg.slice(4).replace(/\u2014/g, "--").replace(/\u2013/g, "--");
|
|
49988
|
+
const addParts = addArg.split(/\s+/);
|
|
49989
|
+
const addUrl = addParts[0];
|
|
49990
|
+
const addAuthIdx = addParts.indexOf("--auth") !== -1 ? addParts.indexOf("--auth") : addParts.indexOf("-auth");
|
|
49991
|
+
const addKey = addAuthIdx !== -1 && addParts[addAuthIdx + 1] ? addParts[addAuthIdx + 1] : "";
|
|
49992
|
+
if (!addKey) {
|
|
49993
|
+
renderError("Usage: /endpoint add <url> --auth <key>");
|
|
49994
|
+
return;
|
|
49995
|
+
}
|
|
49996
|
+
const normalizedAddUrl = normalizeBaseUrl(addUrl);
|
|
49997
|
+
const suffix = addKey.slice(-4);
|
|
49998
|
+
const provider2 = detectProvider(addUrl);
|
|
49999
|
+
const settings = resolveSettings(ctx.repoRoot);
|
|
50000
|
+
const pool = settings.endpointKeys ?? [];
|
|
50001
|
+
if (pool.some((k) => k.suffix === suffix)) {
|
|
50002
|
+
renderWarning(`Key ending ...${suffix} is already in the pool.`);
|
|
50003
|
+
return;
|
|
50004
|
+
}
|
|
50005
|
+
pool.push({ key: addKey, suffix });
|
|
50006
|
+
const backendType2 = provider2.id === "ollama" ? "ollama" : "vllm";
|
|
50007
|
+
ctx.setEndpoint(normalizedAddUrl, backendType2, addKey);
|
|
50008
|
+
setConfigValue("backendUrl", normalizedAddUrl);
|
|
50009
|
+
setConfigValue("backendType", backendType2);
|
|
50010
|
+
setConfigValue("apiKey", addKey);
|
|
50011
|
+
ctx.saveSettings({ backendUrl: normalizedAddUrl, backendType: backendType2, apiKey: addKey, endpointKeys: pool });
|
|
50012
|
+
saveGlobalSettings({ endpointKeys: pool });
|
|
50013
|
+
if (ctx.setKeyPool)
|
|
50014
|
+
ctx.setKeyPool(pool.map((k) => k.key));
|
|
50015
|
+
recordUsage("endpoint", normalizedAddUrl, {
|
|
50016
|
+
meta: { provider: provider2.label, backendType: backendType2, authHint: addKey.slice(0, 4) + "...", authKey: addKey }
|
|
50017
|
+
});
|
|
50018
|
+
renderInfo(`Added key ...${suffix} to pool (${pool.length} key${pool.length > 1 ? "s" : ""} total)`);
|
|
50019
|
+
for (const k of pool) {
|
|
50020
|
+
process.stdout.write(` ${c2.dim("\u25CF")} ${provider2.label}-${k.suffix} ${c2.dim(k.key.slice(0, 4) + "..." + k.key.slice(-4))}
|
|
50021
|
+
`);
|
|
50022
|
+
}
|
|
50023
|
+
process.stdout.write("\n");
|
|
50024
|
+
return;
|
|
50025
|
+
}
|
|
50026
|
+
if (arg === "keys" || arg === "pool") {
|
|
50027
|
+
const settings = resolveSettings(ctx.repoRoot);
|
|
50028
|
+
const pool = settings.endpointKeys ?? [];
|
|
50029
|
+
if (pool.length === 0) {
|
|
50030
|
+
renderInfo("No key pool configured. Use /endpoint add <url> --auth <key> to add keys.");
|
|
50031
|
+
return;
|
|
50032
|
+
}
|
|
50033
|
+
const provider2 = detectProvider(ctx.config.backendUrl);
|
|
50034
|
+
renderInfo(`Key pool for ${c2.bold(ctx.config.backendUrl)} (${pool.length} key${pool.length > 1 ? "s" : ""}):`);
|
|
50035
|
+
for (const k of pool) {
|
|
50036
|
+
process.stdout.write(` ${c2.green("\u25CF")} ${provider2.label}-${k.suffix} ${c2.dim(k.key.slice(0, 4) + "..." + k.key.slice(-4))}
|
|
50037
|
+
`);
|
|
50038
|
+
}
|
|
50039
|
+
process.stdout.write(`
|
|
50040
|
+
${c2.dim("Remove: /endpoint remove <suffix>")}
|
|
50041
|
+
|
|
50042
|
+
`);
|
|
50043
|
+
return;
|
|
50044
|
+
}
|
|
50045
|
+
if (arg.startsWith("remove ") || arg.startsWith("rm ")) {
|
|
50046
|
+
const suffix = arg.split(/\s+/)[1];
|
|
50047
|
+
const settings = resolveSettings(ctx.repoRoot);
|
|
50048
|
+
const pool = settings.endpointKeys ?? [];
|
|
50049
|
+
const idx = pool.findIndex((k) => k.suffix === suffix);
|
|
50050
|
+
if (idx === -1) {
|
|
50051
|
+
renderError(`No key with suffix "${suffix}" in the pool.`);
|
|
50052
|
+
return;
|
|
50053
|
+
}
|
|
50054
|
+
pool.splice(idx, 1);
|
|
50055
|
+
ctx.saveSettings({ endpointKeys: pool });
|
|
50056
|
+
saveGlobalSettings({ endpointKeys: pool });
|
|
50057
|
+
if (ctx.setKeyPool)
|
|
50058
|
+
ctx.setKeyPool(pool.map((k) => k.key));
|
|
50059
|
+
renderInfo(`Removed key ...${suffix} from pool (${pool.length} remaining).`);
|
|
50060
|
+
if (pool.length === 0) {
|
|
50061
|
+
renderInfo("Pool empty \u2014 using single API key from config.");
|
|
50062
|
+
}
|
|
50063
|
+
return;
|
|
50064
|
+
}
|
|
49972
50065
|
const normalizedArg = arg.replace(/\u2014/g, "--").replace(/\u2013/g, "--");
|
|
49973
50066
|
const parts = normalizedArg.split(/\s+/);
|
|
49974
50067
|
const url = parts[0];
|
|
@@ -64049,6 +64142,10 @@ ${lines.join("\n")}
|
|
|
64049
64142
|
backend = new NexusAgenticBackend(sendFn, config.model, targetPeer, config.apiKey, thinkingEnabled);
|
|
64050
64143
|
} else {
|
|
64051
64144
|
backend = new OllamaAgenticBackend(config.backendUrl, config.model, config.apiKey, thinkingEnabled);
|
|
64145
|
+
const poolKeys = config._keyPool;
|
|
64146
|
+
if (poolKeys && poolKeys.length > 0 && backend instanceof OllamaAgenticBackend) {
|
|
64147
|
+
backend.setKeyPool(poolKeys);
|
|
64148
|
+
}
|
|
64052
64149
|
}
|
|
64053
64150
|
try {
|
|
64054
64151
|
const endpointHistory = loadUsageHistory("endpoint", repoRoot);
|
|
@@ -64934,6 +65031,9 @@ async function startInteractive(config, repoPath) {
|
|
|
64934
65031
|
}
|
|
64935
65032
|
if (savedSettings.apiKey)
|
|
64936
65033
|
config = { ...config, apiKey: savedSettings.apiKey };
|
|
65034
|
+
if (savedSettings.endpointKeys && savedSettings.endpointKeys.length > 0) {
|
|
65035
|
+
config._keyPool = savedSettings.endpointKeys.map((k) => k.key);
|
|
65036
|
+
}
|
|
64937
65037
|
if (savedSettings.verbose !== void 0)
|
|
64938
65038
|
config = { ...config, verbose: savedSettings.verbose };
|
|
64939
65039
|
if (savedSettings.maxRetries !== void 0)
|
|
@@ -65982,6 +66082,14 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
65982
66082
|
statusBar.stopRemoteMetricsPolling();
|
|
65983
66083
|
}
|
|
65984
66084
|
},
|
|
66085
|
+
setKeyPool(keys) {
|
|
66086
|
+
if (activeTask) {
|
|
66087
|
+
const backend = activeTask.runner._backend;
|
|
66088
|
+
if (backend?.setKeyPool)
|
|
66089
|
+
backend.setKeyPool(keys);
|
|
66090
|
+
}
|
|
66091
|
+
currentConfig._keyPool = keys;
|
|
66092
|
+
},
|
|
65985
66093
|
clearScreen() {
|
|
65986
66094
|
if (isNeovimActive()) {
|
|
65987
66095
|
writeToNeovimOutput("[screen cleared]\n");
|
package/package.json
CHANGED