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/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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
//
|
|
4721
|
-
//
|
|
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
|
-
|
|
4724
|
-
const m = location.pathname.match(/^\\/apps\\/[^/]
|
|
4725
|
-
|
|
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
|
-
|
|
4729
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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);
|