@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 +40 -4
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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?.();
|