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 +69 -25
- package/dist/bin/bot.js.map +1 -1
- package/dist/index.js +69 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
//
|
|
4723
|
-
//
|
|
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
|
-
|
|
4726
|
-
const m = location.pathname.match(/^\\/apps\\/[^/]
|
|
4727
|
-
|
|
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
|
-
|
|
4731
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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);
|