botapp-cli 0.2.8 → 0.2.10

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/index.js CHANGED
@@ -955,32 +955,38 @@ async function ptyKill(params) {
955
955
  async function openPty(opts) {
956
956
  const nodePty = await loadNodePty();
957
957
  if (nodePty) {
958
- const proc2 = nodePty.spawn(opts.command, opts.args, {
959
- name: "xterm-256color",
960
- cols: opts.cols,
961
- rows: opts.rows,
962
- cwd: opts.cwd,
963
- env: opts.env
964
- });
965
- const ptyId2 = randomUUID();
966
- proc2.onData((data) => {
967
- opts.ctx.pushChunk({ kind: "data", data });
968
- });
969
- const exited2 = new Promise((resolve11) => {
970
- proc2.onExit(({ exitCode }) => {
971
- resolve11(exitCode);
958
+ try {
959
+ const proc2 = nodePty.spawn(opts.command, opts.args, {
960
+ name: "xterm-256color",
961
+ cols: opts.cols,
962
+ rows: opts.rows,
963
+ cwd: opts.cwd,
964
+ env: opts.env
972
965
  });
973
- });
974
- return {
975
- mode: "pty",
976
- exited: exited2,
977
- handle: {
978
- ptyId: ptyId2,
979
- resize: (cols, rows) => proc2.resize(cols, rows),
980
- write: (data) => proc2.write(data),
981
- kill: (signal) => proc2.kill(signal)
982
- }
983
- };
966
+ const ptyId2 = randomUUID();
967
+ proc2.onData((data) => {
968
+ opts.ctx.pushChunk({ kind: "data", data });
969
+ });
970
+ const exited2 = new Promise((resolve11) => {
971
+ proc2.onExit(({ exitCode }) => {
972
+ resolve11(exitCode);
973
+ });
974
+ });
975
+ return {
976
+ mode: "pty",
977
+ exited: exited2,
978
+ handle: {
979
+ ptyId: ptyId2,
980
+ resize: (cols, rows) => proc2.resize(cols, rows),
981
+ write: (data) => proc2.write(data),
982
+ kill: (signal) => proc2.kill(signal)
983
+ }
984
+ };
985
+ } catch (e) {
986
+ console.warn(
987
+ `[pty] node-pty spawn failed (${e?.message ?? e}); falling back to line-oriented pipe mode`
988
+ );
989
+ }
984
990
  }
985
991
  const proc = spawn2(
986
992
  opts.command,
@@ -999,7 +1005,23 @@ async function openPty(opts) {
999
1005
  opts.ctx.pushChunk({ kind: "data", data: chunk.toString("utf8") });
1000
1006
  });
1001
1007
  const exited = new Promise((resolve11) => {
1002
- proc.on("close", (code) => resolve11(code));
1008
+ let settled = false;
1009
+ proc.on("close", (code) => {
1010
+ if (settled) return;
1011
+ settled = true;
1012
+ resolve11(code);
1013
+ });
1014
+ proc.on("error", (err) => {
1015
+ opts.ctx.pushChunk({
1016
+ kind: "data",
1017
+ data: `\r
1018
+ [shell failed to start: ${err.message}]\r
1019
+ `
1020
+ });
1021
+ if (settled) return;
1022
+ settled = true;
1023
+ resolve11(1);
1024
+ });
1003
1025
  });
1004
1026
  return {
1005
1027
  mode: "pipe",
@@ -1363,7 +1385,7 @@ async function runShellAgent(job) {
1363
1385
  child.stderr.on("data", (chunk) => {
1364
1386
  stderr += chunk.toString();
1365
1387
  });
1366
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1388
+ const code = await awaitChildClose(child, job.agent.command);
1367
1389
  if (code !== 0) {
1368
1390
  throw new Error(stderr.trim() || `Agent exited with code ${code}`);
1369
1391
  }
@@ -1451,7 +1473,7 @@ async function runCodexAgent(job, update) {
1451
1473
  }
1452
1474
  const rl = createInterface2({ input: child.stdout });
1453
1475
  rl.on("line", processLine);
1454
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1476
+ const code = await awaitChildClose(child, job.agent.command);
1455
1477
  if (code !== 0) {
1456
1478
  throw new Error(errors.at(-1) ?? (stderr.trim() || `Codex exited with code ${code}`));
1457
1479
  }
@@ -1586,7 +1608,7 @@ async function runClaudeCodeAgent(job, update) {
1586
1608
  }
1587
1609
  const rl = createInterface2({ input: child.stdout });
1588
1610
  rl.on("line", processLine);
1589
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1611
+ const code = await awaitChildClose(child, job.agent.command);
1590
1612
  if (code !== 0) {
1591
1613
  const parts = [];
1592
1614
  if (stderr.trim()) parts.push(stderr.trim());
@@ -1723,7 +1745,7 @@ ${job.query}`;
1723
1745
  }
1724
1746
  const rl = createInterface2({ input: child.stdout });
1725
1747
  rl.on("line", processLine);
1726
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1748
+ const code = await awaitChildClose(child, job.agent.command);
1727
1749
  const resumeMatch = stderr.match(/To resume this session:\s*kimi\s+-r\s+([A-Za-z0-9_-]+)/);
1728
1750
  if (resumeMatch) result.sessionId = resumeMatch[1];
1729
1751
  if (code !== 0) {
@@ -2387,7 +2409,7 @@ Invalid ACP stdout: ${line}`;
2387
2409
  clientInfo: {
2388
2410
  name: "botapp-daemon",
2389
2411
  title: "botapp daemon",
2390
- version: "0.2.8"
2412
+ version: "0.2.10"
2391
2413
  }
2392
2414
  });
2393
2415
  const session = await request2("session/new", {
@@ -2514,6 +2536,20 @@ function parseMaybeJson(value) {
2514
2536
  function sleep(ms) {
2515
2537
  return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
2516
2538
  }
2539
+ function awaitChildClose(child, commandLabel) {
2540
+ return new Promise((resolveClose, reject) => {
2541
+ child.once("error", (err) => {
2542
+ if (err.code === "ENOENT") {
2543
+ reject(new Error(
2544
+ `Agent CLI "${commandLabel}" not found on PATH for the daemon process. Install it, or re-register the agent with an absolute path (\`bot daemon agent remove ${commandLabel}\` then \`bot daemon config\`).`
2545
+ ));
2546
+ } else {
2547
+ reject(err);
2548
+ }
2549
+ });
2550
+ child.once("close", resolveClose);
2551
+ });
2552
+ }
2517
2553
  async function waitForChild(child, timeoutMs, label) {
2518
2554
  return new Promise((resolveWait, reject) => {
2519
2555
  const timeout = setTimeout(() => {
@@ -5041,7 +5077,7 @@ function die(msg) {
5041
5077
  }
5042
5078
 
5043
5079
  // src/index.ts
5044
- var version = "0.2.8";
5080
+ var version = "0.2.10";
5045
5081
  var program = new Command25().name("bot").description("botapp CLI \u2014 operate apps from the command line").version(version).enablePositionalOptions(true).option("--json", "Output as JSON").option("-s, --server <url>", "Server URL override").option("-t, --token <token>", "Auth token override").option("-v, --verbose", "Verbose output");
5046
5082
  program.addCommand(launchCommand);
5047
5083
  program.addCommand(runCommand);