open-agents-ai 0.187.367 → 0.187.369
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 +154 -102
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -544273,77 +544273,84 @@ async function handleSlashCommand(input, ctx3) {
|
|
|
544273
544273
|
await showColorMenu(ctx3);
|
|
544274
544274
|
return "handled";
|
|
544275
544275
|
}
|
|
544276
|
-
case "apikey":
|
|
544277
|
-
|
|
544278
|
-
|
|
544279
|
-
|
|
544280
|
-
|
|
544281
|
-
|
|
544282
|
-
|
|
544283
|
-
|
|
544284
|
-
|
|
544285
|
-
|
|
544286
|
-
|
|
544287
|
-
|
|
544288
|
-
|
|
544289
|
-
if (existsSync91(p2)) key = readFileSync72(p2, "utf8").trim();
|
|
544290
|
-
} catch {
|
|
544291
|
-
}
|
|
544276
|
+
case "apikey":
|
|
544277
|
+
case "key": {
|
|
544278
|
+
const apiKeyHandler = async ({ arg: a2 }) => {
|
|
544279
|
+
const action = (a2 || "show").trim().toLowerCase();
|
|
544280
|
+
let key = process.env["OA_API_KEY"] || "";
|
|
544281
|
+
if (!key) {
|
|
544282
|
+
try {
|
|
544283
|
+
const { homedir: homedir41 } = await import("node:os");
|
|
544284
|
+
const { readFileSync: readFileSync72, existsSync: existsSync91 } = await import("node:fs");
|
|
544285
|
+
const { join: join110 } = await import("node:path");
|
|
544286
|
+
const p2 = join110(homedir41(), ".open-agents", "api.key");
|
|
544287
|
+
if (existsSync91(p2)) key = readFileSync72(p2, "utf8").trim();
|
|
544288
|
+
} catch {
|
|
544292
544289
|
}
|
|
544293
|
-
|
|
544294
|
-
|
|
544295
|
-
|
|
544296
|
-
|
|
544297
|
-
}
|
|
544298
|
-
renderInfo2(`API key: ${c3.bold(c3.yellow(key))}`);
|
|
544299
|
-
renderInfo2("Use Authorization: Bearer <key> or paste in the Web UI key modal.");
|
|
544290
|
+
}
|
|
544291
|
+
if (action === "show") {
|
|
544292
|
+
if (!key) {
|
|
544293
|
+
renderWarning2("No API key set. Use /access any to generate one.");
|
|
544300
544294
|
return "handled";
|
|
544301
544295
|
}
|
|
544302
|
-
|
|
544303
|
-
|
|
544304
|
-
|
|
544305
|
-
|
|
544306
|
-
|
|
544307
|
-
|
|
544308
|
-
|
|
544309
|
-
const tryCmd = (cmd2, args) => spawnSync6(cmd2, args, { input: key, encoding: "utf8" });
|
|
544310
|
-
let ok2 = false;
|
|
544311
|
-
if (process.platform === "darwin") {
|
|
544312
|
-
ok2 = tryCmd("pbcopy", []).status === 0;
|
|
544313
|
-
} else if (process.platform === "win32") {
|
|
544314
|
-
ok2 = tryCmd("clip", []).status === 0;
|
|
544315
|
-
} else {
|
|
544316
|
-
ok2 = tryCmd("wl-copy", []).status === 0 || tryCmd("xclip", ["-selection", "clipboard"]).status === 0;
|
|
544317
|
-
}
|
|
544318
|
-
renderInfo2(ok2 ? "Copied API key to clipboard." : "Copy failed — printed above, select to copy.");
|
|
544319
|
-
} catch {
|
|
544320
|
-
renderInfo2("Copy failed — printed above, select to copy.");
|
|
544321
|
-
}
|
|
544296
|
+
renderInfo2(`API key: ${c3.bold(c3.yellow(key))}`);
|
|
544297
|
+
renderInfo2("Use Authorization: Bearer <key> or paste in the Web UI key modal.");
|
|
544298
|
+
return "handled";
|
|
544299
|
+
}
|
|
544300
|
+
if (action === "copy") {
|
|
544301
|
+
if (!key) {
|
|
544302
|
+
renderWarning2("No API key set. Use /access any to generate one.");
|
|
544322
544303
|
return "handled";
|
|
544323
544304
|
}
|
|
544324
|
-
|
|
544325
|
-
|
|
544326
|
-
|
|
544327
|
-
|
|
544328
|
-
|
|
544329
|
-
|
|
544330
|
-
|
|
544331
|
-
|
|
544332
|
-
|
|
544333
|
-
|
|
544334
|
-
writeFileSync51(join110(dir, "api.key"), newKey + "\n", "utf8");
|
|
544335
|
-
renderInfo2(`New API key: ${c3.bold(c3.yellow(newKey))}`);
|
|
544336
|
-
renderInfo2("Restart the daemon to apply if needed. Use /access any to restart quickly.");
|
|
544337
|
-
} catch (e2) {
|
|
544338
|
-
renderError2(`Failed to rotate key: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
544305
|
+
try {
|
|
544306
|
+
const { spawnSync: spawnSync6 } = await import("node:child_process");
|
|
544307
|
+
const tryCmd = (cmd2, args) => spawnSync6(cmd2, args, { input: key, encoding: "utf8" });
|
|
544308
|
+
let ok2 = false;
|
|
544309
|
+
if (process.platform === "darwin") {
|
|
544310
|
+
ok2 = tryCmd("pbcopy", []).status === 0;
|
|
544311
|
+
} else if (process.platform === "win32") {
|
|
544312
|
+
ok2 = tryCmd("clip", []).status === 0;
|
|
544313
|
+
} else {
|
|
544314
|
+
ok2 = tryCmd("wl-copy", []).status === 0 || tryCmd("xclip", ["-selection", "clipboard"]).status === 0;
|
|
544339
544315
|
}
|
|
544340
|
-
|
|
544316
|
+
renderInfo2(ok2 ? "Copied API key to clipboard." : "Copy failed — printed above, select to copy.");
|
|
544317
|
+
} catch {
|
|
544318
|
+
renderInfo2("Copy failed — printed above, select to copy.");
|
|
544319
|
+
}
|
|
544320
|
+
return "handled";
|
|
544321
|
+
}
|
|
544322
|
+
if (action === "new") {
|
|
544323
|
+
try {
|
|
544324
|
+
const { randomBytes: randomBytes23 } = await import("node:crypto");
|
|
544325
|
+
const { homedir: homedir41 } = await import("node:os");
|
|
544326
|
+
const { mkdirSync: mkdirSync58, writeFileSync: writeFileSync51 } = await import("node:fs");
|
|
544327
|
+
const { join: join110 } = await import("node:path");
|
|
544328
|
+
const newKey = randomBytes23(16).toString("hex");
|
|
544329
|
+
process.env["OA_API_KEY"] = newKey;
|
|
544330
|
+
const dir = join110(homedir41(), ".open-agents");
|
|
544331
|
+
mkdirSync58(dir, { recursive: true });
|
|
544332
|
+
writeFileSync51(join110(dir, "api.key"), newKey + "\n", "utf8");
|
|
544333
|
+
renderInfo2(`New API key: ${c3.bold(c3.yellow(newKey))}`);
|
|
544334
|
+
renderInfo2("Restart the daemon to apply if needed. Use /access any to restart quickly.");
|
|
544335
|
+
} catch (e2) {
|
|
544336
|
+
renderError2(`Failed to rotate key: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
544341
544337
|
}
|
|
544342
|
-
renderInfo2("Usage: /apikey [show|copy|new]");
|
|
544343
544338
|
return "handled";
|
|
544344
544339
|
}
|
|
544340
|
+
renderInfo2("Usage: /apikey [show|copy|new] aliases: /key");
|
|
544341
|
+
return "handled";
|
|
544342
|
+
};
|
|
544343
|
+
registerSlashCommand({
|
|
544344
|
+
name: "apikey",
|
|
544345
|
+
description: "Show/copy/rotate API key (show|copy|new)",
|
|
544346
|
+
handler: async (opts) => apiKeyHandler({ arg: opts.arg })
|
|
544345
544347
|
});
|
|
544346
|
-
|
|
544348
|
+
registerSlashCommand({
|
|
544349
|
+
name: "key",
|
|
544350
|
+
description: "Alias for /apikey",
|
|
544351
|
+
handler: async (opts) => apiKeyHandler({ arg: opts.arg })
|
|
544352
|
+
});
|
|
544353
|
+
return apiKeyHandler({ arg });
|
|
544347
544354
|
}
|
|
544348
544355
|
case "sessions":
|
|
544349
544356
|
case "session": {
|
|
@@ -551406,16 +551413,17 @@ var init_commands = __esm({
|
|
|
551406
551413
|
if (findSlashCommand("access")) return;
|
|
551407
551414
|
registerSlashCommand({
|
|
551408
551415
|
name: "access",
|
|
551409
|
-
description: "Show/set OA_ACCESS (loopback|lan|any)
|
|
551416
|
+
description: "Show/set OA_ACCESS (loopback|lan|any). Live-mutates the daemon; auto-generates API key on 'any'.",
|
|
551410
551417
|
handler: async ({ arg, hasLocal, ctx: ctx3 }) => {
|
|
551411
551418
|
const normalize2 = (v) => v.toLowerCase().trim();
|
|
551419
|
+
const normalizeMode = (v) => v === "all" ? "any" : v;
|
|
551412
551420
|
const curAccess = normalize2(process.env["OA_ACCESS"] ?? "");
|
|
551413
551421
|
const curHost = process.env["OA_HOST"] ?? "0.0.0.0:11435";
|
|
551414
551422
|
const allowed = /* @__PURE__ */ new Set(["loopback", "lan", "any"]);
|
|
551415
|
-
const val = normalize2(arg);
|
|
551423
|
+
const val = normalizeMode(normalize2(arg));
|
|
551416
551424
|
if (!val) {
|
|
551417
551425
|
renderInfo2(`Access: ${curAccess || "(default)"} Host: ${curHost}`);
|
|
551418
|
-
renderInfo2("Use /access loopback|lan|any to change
|
|
551426
|
+
renderInfo2("Use /access loopback|lan|any to change.\n");
|
|
551419
551427
|
return "handled";
|
|
551420
551428
|
}
|
|
551421
551429
|
if (!allowed.has(val)) {
|
|
@@ -551423,16 +551431,90 @@ var init_commands = __esm({
|
|
|
551423
551431
|
return "handled";
|
|
551424
551432
|
}
|
|
551425
551433
|
process.env["OA_ACCESS"] = val;
|
|
551434
|
+
if (val === "any" && !process.env["OA_API_KEY"]) {
|
|
551435
|
+
try {
|
|
551436
|
+
const { randomBytes: randomBytes23 } = await import("node:crypto");
|
|
551437
|
+
const { homedir: homedir41 } = await import("node:os");
|
|
551438
|
+
const { mkdirSync: mkdirSync58, writeFileSync: writeFileSync51 } = await import("node:fs");
|
|
551439
|
+
const { join: join110 } = await import("node:path");
|
|
551440
|
+
const apiKey = randomBytes23(16).toString("hex");
|
|
551441
|
+
process.env["OA_API_KEY"] = apiKey;
|
|
551442
|
+
const dir = join110(homedir41(), ".open-agents");
|
|
551443
|
+
mkdirSync58(dir, { recursive: true });
|
|
551444
|
+
writeFileSync51(join110(dir, "api.key"), apiKey + "\n", "utf8");
|
|
551445
|
+
renderInfo2(`Generated API key: ${c3.bold(c3.yellow(apiKey))}`);
|
|
551446
|
+
renderInfo2("Use Authorization: Bearer <key> or click 'key' in the Web UI header to paste it.");
|
|
551447
|
+
} catch (e2) {
|
|
551448
|
+
renderWarning2(`Failed to generate API key: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
551449
|
+
}
|
|
551450
|
+
}
|
|
551426
551451
|
if (hasLocal) {
|
|
551427
551452
|
ctx3.saveLocalSettings({ oaAccess: val });
|
|
551428
551453
|
} else {
|
|
551429
551454
|
ctx3.saveSettings({ oaAccess: val });
|
|
551430
551455
|
}
|
|
551431
|
-
const
|
|
551432
|
-
|
|
551433
|
-
|
|
551456
|
+
const port = parseInt(process.env["OA_PORT"] || "11435", 10);
|
|
551457
|
+
try {
|
|
551458
|
+
const { homedir: homedir41 } = await import("node:os");
|
|
551459
|
+
const { mkdirSync: mkdirSync58, writeFileSync: writeFileSync51 } = await import("node:fs");
|
|
551460
|
+
const { join: join110 } = await import("node:path");
|
|
551461
|
+
const dir = join110(homedir41(), ".open-agents");
|
|
551462
|
+
mkdirSync58(dir, { recursive: true });
|
|
551463
|
+
writeFileSync51(join110(dir, "access"), `${val}
|
|
551464
|
+
`, "utf8");
|
|
551465
|
+
} catch {
|
|
551466
|
+
}
|
|
551467
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
551468
|
+
const authHeaders = () => {
|
|
551469
|
+
const token = process.env["OA_API_KEY"] || "";
|
|
551470
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
551471
|
+
};
|
|
551472
|
+
let liveOk = false;
|
|
551473
|
+
try {
|
|
551474
|
+
const resp = await fetch(`${baseUrl}/v1/admin/access`, {
|
|
551475
|
+
method: "POST",
|
|
551476
|
+
headers: { "Content-Type": "application/json", ...authHeaders() },
|
|
551477
|
+
body: JSON.stringify({ mode: val }),
|
|
551478
|
+
signal: AbortSignal.timeout(3e3)
|
|
551479
|
+
});
|
|
551480
|
+
liveOk = resp.ok;
|
|
551481
|
+
} catch {
|
|
551482
|
+
}
|
|
551483
|
+
const readCurrent = async () => {
|
|
551484
|
+
try {
|
|
551485
|
+
const r2 = await fetch(`${baseUrl}/v1/admin/access`, { headers: authHeaders(), signal: AbortSignal.timeout(2e3) });
|
|
551486
|
+
if (!r2.ok) return null;
|
|
551487
|
+
const j = await r2.json();
|
|
551488
|
+
return typeof j.mode === "string" ? j.mode : null;
|
|
551489
|
+
} catch {
|
|
551490
|
+
return null;
|
|
551491
|
+
}
|
|
551492
|
+
};
|
|
551493
|
+
const current = await readCurrent();
|
|
551494
|
+
if (liveOk && current === val) {
|
|
551495
|
+
renderInfo2(`Access policy now '${val}' (live, no restart). Persisted to ~/.open-agents/access.`);
|
|
551496
|
+
return "handled";
|
|
551497
|
+
}
|
|
551498
|
+
renderInfo2(`Live switch did not take effect (daemon reports ${current ?? "unreachable"}). Force-restarting daemon...`);
|
|
551499
|
+
const { forceKillDaemon: forceKillDaemon2, ensureDaemon: ensureDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
|
|
551500
|
+
const killed = await forceKillDaemon2(port);
|
|
551501
|
+
if (killed > 0) renderInfo2(`Force-killed ${killed} process(es) bound to port ${port}.`);
|
|
551434
551502
|
const ok2 = await ensureDaemon2();
|
|
551435
|
-
|
|
551503
|
+
if (!ok2) {
|
|
551504
|
+
renderError2("Failed to start a fresh daemon after force-kill.");
|
|
551505
|
+
return "handled";
|
|
551506
|
+
}
|
|
551507
|
+
let finalMode = null;
|
|
551508
|
+
for (let i2 = 0; i2 < 10; i2++) {
|
|
551509
|
+
finalMode = await readCurrent();
|
|
551510
|
+
if (finalMode) break;
|
|
551511
|
+
await new Promise((r2) => setTimeout(r2, 250));
|
|
551512
|
+
}
|
|
551513
|
+
if (finalMode === val) {
|
|
551514
|
+
renderInfo2(`Access policy now '${val}' (daemon restarted, verified).`);
|
|
551515
|
+
} else {
|
|
551516
|
+
renderWarning2(`Daemon restarted but reports mode='${finalMode ?? "unreachable"}'. Expected '${val}'.`);
|
|
551517
|
+
}
|
|
551436
551518
|
return "handled";
|
|
551437
551519
|
}
|
|
551438
551520
|
});
|
|
@@ -552609,6 +552691,10 @@ var init_render2 = __esm({
|
|
|
552609
552691
|
["/scheduler menu", "Interactive scheduler menu (toggle/kill)"],
|
|
552610
552692
|
["/scheduler list", "List all scheduled tasks and timers"],
|
|
552611
552693
|
["/scheduler kill", "Kill schedulers + active runs (with escalation if needed)"],
|
|
552694
|
+
["/apikey", "Show current API key (for pasting into Web UI / clients)"],
|
|
552695
|
+
["/apikey copy", "Copy the API key to clipboard"],
|
|
552696
|
+
["/apikey new", "Rotate to a new API key (regenerate)"],
|
|
552697
|
+
["/key", "Alias for /apikey"],
|
|
552612
552698
|
["/codegraph", "Code-graph snapshot: stats, top files, recent activity"],
|
|
552613
552699
|
["/codegraph watch [N]", "Subscribe to live code-graph events for N seconds (default 30)"],
|
|
552614
552700
|
["/cg", "Alias for /codegraph"],
|
|
@@ -580185,40 +580271,6 @@ async function startInteractive(config, repoPath) {
|
|
|
580185
580271
|
const repoRoot = resolve36(repoPath ?? cwd());
|
|
580186
580272
|
try {
|
|
580187
580273
|
const { registerSlashCommand: registerSlashCommand2 } = await Promise.resolve().then(() => (init_commands(), commands_exports));
|
|
580188
|
-
registerSlashCommand2({
|
|
580189
|
-
name: "access",
|
|
580190
|
-
description: "Show/set OA_ACCESS (loopback|lan|any) and restart daemon",
|
|
580191
|
-
handler: async ({ arg, hasLocal, ctx: ctx3 }) => {
|
|
580192
|
-
const normalize2 = (v) => v.toLowerCase().trim();
|
|
580193
|
-
const curAccess = normalize2(process.env["OA_ACCESS"] ?? "");
|
|
580194
|
-
const curHost = process.env["OA_HOST"] ?? "0.0.0.0:11435";
|
|
580195
|
-
const allowed = /* @__PURE__ */ new Set(["loopback", "lan", "any"]);
|
|
580196
|
-
const val = normalize2(arg || "");
|
|
580197
|
-
if (!val) {
|
|
580198
|
-
process.stdout.write(`
|
|
580199
|
-
Access: ${curAccess || "(default)"} Host: ${curHost}
|
|
580200
|
-
|
|
580201
|
-
`);
|
|
580202
|
-
return "handled";
|
|
580203
|
-
}
|
|
580204
|
-
if (!allowed.has(val)) {
|
|
580205
|
-
process.stdout.write("\n Invalid access mode. Use: loopback, lan, or any.\n\n");
|
|
580206
|
-
return "handled";
|
|
580207
|
-
}
|
|
580208
|
-
process.env["OA_ACCESS"] = val;
|
|
580209
|
-
if (hasLocal) {
|
|
580210
|
-
ctx3.saveLocalSettings({ oaAccess: val });
|
|
580211
|
-
} else {
|
|
580212
|
-
ctx3.saveSettings({ oaAccess: val });
|
|
580213
|
-
}
|
|
580214
|
-
const { stopDaemon: stopDaemon2, ensureDaemon: ensureDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
|
|
580215
|
-
stopDaemon2();
|
|
580216
|
-
await new Promise((r2) => setTimeout(r2, 800));
|
|
580217
|
-
const ok2 = await ensureDaemon2();
|
|
580218
|
-
process.stdout.write(ok2 ? "\n Daemon restarted to apply access policy.\n\n" : "\n Failed to restart daemon.\n\n");
|
|
580219
|
-
return "handled";
|
|
580220
|
-
}
|
|
580221
|
-
});
|
|
580222
580274
|
registerSlashCommand2({
|
|
580223
580275
|
name: "host",
|
|
580224
580276
|
description: "Set OA_HOST host:port and restart daemon",
|
package/package.json
CHANGED