@livx.cc/agentx 0.99.106 → 0.99.107

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
@@ -139,6 +139,7 @@ interface Args {
139
139
  reasoning?: ReasoningEffort;
140
140
  help: boolean;
141
141
  version: boolean;
142
+ keepAlive?: boolean;
142
143
  duplex: boolean;
143
144
  duplexV2?: boolean;
144
145
  call?: boolean;
package/dist/cli.js CHANGED
@@ -18634,7 +18634,8 @@ function parseArgs(argv) {
18634
18634
  } else if (x === "--call") {
18635
18635
  a.call = true;
18636
18636
  a.duplex = true;
18637
- } else if (x === "--channel-only") a.channelOnly = true;
18637
+ } else if (x === "--keep-alive") a.keepAlive = true;
18638
+ else if (x === "--channel-only") a.channelOnly = true;
18638
18639
  else if (x === "--channel-mode") a.channelMode = parseChannelMode(val(++i, x));
18639
18640
  else if (x === "--conversational" || x === "--convo" || x === "--voice") {
18640
18641
  a.voice = true;
@@ -18676,6 +18677,7 @@ function parseArgs(argv) {
18676
18677
  if (a.worktree && (a.vfs || a.boddb)) throw new Error("--worktree is a real-disk concept \u2014 incompatible with --vfs/--boddb");
18677
18678
  if (a.duplex && (a.task || a.print)) throw new Error("--duplex is interactive-only (a conversational mode) \u2014 drop the task/-p");
18678
18679
  if (a.inputFormat && (!a.duplex && !a.print && !a.channelOnly || a.outputFormat !== "stream-json")) throw new Error("--input-format stream-json needs --output-format stream-json and --duplex (or --voice), --channel-only or -p");
18680
+ if (a.keepAlive && (!a.print || !a.inputFormat)) throw new Error("--keep-alive needs -p --input-format stream-json --output-format stream-json");
18679
18681
  if (a.channelOnly && !a.inputFormat) throw new Error("--channel-only needs --input-format stream-json --output-format stream-json");
18680
18682
  if (a.duplex && a.plan) throw new Error("--plan is not supported in --duplex (workers are non-interactive; a plan could never be approved)");
18681
18683
  if (a.voiceSystemPrompt && !a.duplex) throw new Error("--voice-system-prompt only applies with --duplex");
@@ -18763,6 +18765,9 @@ Flags:
18763
18765
  (NDJSON turns/barge-ins on stdin, reflex text + worker speech + task events on stdout)
18764
18766
  with -p: the first {"type":"user","text"} line is the prompt; later ones STEER the running turn
18765
18767
  (unconsumed steers come back as the result's \`unsteered\`)
18768
+ --keep-alive with -p --input-format stream-json: stay up after a turn \u2014 each {"type":"user"} line while idle
18769
+ is the NEXT turn (warm: same session, model connection and MCP servers), one {type:result}
18770
+ per turn; {"type":"abort"} stops the running turn; stdin EOF exits
18766
18771
  --output-format <f> headless output: text (default) | json (one result object) | stream-json (NDJSON events: {type:text|thinking}\u2026 then {type:result})
18767
18772
  -v, --version print version and exit
18768
18773
  -h, --help
@@ -22527,9 +22532,9 @@ async function channelServe(args, ai, cfg) {
22527
22532
  await new Promise((r) => rl.on("close", () => r()));
22528
22533
  call.end();
22529
22534
  }
22530
- function readStdinSteers() {
22535
+ function readStdinSteers(keepAlive = false) {
22531
22536
  const early = [];
22532
- let sink, got;
22537
+ let sink, got, closed = false;
22533
22538
  const first = new Promise((res) => {
22534
22539
  got = res;
22535
22540
  });
@@ -22541,6 +22546,10 @@ function readStdinSteers() {
22541
22546
  } catch {
22542
22547
  return;
22543
22548
  }
22549
+ if (keepAlive && m?.type === "abort") {
22550
+ activeTurn?.abort();
22551
+ return;
22552
+ }
22544
22553
  if (m?.type !== "user" || typeof m.text !== "string" || !m.text.trim()) return;
22545
22554
  if (got) {
22546
22555
  got(m.text);
@@ -22548,11 +22557,21 @@ function readStdinSteers() {
22548
22557
  } else if (sink) sink(m.text);
22549
22558
  else early.push(m.text);
22550
22559
  });
22551
- rl.on("close", () => got?.(""));
22560
+ rl.on("close", () => {
22561
+ closed = true;
22562
+ got?.("");
22563
+ got = void 0;
22564
+ });
22565
+ const next = () => {
22566
+ sink = void 0;
22567
+ return early.length ? Promise.resolve(early.shift()) : closed ? Promise.resolve("") : new Promise((res) => {
22568
+ got = res;
22569
+ });
22570
+ };
22552
22571
  return { first, steer: (to) => {
22553
22572
  sink = to;
22554
22573
  early.splice(0).forEach(to);
22555
- } };
22574
+ }, next };
22556
22575
  }
22557
22576
  function readAllStdin() {
22558
22577
  return new Promise((res) => {
@@ -22587,7 +22606,7 @@ async function main() {
22587
22606
  process.exit(installUpdate() ? 0 : 1);
22588
22607
  }
22589
22608
  if (args.debug) process.env.DEBUG ||= "*";
22590
- const steers = args.print && args.inputFormat && !args.task ? readStdinSteers() : void 0;
22609
+ const steers = args.print && args.inputFormat && !args.task ? readStdinSteers(args.keepAlive) : void 0;
22591
22610
  if (steers) args.task = (await steers.first).trim();
22592
22611
  else if (args.print && !args.task && !process.stdin.isTTY) args.task = (await readAllStdin()).trim();
22593
22612
  if (args.print && !args.task) {
@@ -22680,7 +22699,19 @@ async function main() {
22680
22699
  const session = startSession(args, store, agent, cwd);
22681
22700
  process.once("SIGINT", () => activeTurn?.abort());
22682
22701
  steers?.steer((text) => agent.inject(text));
22683
- const { ok, res } = await runTurn(agent, store, session, args.task, void 0, cwd, autoRouteSend(args, agent, () => session, (m) => providerOptionsFor(m, cwd, cfg.mcpServers, mounted.map((x) => x.name))));
22702
+ const turn = (task) => runTurn(agent, store, session, task, void 0, cwd, autoRouteSend(args, agent, () => session, (m) => providerOptionsFor(m, cwd, cfg.mcpServers, mounted.map((x) => x.name))));
22703
+ if (args.keepAlive && steers) {
22704
+ for (let task = args.task; task.trim(); task = (await steers.next()).trim()) {
22705
+ steers.steer((text) => agent.inject(text));
22706
+ const { res: res2 } = await turn(task);
22707
+ const left = agent.drainPendingSteers();
22708
+ process.stdout.write(JSON.stringify({ type: "result", ...res2 ? jsonResult(res2, session) : { ok: false, finishReason: "error", sessionId: session.meta.id }, ...left.length ? { unsteered: left } : {} }) + "\n");
22709
+ }
22710
+ await closeMcp(mounted);
22711
+ worktreeCleanup?.();
22712
+ process.exit(0);
22713
+ }
22714
+ const { ok, res } = await turn(args.task);
22684
22715
  if (cfg.reflectOnFailure && !ok && res?.finishReason !== "needs_input" && res && agent.options.memoryDir) {
22685
22716
  const _fsBase = agent.options.fs.getCwd() === "/" ? "" : agent.options.fs.getCwd();
22686
22717
  const slug2 = await reflectOnRun({ ai, model: agent.options.model, fs: agent.options.fs, dir: primaryMemDir(agent.options.memoryDir, `${_fsBase}/.agent/memory`), result: res });