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