open-agents-ai 0.187.578 → 0.187.579
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 +125 -53
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ function parseBackendType(value2) {
|
|
|
65
65
|
return VALID_BACKEND_TYPES.has(value2) ? value2 : void 0;
|
|
66
66
|
}
|
|
67
67
|
function loadConfigFile() {
|
|
68
|
-
const configPath2 = join(
|
|
68
|
+
const configPath2 = join(openAgentsConfigDir(), "config.json");
|
|
69
69
|
if (!existsSync(configPath2)) return {};
|
|
70
70
|
try {
|
|
71
71
|
const raw = readFileSync(configPath2, "utf8");
|
|
@@ -110,13 +110,16 @@ function mergeConfig(base3, overrides) {
|
|
|
110
110
|
return { ...base3, ...overrides };
|
|
111
111
|
}
|
|
112
112
|
function setConfigValue(key, value2) {
|
|
113
|
-
const dir =
|
|
113
|
+
const dir = openAgentsConfigDir();
|
|
114
114
|
mkdirSync(dir, { recursive: true });
|
|
115
115
|
const configPath2 = join(dir, "config.json");
|
|
116
116
|
const existing = loadConfigFile();
|
|
117
117
|
existing[key] = coerceConfigValue(key, value2);
|
|
118
118
|
writeFileSync(configPath2, JSON.stringify(existing, null, 2) + "\n", { encoding: "utf8", mode: 384 });
|
|
119
119
|
}
|
|
120
|
+
function openAgentsConfigDir() {
|
|
121
|
+
return join(process.env["OPEN_AGENTS_CONFIG_HOME"] ?? homedir(), ".open-agents");
|
|
122
|
+
}
|
|
120
123
|
function coerceConfigValue(key, value2) {
|
|
121
124
|
const intKeys = /* @__PURE__ */ new Set(["maxRetries", "timeoutMs"]);
|
|
122
125
|
const boolKeys = /* @__PURE__ */ new Set(["dryRun", "verbose"]);
|
|
@@ -594439,6 +594442,18 @@ async function runCommand(input, opts) {
|
|
|
594439
594442
|
const argsStr = rest.join(" ");
|
|
594440
594443
|
const release = await acquireLock2();
|
|
594441
594444
|
try {
|
|
594445
|
+
const quick2 = buildNonInteractiveSummary(cmdName, argsStr, opts?.config);
|
|
594446
|
+
if (quick2) {
|
|
594447
|
+
return {
|
|
594448
|
+
ok: true,
|
|
594449
|
+
command: cmdName,
|
|
594450
|
+
args: argsStr,
|
|
594451
|
+
kind: "handled",
|
|
594452
|
+
output: quick2,
|
|
594453
|
+
ansi: quick2,
|
|
594454
|
+
durationMs: Date.now() - start2
|
|
594455
|
+
};
|
|
594456
|
+
}
|
|
594442
594457
|
const buf = [];
|
|
594443
594458
|
setContentWriteHook({
|
|
594444
594459
|
begin: () => {
|
|
@@ -594489,6 +594504,43 @@ async function runCommand(input, opts) {
|
|
|
594489
594504
|
release();
|
|
594490
594505
|
}
|
|
594491
594506
|
}
|
|
594507
|
+
function buildNonInteractiveSummary(cmdName, _args, config) {
|
|
594508
|
+
const cfg = config ?? loadConfig();
|
|
594509
|
+
if (cmdName === "setup" || cmdName === "wizard") {
|
|
594510
|
+
return [
|
|
594511
|
+
"open-agents setup",
|
|
594512
|
+
"",
|
|
594513
|
+
"The setup wizard is an interactive terminal flow. In the GUI command bridge it is summarized instead of opening prompts, installing software, starting Ollama, or pulling models.",
|
|
594514
|
+
"",
|
|
594515
|
+
`Current backend: ${cfg.backendType ?? "ollama"}`,
|
|
594516
|
+
`Current endpoint: ${cfg.backendUrl ?? "http://127.0.0.1:11434"}`,
|
|
594517
|
+
`Current model: ${cfg.model ?? "qwen3.5:latest"}`,
|
|
594518
|
+
"",
|
|
594519
|
+
"Available non-interactive setup actions:",
|
|
594520
|
+
" /endpoint <url> Set or inspect the inference endpoint.",
|
|
594521
|
+
" /model <name> Set the active model directly.",
|
|
594522
|
+
" /models Show model-selection guidance.",
|
|
594523
|
+
" /config Inspect persisted configuration.",
|
|
594524
|
+
" /doctor Run diagnostics from the terminal if deeper repair is needed.",
|
|
594525
|
+
"",
|
|
594526
|
+
"Open a terminal and run `oa`, then use /setup for the full guided wizard."
|
|
594527
|
+
].join("\n");
|
|
594528
|
+
}
|
|
594529
|
+
if (cmdName === "models") {
|
|
594530
|
+
return [
|
|
594531
|
+
"open-agents models",
|
|
594532
|
+
"",
|
|
594533
|
+
"The model picker is interactive in the TUI. The GUI bridge does not probe remote model endpoints here, so it cannot hang on a stale backend.",
|
|
594534
|
+
"",
|
|
594535
|
+
`Active model: ${cfg.model ?? "qwen3.5:latest"}`,
|
|
594536
|
+
`Endpoint: ${cfg.backendUrl ?? "http://127.0.0.1:11434"}`,
|
|
594537
|
+
`Backend: ${cfg.backendType ?? "ollama"}`,
|
|
594538
|
+
"",
|
|
594539
|
+
"Use /model <name> to set a model directly, /endpoint to switch providers, or open the TUI for the searchable model picker."
|
|
594540
|
+
].join("\n");
|
|
594541
|
+
}
|
|
594542
|
+
return null;
|
|
594543
|
+
}
|
|
594492
594544
|
function acquireLock2() {
|
|
594493
594545
|
let release;
|
|
594494
594546
|
const next = new Promise((res) => {
|
|
@@ -607320,6 +607372,7 @@ async function refreshEndpointRegistry() {
|
|
|
607320
607372
|
type: config.backendType || "ollama",
|
|
607321
607373
|
authKey: config.apiKey
|
|
607322
607374
|
});
|
|
607375
|
+
if (process.env["OA_SKIP_SPONSOR_DISCOVERY"] === "1") return;
|
|
607323
607376
|
try {
|
|
607324
607377
|
const resp = await fetch("https://openagents.nexus/api/v1/sponsors", {
|
|
607325
607378
|
signal: AbortSignal.timeout(5e3)
|
|
@@ -607440,6 +607493,16 @@ function getBackendTimeoutMs(perRequestSeconds) {
|
|
|
607440
607493
|
}
|
|
607441
607494
|
return BACKEND_TIMEOUT_DEFAULT_MS;
|
|
607442
607495
|
}
|
|
607496
|
+
function getModelListTimeoutMs() {
|
|
607497
|
+
const envS = process.env["OA_MODEL_LIST_TIMEOUT_S"];
|
|
607498
|
+
if (envS) {
|
|
607499
|
+
const n2 = parseFloat(envS);
|
|
607500
|
+
if (Number.isFinite(n2) && n2 > 0) {
|
|
607501
|
+
return Math.min(Math.floor(n2 * 1e3), 3e4);
|
|
607502
|
+
}
|
|
607503
|
+
}
|
|
607504
|
+
return MODEL_LIST_TIMEOUT_DEFAULT_MS;
|
|
607505
|
+
}
|
|
607443
607506
|
function recordMetric(method, path11, status) {
|
|
607444
607507
|
const key = `${method}|${path11}|${status}`;
|
|
607445
607508
|
const existing = metrics.requests.get(key);
|
|
@@ -607879,10 +607942,12 @@ function ollamaRequest(ollamaUrl, path11, method, body, timeoutMs) {
|
|
|
607879
607942
|
}
|
|
607880
607943
|
};
|
|
607881
607944
|
const transport = isHttps ? https3 : http5;
|
|
607945
|
+
const _to = getBackendTimeoutMs(timeoutMs ? timeoutMs / 1e3 : void 0);
|
|
607882
607946
|
const proxyReq = transport.request(options2, (proxyRes) => {
|
|
607883
607947
|
const chunks = [];
|
|
607884
607948
|
proxyRes.on("data", (chunk) => chunks.push(chunk));
|
|
607885
607949
|
proxyRes.on("end", () => {
|
|
607950
|
+
clearTimeout(hardTimeout);
|
|
607886
607951
|
resolve43({
|
|
607887
607952
|
status: proxyRes.statusCode ?? 500,
|
|
607888
607953
|
headers: proxyRes.headers,
|
|
@@ -607890,11 +607955,17 @@ function ollamaRequest(ollamaUrl, path11, method, body, timeoutMs) {
|
|
|
607890
607955
|
});
|
|
607891
607956
|
});
|
|
607892
607957
|
});
|
|
607893
|
-
const
|
|
607958
|
+
const hardTimeout = setTimeout(() => {
|
|
607959
|
+
proxyReq.destroy(new Error(`Backend request timeout (${Math.round(_to / 1e3)}s)`));
|
|
607960
|
+
}, _to);
|
|
607961
|
+
hardTimeout.unref();
|
|
607894
607962
|
proxyReq.setTimeout(_to, () => {
|
|
607895
607963
|
proxyReq.destroy(new Error(`Backend request timeout (${Math.round(_to / 1e3)}s)`));
|
|
607896
607964
|
});
|
|
607897
|
-
proxyReq.on("error",
|
|
607965
|
+
proxyReq.on("error", (err) => {
|
|
607966
|
+
clearTimeout(hardTimeout);
|
|
607967
|
+
reject(err);
|
|
607968
|
+
});
|
|
607898
607969
|
if (body) proxyReq.write(body);
|
|
607899
607970
|
proxyReq.end();
|
|
607900
607971
|
});
|
|
@@ -608670,7 +608741,7 @@ async function fetchAggregatedOllamaTags() {
|
|
|
608670
608741
|
try {
|
|
608671
608742
|
const isOllama = ep.type === "ollama";
|
|
608672
608743
|
const path11 = isOllama ? "/api/tags" : "/v1/models";
|
|
608673
|
-
const result = await ollamaRequest(ep.url, path11, "GET");
|
|
608744
|
+
const result = await ollamaRequest(ep.url, path11, "GET", void 0, getModelListTimeoutMs());
|
|
608674
608745
|
if (result.status !== 200) return;
|
|
608675
608746
|
const body = JSON.parse(result.body);
|
|
608676
608747
|
if (isOllama) {
|
|
@@ -608727,6 +608798,10 @@ async function fetchAggregatedOllamaTags() {
|
|
|
608727
608798
|
return out.sort((a2, b) => a2.name.localeCompare(b.name));
|
|
608728
608799
|
}
|
|
608729
608800
|
async function handleApiTags(res) {
|
|
608801
|
+
if (process.env["OA_API_TEST_MODE"] === "1") {
|
|
608802
|
+
jsonResponse(res, 200, { models: [] });
|
|
608803
|
+
return;
|
|
608804
|
+
}
|
|
608730
608805
|
try {
|
|
608731
608806
|
const models = await fetchAggregatedOllamaTags();
|
|
608732
608807
|
jsonResponse(res, 200, { models });
|
|
@@ -611272,8 +611347,16 @@ async function handleRequest(req2, res, ollamaUrl, verbose) {
|
|
|
611272
611347
|
jsonResponse(res, 400, { error: "missing_text" });
|
|
611273
611348
|
return;
|
|
611274
611349
|
}
|
|
611350
|
+
const voiceStatus = getRuntimeStatus();
|
|
611351
|
+
if (!voiceStatus.voiceReady) {
|
|
611352
|
+
jsonResponse(res, 501, {
|
|
611353
|
+
error: "tts_not_ready",
|
|
611354
|
+
message: "Voice synthesis is not ready in the daemon. Warm the voice runtime with POST /v1/voice/start before requesting audio.",
|
|
611355
|
+
state: voiceStatus
|
|
611356
|
+
});
|
|
611357
|
+
return;
|
|
611358
|
+
}
|
|
611275
611359
|
try {
|
|
611276
|
-
await ensureRuntime();
|
|
611277
611360
|
const ve = getVoiceEngine();
|
|
611278
611361
|
let prevModel = null;
|
|
611279
611362
|
if (requestedModel && ve.modelId !== requestedModel) {
|
|
@@ -613510,6 +613593,7 @@ function startApiServer(options2 = {}) {
|
|
|
613510
613593
|
if (options2.host) host = options2.host;
|
|
613511
613594
|
if (options2.port) port = options2.port;
|
|
613512
613595
|
const verbose = options2.verbose ?? false;
|
|
613596
|
+
const apiTestMode = process.env["OA_API_TEST_MODE"] === "1";
|
|
613513
613597
|
const config = loadConfig();
|
|
613514
613598
|
const ollamaUrl = options2.ollamaUrl ?? config.backendUrl;
|
|
613515
613599
|
const cwd4 = process.cwd();
|
|
@@ -613529,31 +613613,37 @@ function startApiServer(options2 = {}) {
|
|
|
613529
613613
|
taskMgr.onEviction((taskId) => {
|
|
613530
613614
|
deleteAgentTaskSidecar(taskId);
|
|
613531
613615
|
});
|
|
613532
|
-
|
|
613533
|
-
|
|
613534
|
-
|
|
613616
|
+
if (!apiTestMode) {
|
|
613617
|
+
restoreAgentTasks(taskMgr).then((report2) => {
|
|
613618
|
+
if (report2.restored > 0) {
|
|
613619
|
+
log22(` task recovery: restored=${report2.restored} re-attached=${report2.reAttached} marked-failed=${report2.markedFailed}
|
|
613535
613620
|
`);
|
|
613536
|
-
|
|
613537
|
-
|
|
613538
|
-
|
|
613539
|
-
|
|
613540
|
-
|
|
613541
|
-
|
|
613542
|
-
|
|
613543
|
-
|
|
613544
|
-
|
|
613621
|
+
}
|
|
613622
|
+
}).catch(() => {
|
|
613623
|
+
});
|
|
613624
|
+
}
|
|
613625
|
+
if (!apiTestMode) {
|
|
613626
|
+
setTimeout(() => {
|
|
613627
|
+
try {
|
|
613628
|
+
purgeOldSidecars(24);
|
|
613629
|
+
} catch {
|
|
613630
|
+
}
|
|
613631
|
+
}, 5e3).unref();
|
|
613632
|
+
}
|
|
613545
613633
|
} catch {
|
|
613546
613634
|
}
|
|
613547
|
-
|
|
613548
|
-
|
|
613549
|
-
|
|
613550
|
-
|
|
613635
|
+
if (!apiTestMode) {
|
|
613636
|
+
try {
|
|
613637
|
+
const report2 = loadPersistedSessions();
|
|
613638
|
+
if (report2.restored > 0 || report2.staleInFlight > 0) {
|
|
613639
|
+
log22(` chat sessions: restored=${report2.restored} stale-in-flight=${report2.staleInFlight}
|
|
613551
613640
|
`);
|
|
613641
|
+
}
|
|
613642
|
+
} catch {
|
|
613552
613643
|
}
|
|
613553
|
-
} catch {
|
|
613554
613644
|
}
|
|
613555
613645
|
setTodoEventPublisher(null);
|
|
613556
|
-
try {
|
|
613646
|
+
if (!apiTestMode) try {
|
|
613557
613647
|
const dir = todoDir();
|
|
613558
613648
|
try {
|
|
613559
613649
|
mkdirSync69(dir, { recursive: true });
|
|
@@ -613630,7 +613720,7 @@ function startApiServer(options2 = {}) {
|
|
|
613630
613720
|
`);
|
|
613631
613721
|
}
|
|
613632
613722
|
const retentionDays = parseInt(process.env["OA_JOB_RETENTION_DAYS"] ?? "30", 10);
|
|
613633
|
-
if (retentionDays > 0) {
|
|
613723
|
+
if (!apiTestMode && retentionDays > 0) {
|
|
613634
613724
|
try {
|
|
613635
613725
|
const jobsDir3 = join129(cwd4, ".oa", "jobs");
|
|
613636
613726
|
if (existsSync113(jobsDir3)) {
|
|
@@ -613681,9 +613771,12 @@ function startApiServer(options2 = {}) {
|
|
|
613681
613771
|
}
|
|
613682
613772
|
let _accessRejected = 0;
|
|
613683
613773
|
const handler = (req2, res) => {
|
|
613774
|
+
const requestId = req2.headers["x-request-id"] || randomUUID16();
|
|
613775
|
+
res.setHeader("X-Request-ID", requestId);
|
|
613776
|
+
res.setHeader("X-API-Version", API_VERSION);
|
|
613684
613777
|
const rawIp = req2.socket?.remoteAddress ?? "";
|
|
613685
613778
|
const hasBearer = typeof req2.headers["authorization"] === "string" && req2.headers["authorization"].startsWith("Bearer ");
|
|
613686
|
-
const anyKeyConfigured = Boolean(
|
|
613779
|
+
const anyKeyConfigured = hasBearer && Boolean(
|
|
613687
613780
|
process.env["OA_API_KEY"] || process.env["OA_API_KEYS"] || runtimeKeysExist()
|
|
613688
613781
|
);
|
|
613689
613782
|
if (!isAllowedIP(rawIp, runtimeAccessMode) && !(hasBearer && anyKeyConfigured)) {
|
|
@@ -613770,10 +613863,6 @@ function startApiServer(options2 = {}) {
|
|
|
613770
613863
|
handleEntitiesList(req2, res);
|
|
613771
613864
|
return;
|
|
613772
613865
|
}
|
|
613773
|
-
if (req2.method === "POST" && url.pathname === "/v1/memory/search") {
|
|
613774
|
-
handleMemorySearch2(req2, res);
|
|
613775
|
-
return;
|
|
613776
|
-
}
|
|
613777
613866
|
} catch {
|
|
613778
613867
|
}
|
|
613779
613868
|
handleRequest(req2, res, ollamaUrl, verbose).catch((err) => {
|
|
@@ -614024,6 +614113,10 @@ function startApiServer(options2 = {}) {
|
|
|
614024
614113
|
`);
|
|
614025
614114
|
log22(` Primary: ${config.backendUrl} (${config.backendType || "ollama"})
|
|
614026
614115
|
`);
|
|
614116
|
+
if (apiTestMode) {
|
|
614117
|
+
void refreshEndpointRegistry();
|
|
614118
|
+
return;
|
|
614119
|
+
}
|
|
614027
614120
|
try {
|
|
614028
614121
|
const { writeFileSync: writeFileSync67, mkdirSync: mkdirSync74, existsSync: _exists, readFileSync: _rfs } = require3("node:fs");
|
|
614029
614122
|
const { join: _join } = require3("node:path");
|
|
@@ -614451,28 +614544,6 @@ async function handleEntitiesList(req2, res) {
|
|
|
614451
614544
|
jsonResponse(res, 500, { error: "server_error", message: err instanceof Error ? err.message : String(err) });
|
|
614452
614545
|
}
|
|
614453
614546
|
}
|
|
614454
|
-
async function handleMemorySearch2(req2, res) {
|
|
614455
|
-
try {
|
|
614456
|
-
const body = await parseJsonBody(req2);
|
|
614457
|
-
if (!body || typeof body !== "object") {
|
|
614458
|
-
jsonResponse(res, 400, { error: "bad_request" });
|
|
614459
|
-
return;
|
|
614460
|
-
}
|
|
614461
|
-
const b = body;
|
|
614462
|
-
const query = String(b.query || "");
|
|
614463
|
-
const modality = b.modality ? String(b.modality) : void 0;
|
|
614464
|
-
const limit = b.limit ? Math.max(1, Math.min(200, parseInt(String(b.limit), 10))) : 20;
|
|
614465
|
-
const qEmb = Array.isArray(b.query_embedding) ? new Float32Array(b.query_embedding) : null;
|
|
614466
|
-
const wLex = typeof b.lexical_weight === "number" ? b.lexical_weight : 1;
|
|
614467
|
-
const wEmb = typeof b.embedding_weight === "number" ? b.embedding_weight : 1;
|
|
614468
|
-
const { EpisodeStore: EpisodeStore3 } = await Promise.resolve().then(() => (init_dist7(), dist_exports2));
|
|
614469
|
-
const epStore = new EpisodeStore3(join129(process.cwd(), ".oa", "memory.db"));
|
|
614470
|
-
const results = epStore.search({ query, modality, limit }, { queryEmbedding: qEmb, lexicalWeight: wLex, embeddingWeight: wEmb });
|
|
614471
|
-
jsonResponse(res, 200, { object: "list", data: results.map((e2) => ({ id: e2.id, modality: e2.modality, content: e2.content, timestamp: e2.timestamp })) });
|
|
614472
|
-
} catch (err) {
|
|
614473
|
-
jsonResponse(res, 500, { error: "server_error", message: err instanceof Error ? err.message : String(err) });
|
|
614474
|
-
}
|
|
614475
|
-
}
|
|
614476
614547
|
async function apiServeCommand(opts, config) {
|
|
614477
614548
|
const server2 = startApiServer({
|
|
614478
614549
|
port: opts.port,
|
|
@@ -614533,7 +614604,7 @@ function setTimerEnabled(name10, enabled2) {
|
|
|
614533
614604
|
return false;
|
|
614534
614605
|
}
|
|
614535
614606
|
}
|
|
614536
|
-
var require3, endpointRegistry, modelRouteMap, endpointUsage, _lastEndpointDiagnostics, BACKEND_TIMEOUT_DEFAULT_MS, BACKEND_TIMEOUT_MAX_MS, metrics, startedAt, runningProcesses, perKeyUsage, CRON_MARKER2;
|
|
614607
|
+
var require3, endpointRegistry, modelRouteMap, endpointUsage, _lastEndpointDiagnostics, BACKEND_TIMEOUT_DEFAULT_MS, BACKEND_TIMEOUT_MAX_MS, MODEL_LIST_TIMEOUT_DEFAULT_MS, metrics, startedAt, runningProcesses, perKeyUsage, CRON_MARKER2;
|
|
614537
614608
|
var init_serve = __esm({
|
|
614538
614609
|
"packages/cli/src/api/serve.ts"() {
|
|
614539
614610
|
"use strict";
|
|
@@ -614569,6 +614640,7 @@ var init_serve = __esm({
|
|
|
614569
614640
|
_lastEndpointDiagnostics = [];
|
|
614570
614641
|
BACKEND_TIMEOUT_DEFAULT_MS = 12e4;
|
|
614571
614642
|
BACKEND_TIMEOUT_MAX_MS = 36e5;
|
|
614643
|
+
MODEL_LIST_TIMEOUT_DEFAULT_MS = 1500;
|
|
614572
614644
|
metrics = {
|
|
614573
614645
|
requests: /* @__PURE__ */ new Map(),
|
|
614574
614646
|
totalTokensIn: 0,
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-agents-ai",
|
|
3
|
-
"version": "0.187.
|
|
3
|
+
"version": "0.187.579",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "open-agents-ai",
|
|
9
|
-
"version": "0.187.
|
|
9
|
+
"version": "0.187.579",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "CC-BY-NC-4.0",
|
|
12
12
|
"dependencies": {
|
package/package.json
CHANGED