@livx.cc/agentx 0.99.82 → 0.99.84

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.js CHANGED
@@ -16407,7 +16407,7 @@ function parseArgs(argv) {
16407
16407
  if (a.seed && !a.boddb) throw new Error("--seed only applies with --boddb (it seeds the database from cwd on first run)");
16408
16408
  if (a.worktree && (a.vfs || a.boddb)) throw new Error("--worktree is a real-disk concept \u2014 incompatible with --vfs/--boddb");
16409
16409
  if (a.duplex && (a.task || a.print)) throw new Error("--duplex is interactive-only (a conversational mode) \u2014 drop the task/-p");
16410
- if (a.inputFormat && (!a.duplex || a.outputFormat !== "stream-json")) throw new Error("--input-format stream-json is headless duplex \u2014 use it with --duplex (or --voice) and --output-format stream-json");
16410
+ if (a.inputFormat && (!a.duplex && !a.print || a.outputFormat !== "stream-json")) throw new Error("--input-format stream-json needs --output-format stream-json and --duplex (or --voice) or -p");
16411
16411
  if (a.duplex && a.plan) throw new Error("--plan is not supported in --duplex (workers are non-interactive; a plan could never be approved)");
16412
16412
  if (a.voiceSystemPrompt && !a.duplex) throw new Error("--voice-system-prompt only applies with --duplex");
16413
16413
  if (a.voiceModel && !a.duplex) throw new Error("--voice-model only applies with --duplex");
@@ -16472,6 +16472,8 @@ Flags:
16472
16472
  --timeout <sec> wall-clock kill-switch (default 120)
16473
16473
  --input-format stream-json with --duplex|--voice + --output-format stream-json: headless duplex for a host app
16474
16474
  (NDJSON turns/barge-ins on stdin, reflex text + worker speech + task events on stdout)
16475
+ with -p: the first {"type":"user","text"} line is the prompt; later ones STEER the running turn
16476
+ (unconsumed steers come back as the result's \`unsteered\`)
16475
16477
  --output-format <f> headless output: text (default) | json (one result object) | stream-json (NDJSON events: {type:text|thinking}\u2026 then {type:result})
16476
16478
  -v, --version print version and exit
16477
16479
  -h, --help
@@ -17663,7 +17665,7 @@ async function repl(args, ai, cfg, cwd) {
17663
17665
  let dx;
17664
17666
  let voiceIO;
17665
17667
  let voiceDiag;
17666
- const decider = duplex && process.env.TYPESAFE_AI_KEY ? new DecideClient({ apiKey: process.env.TYPESAFE_AI_KEY }) : void 0;
17668
+ const decider = duplex ? leakDecider() : void 0;
17667
17669
  const instinct = decider && process.env.VOICE_INSTINCT === "1" ? new Instinct({
17668
17670
  decider,
17669
17671
  context: () => ({ agentSaid: dx?.recentExcerpt(1).replace(/^\w+: /, ""), recent: dx?.recentExcerpt(4) }),
@@ -19925,6 +19927,7 @@ function duplexError(e, reflexModel) {
19925
19927
  const code = e?.statusCode;
19926
19928
  return code && !msg.includes(String(code)) ? `${msg} (${code})` : msg;
19927
19929
  }
19930
+ var leakDecider = () => process.env.TYPESAFE_AI_KEY ? new DecideClient({ apiKey: process.env.TYPESAFE_AI_KEY }) : void 0;
19928
19931
  async function duplexServe(args, ai, cfg, cwd) {
19929
19932
  const out = (o) => process.stdout.write(JSON.stringify(o) + "\n");
19930
19933
  const mounted = await mountMcp(cfg, new McpOAuth({ storePath: join15(cwd, ".agent", "mcp-auth.json") }));
@@ -19952,6 +19955,8 @@ async function duplexServe(args, ai, cfg, cwd) {
19952
19955
  `));
19953
19956
  const dx = new DuplexAgent({
19954
19957
  ai,
19958
+ decider: leakDecider(),
19959
+ // without it only the strict leak shapes are cut — "We need to provide…" was spoken (bare-browser #509)
19955
19960
  fs: agent.options.fs,
19956
19961
  memoryDir: agent.options.memoryDir,
19957
19962
  memoryUserDir: agent.options.memoryUserDir,
@@ -20013,6 +20018,33 @@ async function duplexServe(args, ai, cfg, cwd) {
20013
20018
  persist();
20014
20019
  await closeMcp(mounted);
20015
20020
  }
20021
+ function readStdinSteers() {
20022
+ const early = [];
20023
+ let sink, got;
20024
+ const first = new Promise((res) => {
20025
+ got = res;
20026
+ });
20027
+ const rl = createInterface({ input: process.stdin });
20028
+ rl.on("line", (line) => {
20029
+ let m;
20030
+ try {
20031
+ m = JSON.parse(line);
20032
+ } catch {
20033
+ return;
20034
+ }
20035
+ if (m?.type !== "user" || typeof m.text !== "string" || !m.text.trim()) return;
20036
+ if (got) {
20037
+ got(m.text);
20038
+ got = void 0;
20039
+ } else if (sink) sink(m.text);
20040
+ else early.push(m.text);
20041
+ });
20042
+ rl.on("close", () => got?.(""));
20043
+ return { first, steer: (to) => {
20044
+ sink = to;
20045
+ early.splice(0).forEach(to);
20046
+ } };
20047
+ }
20016
20048
  function readAllStdin() {
20017
20049
  return new Promise((res) => {
20018
20050
  let data = "";
@@ -20046,7 +20078,9 @@ async function main() {
20046
20078
  process.exit(installUpdate() ? 0 : 1);
20047
20079
  }
20048
20080
  if (args.debug) process.env.DEBUG ||= "*";
20049
- if (args.print && !args.task && !process.stdin.isTTY) args.task = (await readAllStdin()).trim();
20081
+ const steers = args.print && args.inputFormat && !args.task ? readStdinSteers() : void 0;
20082
+ if (steers) args.task = (await steers.first).trim();
20083
+ else if (args.print && !args.task && !process.stdin.isTTY) args.task = (await readAllStdin()).trim();
20050
20084
  if (args.print && !args.task) {
20051
20085
  console.error(red(" -p: empty prompt (no task argument and nothing on stdin)"));
20052
20086
  process.exit(2);
@@ -20136,6 +20170,7 @@ async function main() {
20136
20170
  const store = new SessionStore(cwd);
20137
20171
  const session = startSession(args, store, agent, cwd);
20138
20172
  process.once("SIGINT", () => activeTurn?.abort());
20173
+ steers?.steer((text) => agent.inject(text));
20139
20174
  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))));
20140
20175
  if (cfg.reflectOnFailure && !ok && res?.finishReason !== "needs_input" && res && agent.options.memoryDir) {
20141
20176
  const _fsBase = agent.options.fs.getCwd() === "/" ? "" : agent.options.fs.getCwd();
@@ -20145,7 +20180,8 @@ async function main() {
20145
20180
  }
20146
20181
  await closeMcp(mounted);
20147
20182
  if (args.outputFormat === "json" || args.outputFormat === "stream-json") {
20148
- const obj = res ? jsonResult(res, session) : { ok: false, finishReason: "error", sessionId: session.meta.id };
20183
+ const left = steers ? agent.drainPendingSteers() : [];
20184
+ const obj = { ...res ? jsonResult(res, session) : { ok: false, finishReason: "error", sessionId: session.meta.id }, ...left.length ? { unsteered: left } : {} };
20149
20185
  process.stdout.write(JSON.stringify(args.outputFormat === "stream-json" ? { type: "result", ...obj } : obj) + "\n");
20150
20186
  }
20151
20187
  worktreeCleanup?.();