@livx.cc/agentx 0.96.1 → 0.96.3

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/cli.d.ts CHANGED
@@ -142,6 +142,7 @@ interface Args {
142
142
  harden?: boolean;
143
143
  hardenNet?: boolean;
144
144
  worktree?: string;
145
+ updateCheck?: boolean;
145
146
  }
146
147
  declare function parseArgs(argv: string[]): Args;
147
148
  /** Hooks that render tool activity to stderr: a preToolUse header, and for edits a colorized diff.
package/dist/cli.js CHANGED
@@ -10138,7 +10138,7 @@ function parseReasoning(raw) {
10138
10138
  throw new Error(`invalid --reasoning: ${raw} (use off|low|medium|high or a token budget)`);
10139
10139
  }
10140
10140
  function parseArgs(argv) {
10141
- const a = { stream: true, plan: false, ask: false, yes: false, vfs: false, shell: void 0, seed: false, subagents: false, help: false, version: false, cont: false, outputFormat: "text", duplex: false, voice: false, scratch: true };
10141
+ const a = { stream: true, plan: false, ask: false, yes: false, vfs: false, shell: void 0, seed: false, subagents: false, help: false, version: false, cont: false, outputFormat: "text", duplex: false, voice: false, scratch: true, updateCheck: true };
10142
10142
  const rest = [];
10143
10143
  const val = (i, flag) => {
10144
10144
  const v = argv[i];
@@ -10167,6 +10167,7 @@ function parseArgs(argv) {
10167
10167
  else if (x === "--vfs" || x === "--sandbox") a.vfs = true;
10168
10168
  else if (x === "--scratch") a.scratch = true;
10169
10169
  else if (x === "--no-scratch") a.scratch = false;
10170
+ else if (x === "--no-update-check") a.updateCheck = false;
10170
10171
  else if (x === "--boddb") a.boddb = val(++i, x);
10171
10172
  else if (x === "--seed") a.seed = true;
10172
10173
  else if (x === "--shell") a.shell = true;
@@ -10237,6 +10238,7 @@ Flags:
10237
10238
  --plan plan mode: edits blocked until you approve a plan
10238
10239
  --ask confirm each mutating tool (bash/Shell/Write/Edit/\u2026)
10239
10240
  --yes, -y auto-approve mutating tools (no prompts) \u2014 for trusted/unattended runs
10241
+ --no-update-check skip the automatic update check on startup
10240
10242
  --verbose, --debug verbose logs (sets DEBUG=* \u2014 tool args, hook decisions, retries)
10241
10243
  --allowedTools <l> comma-list of tools to allow w/o asking, e.g. "Edit,Shell(git *)"
10242
10244
  --disallowedTools <l> comma-list of tools to deny outright (wins over allow), e.g. "Shell(rm *)"
@@ -10280,7 +10282,7 @@ Project instructions: ./AGENTS.md or ./CLAUDE.md are auto-loaded (scaffold with
10280
10282
  Auto-loaded from ./.agent/: commands/, skills/, memory/, agents/.
10281
10283
 
10282
10284
  REPL shortcuts: !<cmd> runs a shell command inline \xB7 #<note> saves a memory \xB7 @path inlines a file
10283
- REPL slash commands: /help /version /tools /permissions /status /cost /context /transcript /doctor /cwd /model /reasoning /config /rename /compact /memory /rewind /undo /clear /sessions /resume /commands /skills /reload /mcp /init /export /paste /goal /exit (duplex: /act /think /tasks /voice /voice-model /think-model)
10285
+ REPL slash commands: /help /version /tools /permissions /status /cost /context /transcript /doctor /cwd /model /reasoning /config /rename /compact /memory /rewind /undo /clear /sessions /resume /commands /skills /reload /mcp /init /export /paste /goal /update /exit (duplex: /act /think /tasks /voice /voice-model /think-model)
10284
10286
  REPL completion: type / (commands+skills) or @ (files) for a LIVE menu \u2014 \u2191/\u2193 select, \u23CE/Tab accept, Esc dismiss.
10285
10287
  REPL multi-line: Option/Alt+Enter inserts a newline, or end a line with \\ to continue. Esc cancels a running turn / clears the input line; double-Esc jumps back to edit a previous message.
10286
10288
  REPL shortcuts: Shift+Tab cycles permission posture (ask \u2192 accept-edits \u2192 plan) \xB7 Alt+T toggles reasoning \xB7 Alt+P switches model \xB7 Ctrl+O toggles verbose tool output \xB7 Ctrl+X Ctrl+E edits the buffer in $EDITOR \xB7 \u2192 or Tab accepts the dim history ghost-suggestion \xB7 Alt+S/Ctrl+S stash/unstash.
@@ -10301,20 +10303,45 @@ function resolveModelOrNewest(model) {
10301
10303
  return fallback;
10302
10304
  }
10303
10305
  var ENV_KEY_ALIASES = { google: ["GEMINI_API_KEY"] };
10306
+ function loadEnvFile(file) {
10307
+ if (!existsSync9(file)) return;
10308
+ for (const line of readFileSync8(file, "utf8").split("\n")) {
10309
+ const m = line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
10310
+ if (!m || m[1] in process.env) continue;
10311
+ let val = m[2].trim();
10312
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) val = val.slice(1, -1);
10313
+ else val = val.replace(/\s+#.*$/, "").trim();
10314
+ process.env[m[1]] = val;
10315
+ }
10316
+ }
10304
10317
  function loadInstallEnv() {
10305
10318
  let dir = dirname4(import.meta.path);
10306
10319
  for (let i = 0; i < 5 && !existsSync9(join14(dir, "package.json")); i++) dir = dirname4(dir);
10307
10320
  for (const name of [".env", ".env.local"]) {
10308
- const file = join14(dir, name);
10309
- if (!existsSync9(file)) continue;
10310
- for (const line of readFileSync8(file, "utf8").split("\n")) {
10311
- const m = line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
10312
- if (!m || m[1] in process.env) continue;
10313
- let val = m[2].trim();
10314
- if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) val = val.slice(1, -1);
10315
- else val = val.replace(/\s+#.*$/, "").trim();
10316
- process.env[m[1]] = val;
10321
+ loadEnvFile(join14(dir, name));
10322
+ loadEnvFile(join14(homedir9(), ".agent", name));
10323
+ }
10324
+ }
10325
+ async function loadBodifySecrets() {
10326
+ const apiKey = process.env.BODIFY_API_KEY, appId = process.env.BODIFY_APP_ID;
10327
+ if (!apiKey || !appId) return;
10328
+ const base = process.env.BODIFY_URL || "https://bodify.bod.ee";
10329
+ try {
10330
+ const res = await fetch(`${base}/api/apps/${encodeURIComponent(appId)}/env`, {
10331
+ headers: { Authorization: `Bearer ${apiKey}` },
10332
+ signal: AbortSignal.timeout(5e3)
10333
+ });
10334
+ if (!res.ok) {
10335
+ console.error(` bodify secrets: ${res.status} ${res.statusText}`);
10336
+ return;
10317
10337
  }
10338
+ const { values } = await res.json();
10339
+ if (!values) return;
10340
+ for (const [k, v] of Object.entries(values)) {
10341
+ if (!(k in process.env)) process.env[k] = v;
10342
+ }
10343
+ } catch (e) {
10344
+ console.error(` bodify secrets: ${e.message ?? e}`);
10318
10345
  }
10319
10346
  }
10320
10347
  function apiKeysFromEnv() {
@@ -11956,6 +11983,7 @@ ${task}`;
11956
11983
  `));
11957
11984
  const keys = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_API_KEY", "GROQ_API_KEY"].filter((k) => process.env[k]);
11958
11985
  keys.length ? ok(`provider keys: ${keys.join(", ")}`) : bad("no provider keys set (ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY)");
11986
+ process.env.BODIFY_API_KEY && process.env.BODIFY_APP_ID ? ok(`bodify secrets: ${process.env.BODIFY_APP_ID}`) : warn("bodify secrets: not configured (set BODIFY_API_KEY + BODIFY_APP_ID)");
11959
11987
  const info = getModelInfo(work.model);
11960
11988
  info?.pricing ? ok(`model ${work.model} \u2014 priced (${info.pricing.inputCostPer1K}/${info.pricing.outputCostPer1K} per 1k in/out)`) : warn(`model ${work.model} \u2014 no pricing in the catalog (costs will show ~$0; verify the id)`);
11961
11989
  const cfgFiles = ["ts", "js", "json"].flatMap((e) => [`${cwd}/.agent/config.${e}`, `${homedir9()}/.agent/config.${e}`]).filter((p) => existsSync9(p));
@@ -12201,7 +12229,8 @@ ${task}`;
12201
12229
  { label: "permission posture", value: "posture", desc: postureLabel() + " (Shift+Tab)" },
12202
12230
  // streaming is the voice's lifeblood in duplex (always on) — only a normal-mode knob
12203
12231
  ...duplex ? [] : [{ label: "streaming", value: "stream", desc: agent.options.stream ? "on" : "off" }],
12204
- { label: "editor mode", value: "editor", desc: cfg.editorMode === "vim" ? "vim" : "normal" }
12232
+ { label: "editor mode", value: "editor", desc: cfg.editorMode === "vim" ? "vim" : "normal" },
12233
+ { label: "update check", value: "updateCheck", desc: cfg.updateCheck === false ? "off" : "on" }
12205
12234
  ];
12206
12235
  const pick = await selectMenu(process.stderr, { title: "Settings \xB7 \u21B5 change \xB7 esc close", items });
12207
12236
  if (!pick) return;
@@ -12222,6 +12251,10 @@ ${task}`;
12222
12251
  cfg.editorMode = cfg.editorMode === "vim" ? "normal" : "vim";
12223
12252
  persistSetting(cwd, "editorMode", cfg.editorMode);
12224
12253
  err(dim(" editor \u2192 " + cfg.editorMode + "\n"));
12254
+ } else if (pick === "updateCheck") {
12255
+ cfg.updateCheck = cfg.updateCheck === false ? true : false;
12256
+ persistSetting(cwd, "updateCheck", cfg.updateCheck);
12257
+ err(dim(" update check \u2192 " + (cfg.updateCheck ? "on" : "off") + "\n"));
12225
12258
  }
12226
12259
  }
12227
12260
  }
@@ -12753,6 +12786,18 @@ ${task}`;
12753
12786
  if (exitRequested) return true;
12754
12787
  }
12755
12788
  },
12789
+ update: {
12790
+ desc: "check for updates and install if available",
12791
+ run: async () => {
12792
+ err(dim(" checking\u2026\n"));
12793
+ const msg = await checkForUpdate(VERSION).catch(() => null);
12794
+ if (msg) {
12795
+ err(yellow(` ${msg}
12796
+ `));
12797
+ err(dim(" run the command above to update, then restart.\n"));
12798
+ } else err(green(" \u2713 up to date\n"));
12799
+ }
12800
+ },
12756
12801
  exit: { desc: "quit", run: () => true },
12757
12802
  quit: { desc: "quit", run: () => true }
12758
12803
  };
@@ -12760,7 +12805,7 @@ ${task}`;
12760
12805
  banner(bold("agentx") + cyan(" v" + VERSION) + dim(` \u2014 ${work.model} \xB7 ${cwd}`));
12761
12806
  banner(dim("Type a task, or /help. Type / or @ for live suggestions (\u2191/\u2193 \u23CE). Esc cancels/clears; double-Esc jumps back; Ctrl-D exits."));
12762
12807
  if (dx) banner(dim(`\u25D1 duplex \u2014 reflex: ${dx.options.reflexModel} \xB7 act: ${work.model}${dx.options.thinkModel !== false ? ` \xB7 think: ${dx.options.thinkModel}` : ""} (real work runs in background tasks, re-voiced when done)`));
12763
- checkForUpdate(VERSION).then((msg) => {
12808
+ if (args.updateCheck !== false && cfg.updateCheck !== false) checkForUpdate(VERSION).then((msg) => {
12764
12809
  if (msg) err(yellow(` ${msg}
12765
12810
  `));
12766
12811
  }).catch(() => {
@@ -13280,6 +13325,7 @@ async function main() {
13280
13325
  args.resume = id;
13281
13326
  }
13282
13327
  loadInstallEnv();
13328
+ await loadBodifySecrets();
13283
13329
  const apiKeys = { ...cfg.apiKeys, ...apiKeysFromEnv() };
13284
13330
  if (!Object.keys(apiKeys).length) {
13285
13331
  console.error(red("No provider key found. Set ANTHROPIC_API_KEY (or OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY), e.g. in .env."));