@livx.cc/agentx 0.96.2 → 0.96.4

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/README.md CHANGED
@@ -112,7 +112,7 @@ agentx --resume <id> "…" # resume a specific session
112
112
  - **Syntax-highlighted code fences** — ```` ```ts ```` (and js/py/sh/go/rust/…) blocks render with keywords bold, strings green, numbers cyan, comments dim; unknown languages keep the plain cyan body. **TodoWrite plans** pin a compact `☑ 2/5 · current step` line into the idle footer.
113
113
  - **`/agents`** — list subagent types from `./.agent/agents` (description, model, tool scope); `/agents new <name>` scaffolds a frontmatter'd definition for the `Task` tool's `agentType`. **`!<partial>` + menu** completes from past `!` shell commands. **`@server:uri`** mentions inline an MCP resource body into the prompt. Transient network drops mid-step retry automatically (2 attempts, backoff) instead of failing the turn.
114
114
  - **Project instructions** — `./AGENTS.md` (or `CLAUDE.md`) auto-loads into every run; `/init` scaffolds one.
115
- - **Any provider** — set `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GOOGLE_API_KEY` / `GROQ_API_KEY`; choose with `-m provider/model`.
115
+ - **Any provider** — set `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GOOGLE_API_KEY` / `GROQ_API_KEY`; choose with `-m provider/model`. Env files load with precedence: CWD `.env` (bun) → install-dir `.env` → `~/.agent/.env` (user-wide). **Bodify secrets**: set `BODIFY_API_KEY` + `BODIFY_APP_ID` (e.g. in `~/.agent/.env`) to pull provider keys from a Bodify app at startup — no local key management needed.
116
116
  - **@-file mentions & headless JSON** — reference files inline in a prompt with `@path` (e.g. `explain @src/Agent.ts`; `~/` expands to the home directory; quote paths with spaces as `@"…"` — drag-dropped files, e.g. macOS screenshots, quote themselves automatically); script with `-p --output-format json` to get one machine-readable result object on stdout (activity stays on stderr).
117
117
  - **Tab-completion** — `Tab` completes `/<command>` names and `@<path>` file/dir references (descends subdirs, dotfiles hidden unless typed) straight from the working tree.
118
118
  - **Duplex mode** — `agentx --duplex` runs the full standard REPL (slash commands, sessions, postures, rewind, MCP) with the three-tier engine driving turns: a fast voice model (`--voice-model`, default `groq/openai/gpt-oss-120b`) answers every line instantly and delegates real work to background workers built with the same wiring as a normal run (fs mode, permissions, MCP); worker activity shows as dim chrome and results are re-voiced when ready. Switch any tier live with `/model` (opens a reflex/act/think picker), or the `/voice-model` · `/think-model` shortcuts. `/tasks` lists background tasks, inspects a task's live output tail, and cancels a running one from a picker (Esc mid-turn cancels the foreground turn; Esc again at the idle prompt cancels running workers).
package/dist/cli.js CHANGED
@@ -10268,6 +10268,8 @@ Flags:
10268
10268
  Prompts may reference files with @path (e.g. "explain @src/Agent.ts") \u2014 they're inlined.
10269
10269
 
10270
10270
  Providers: set any of ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY / GROQ_API_KEY.
10271
+ Env files: .env (CWD, bun auto-loads) > install-dir .env > ~/.agent/.env (user-wide).
10272
+ Bodify secrets: set BODIFY_API_KEY + BODIFY_APP_ID (in ~/.agent/.env) to pull keys from a Bodify app.
10271
10273
  Config: ./.agent/config.{ts,js,json} (project) or ~/.agent/config.* (user).
10272
10274
  export default { model, maxSteps, reasoning, permissionMode, editorMode, tools, apiKeys, baseUrls, hooks, permissions, mcpServers, maxTokens,
10273
10275
  timeoutMs, maxRepeats, maxToolCalls, keepToolOutputs, maxContextTokens,
@@ -10303,20 +10305,23 @@ function resolveModelOrNewest(model) {
10303
10305
  return fallback;
10304
10306
  }
10305
10307
  var ENV_KEY_ALIASES = { google: ["GEMINI_API_KEY"] };
10308
+ function loadEnvFile(file) {
10309
+ if (!existsSync9(file)) return;
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;
10317
+ }
10318
+ }
10306
10319
  function loadInstallEnv() {
10307
10320
  let dir = dirname4(import.meta.path);
10308
10321
  for (let i = 0; i < 5 && !existsSync9(join14(dir, "package.json")); i++) dir = dirname4(dir);
10309
10322
  for (const name of [".env", ".env.local"]) {
10310
- const file = join14(dir, name);
10311
- if (!existsSync9(file)) continue;
10312
- for (const line of readFileSync8(file, "utf8").split("\n")) {
10313
- const m = line.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
10314
- if (!m || m[1] in process.env) continue;
10315
- let val = m[2].trim();
10316
- if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) val = val.slice(1, -1);
10317
- else val = val.replace(/\s+#.*$/, "").trim();
10318
- process.env[m[1]] = val;
10319
- }
10323
+ loadEnvFile(join14(dir, name));
10324
+ loadEnvFile(join14(homedir9(), ".agent", name));
10320
10325
  }
10321
10326
  }
10322
10327
  async function loadBodifySecrets() {
@@ -12226,7 +12231,8 @@ ${task}`;
12226
12231
  { label: "permission posture", value: "posture", desc: postureLabel() + " (Shift+Tab)" },
12227
12232
  // streaming is the voice's lifeblood in duplex (always on) — only a normal-mode knob
12228
12233
  ...duplex ? [] : [{ label: "streaming", value: "stream", desc: agent.options.stream ? "on" : "off" }],
12229
- { label: "editor mode", value: "editor", desc: cfg.editorMode === "vim" ? "vim" : "normal" }
12234
+ { label: "editor mode", value: "editor", desc: cfg.editorMode === "vim" ? "vim" : "normal" },
12235
+ { label: "update check", value: "updateCheck", desc: cfg.updateCheck === false ? "off" : "on" }
12230
12236
  ];
12231
12237
  const pick = await selectMenu(process.stderr, { title: "Settings \xB7 \u21B5 change \xB7 esc close", items });
12232
12238
  if (!pick) return;
@@ -12247,6 +12253,10 @@ ${task}`;
12247
12253
  cfg.editorMode = cfg.editorMode === "vim" ? "normal" : "vim";
12248
12254
  persistSetting(cwd, "editorMode", cfg.editorMode);
12249
12255
  err(dim(" editor \u2192 " + cfg.editorMode + "\n"));
12256
+ } else if (pick === "updateCheck") {
12257
+ cfg.updateCheck = cfg.updateCheck === false ? true : false;
12258
+ persistSetting(cwd, "updateCheck", cfg.updateCheck);
12259
+ err(dim(" update check \u2192 " + (cfg.updateCheck ? "on" : "off") + "\n"));
12250
12260
  }
12251
12261
  }
12252
12262
  }
@@ -12797,7 +12807,7 @@ ${task}`;
12797
12807
  banner(bold("agentx") + cyan(" v" + VERSION) + dim(` \u2014 ${work.model} \xB7 ${cwd}`));
12798
12808
  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."));
12799
12809
  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)`));
12800
- if (args.updateCheck !== false) checkForUpdate(VERSION).then((msg) => {
12810
+ if (args.updateCheck !== false && cfg.updateCheck !== false) checkForUpdate(VERSION).then((msg) => {
12801
12811
  if (msg) err(yellow(` ${msg}
12802
12812
  `));
12803
12813
  }).catch(() => {