botapp-cli 0.2.7 → 0.2.9

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/bin/bot.js CHANGED
@@ -1361,7 +1361,7 @@ async function runShellAgent(job) {
1361
1361
  child.stderr.on("data", (chunk) => {
1362
1362
  stderr += chunk.toString();
1363
1363
  });
1364
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1364
+ const code = await awaitChildClose(child, job.agent.command);
1365
1365
  if (code !== 0) {
1366
1366
  throw new Error(stderr.trim() || `Agent exited with code ${code}`);
1367
1367
  }
@@ -1449,7 +1449,7 @@ async function runCodexAgent(job, update) {
1449
1449
  }
1450
1450
  const rl = createInterface2({ input: child.stdout });
1451
1451
  rl.on("line", processLine);
1452
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1452
+ const code = await awaitChildClose(child, job.agent.command);
1453
1453
  if (code !== 0) {
1454
1454
  throw new Error(errors.at(-1) ?? (stderr.trim() || `Codex exited with code ${code}`));
1455
1455
  }
@@ -1584,7 +1584,7 @@ async function runClaudeCodeAgent(job, update) {
1584
1584
  }
1585
1585
  const rl = createInterface2({ input: child.stdout });
1586
1586
  rl.on("line", processLine);
1587
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1587
+ const code = await awaitChildClose(child, job.agent.command);
1588
1588
  if (code !== 0) {
1589
1589
  const parts = [];
1590
1590
  if (stderr.trim()) parts.push(stderr.trim());
@@ -1721,7 +1721,7 @@ ${job.query}`;
1721
1721
  }
1722
1722
  const rl = createInterface2({ input: child.stdout });
1723
1723
  rl.on("line", processLine);
1724
- const code = await new Promise((resolve11) => child.on("close", resolve11));
1724
+ const code = await awaitChildClose(child, job.agent.command);
1725
1725
  const resumeMatch = stderr.match(/To resume this session:\s*kimi\s+-r\s+([A-Za-z0-9_-]+)/);
1726
1726
  if (resumeMatch) result.sessionId = resumeMatch[1];
1727
1727
  if (code !== 0) {
@@ -2385,7 +2385,7 @@ Invalid ACP stdout: ${line}`;
2385
2385
  clientInfo: {
2386
2386
  name: "botapp-daemon",
2387
2387
  title: "botapp daemon",
2388
- version: "0.2.7"
2388
+ version: "0.2.9"
2389
2389
  }
2390
2390
  });
2391
2391
  const session = await request2("session/new", {
@@ -2512,6 +2512,20 @@ function parseMaybeJson(value) {
2512
2512
  function sleep(ms) {
2513
2513
  return new Promise((resolveSleep) => setTimeout(resolveSleep, ms));
2514
2514
  }
2515
+ function awaitChildClose(child, commandLabel) {
2516
+ return new Promise((resolveClose, reject) => {
2517
+ child.once("error", (err) => {
2518
+ if (err.code === "ENOENT") {
2519
+ reject(new Error(
2520
+ `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\`).`
2521
+ ));
2522
+ } else {
2523
+ reject(err);
2524
+ }
2525
+ });
2526
+ child.once("close", resolveClose);
2527
+ });
2528
+ }
2515
2529
  async function waitForChild(child, timeoutMs, label) {
2516
2530
  return new Promise((resolveWait, reject) => {
2517
2531
  const timeout = setTimeout(() => {
@@ -4492,7 +4506,7 @@ function packageJson(ctx, headless) {
4492
4506
  typecheck: "tsc --noEmit"
4493
4507
  };
4494
4508
  const deps = {
4495
- "botapp-sdk": "^0.1.0",
4509
+ "botapp-sdk": "^0.1.1",
4496
4510
  ws: "^8.18.0"
4497
4511
  };
4498
4512
  const devDeps = {
@@ -4654,7 +4668,7 @@ function apiEntryTs(ctx, headless) {
4654
4668
 
4655
4669
  ctx.serveStatic('./dist/public')
4656
4670
  `;
4657
- return `import { BotApp } from 'botapp-sdk'
4671
+ return `import { BotApp, runHosted } from 'botapp-sdk'
4658
4672
 
4659
4673
  const app = new BotApp({
4660
4674
  name: '${ctx.name}',
@@ -4676,7 +4690,16 @@ const app = new BotApp({
4676
4690
  ${widget} },
4677
4691
  })
4678
4692
 
4679
- await app.start()
4693
+ export default app
4694
+
4695
+ // Hosted-tier bridge: only connects when launched with BOTAPP_SERVER +
4696
+ // BOTAPP_APP_TOKEN (set by \`bot simulate\` and the platform-spawned runner).
4697
+ // In every other context (tests, in-process discovery) the bridge stays
4698
+ // dormant. Use globalThis.process so this typechecks without @types/node.
4699
+ const env = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env ?? {}
4700
+ if (env.BOTAPP_SERVER && env.BOTAPP_APP_TOKEN) {
4701
+ await runHosted(app)
4702
+ }
4680
4703
  `;
4681
4704
  }
4682
4705
  function srcMainTsx(_ctx) {
@@ -4717,32 +4740,53 @@ export function App() {
4717
4740
  }
4718
4741
  function srcApiTs() {
4719
4742
  return `// Tiny client for calling app routes/commands from the browser.
4720
- // Routes resolve as /apps/<name>/* on the platform; the platform forwards
4721
- // each request to your app's WebSocket session.
4743
+ // Two ways an app frontend reaches its backend on a botapp server:
4744
+ //
4745
+ // 1. Path-prefixed: /apps/<name>/api/commands/<cmd> (on bare apex)
4746
+ // 2. Subdomain: /api/apps/<name>/commands/<cmd> (on app subdomain)
4747
+ //
4748
+ // The subdomain dispatcher in the server leaves /api/* unrewritten on
4749
+ // subdomain hosts, so the frontend has to construct the absolute
4750
+ // /api/apps/<name>/... URL itself. We resolve <name> three ways and
4751
+ // take the first that works:
4752
+ // \u2022 from a /apps/<name>/ path prefix (host is the apex)
4753
+ // \u2022 from the first DNS label (host is <name>.<domain>)
4754
+ // \u2022 fallback: skip the /api/apps/<name> prefix (single-app local dev)
4722
4755
 
4723
- const APP_BASE = ((): string => {
4724
- const m = location.pathname.match(/^\\/apps\\/[^/]+\\//)
4725
- return m ? m[0] : '/'
4726
- })()
4756
+ function resolveAppName(): string | null {
4757
+ const m = location.pathname.match(/^\\/apps\\/([^/]+)\\//)
4758
+ if (m) return m[1]
4759
+ const host = location.hostname
4760
+ const first = host.split('.')[0]
4761
+ if (first && first !== 'www' && host.split('.').length >= 2) return first
4762
+ return null
4763
+ }
4727
4764
 
4728
- export async function callCommand(name: string, params: Record<string, unknown> = {}) {
4729
- const r = await fetch(\`\${APP_BASE}api/commands/\${encodeURIComponent(name)}\`, {
4765
+ const APP_NAME = resolveAppName()
4766
+ const API_BASE = APP_NAME ? \`/api/apps/\${APP_NAME}\` : '/api'
4767
+
4768
+ async function call(kind: 'commands' | 'actions', name: string, params: Record<string, unknown>): Promise<unknown> {
4769
+ const r = await fetch(\`\${API_BASE}/\${kind}/\${encodeURIComponent(name)}\`, {
4730
4770
  method: 'POST',
4731
4771
  headers: { 'Content-Type': 'application/json' },
4732
4772
  body: JSON.stringify(params),
4733
4773
  })
4734
4774
  if (!r.ok) throw new Error(await r.text())
4735
- return r.json()
4775
+ // The /api/apps/<name>/... handler wraps responses as
4776
+ // \`{ status: 'success', result }\` or \`{ status: 'error', error }\`.
4777
+ // Unwrap so callers see the bare result; throw on error.
4778
+ const json = (await r.json()) as { status?: string; result?: unknown; error?: string }
4779
+ if (json.status === 'error') throw new Error(json.error ?? 'unknown error')
4780
+ if (json.status === 'success') return json.result
4781
+ return json
4782
+ }
4783
+
4784
+ export async function callCommand(name: string, params: Record<string, unknown> = {}) {
4785
+ return call('commands', name, params)
4736
4786
  }
4737
4787
 
4738
4788
  export async function callAction(name: string, params: Record<string, unknown> = {}) {
4739
- const r = await fetch(\`\${APP_BASE}api/actions/\${encodeURIComponent(name)}\`, {
4740
- method: 'POST',
4741
- headers: { 'Content-Type': 'application/json' },
4742
- body: JSON.stringify(params),
4743
- })
4744
- if (!r.ok) throw new Error(await r.text())
4745
- return r.json()
4789
+ return call('actions', name, params)
4746
4790
  }
4747
4791
  `;
4748
4792
  }
@@ -5009,7 +5053,7 @@ function die(msg) {
5009
5053
  }
5010
5054
 
5011
5055
  // src/index.ts
5012
- var version = "0.2.7";
5056
+ var version = "0.2.9";
5013
5057
  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");
5014
5058
  program.addCommand(launchCommand);
5015
5059
  program.addCommand(runCommand);