bazilion 0.2.1 → 0.4.0

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/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { defineCommand as defineCommand20, runCommand, showUsage } from "citty";
4
+ import { defineCommand as defineCommand22, runCommand, showUsage } from "citty";
5
5
 
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "bazilion",
9
- version: "0.2.1",
9
+ version: "0.4.0",
10
10
  description: "Multi-agent runtime CLI \u2014 spawn LLM agents, manage profiles/groups/skills, and run the local daemon.",
11
11
  license: "MIT",
12
12
  repository: {
@@ -49,18 +49,19 @@ var package_default = {
49
49
  access: "public"
50
50
  },
51
51
  dependencies: {
52
- "@earendil-works/pi-agent-core": "^0.75.4",
53
- "@earendil-works/pi-ai": "^0.75.4",
54
- "@earendil-works/pi-coding-agent": "^0.75.4",
55
- "@hono/node-server": "^2.0.3",
52
+ "@earendil-works/pi-agent-core": "^0.77.0",
53
+ "@earendil-works/pi-ai": "^0.77.0",
54
+ "@earendil-works/pi-coding-agent": "^0.77.0",
55
+ "@hono/node-server": "^2.0.4",
56
56
  "@mozilla/readability": "^0.6.0",
57
- "@tobilu/qmd": "^2.5.2",
57
+ "@tobilu/qmd": "^2.5.3",
58
58
  "adm-zip": "^0.5.17",
59
59
  citty: "^0.2.2",
60
- hono: "^4.12.22",
60
+ hono: "^4.12.23",
61
61
  linkedom: "^0.18.12",
62
+ playwright: "^1.60.0",
62
63
  "qrcode-terminal": "^0.12.0",
63
- typebox: "^1.1.38",
64
+ typebox: "^1.1.39",
64
65
  undici: "^8.3.0",
65
66
  yaml: "^2.9.0"
66
67
  },
@@ -209,6 +210,8 @@ function createClient2(cfg = loadClientConfig()) {
209
210
  }
210
211
 
211
212
  // src/commands/agent.ts
213
+ import { readFileSync as readFileSync2, writeFileSync } from "fs";
214
+ import { basename, extname } from "path";
212
215
  import { stdin, stdout } from "process";
213
216
  import { createInterface } from "readline/promises";
214
217
  import { defineCommand } from "citty";
@@ -234,6 +237,39 @@ function columnize(rows, gap = " ") {
234
237
  }
235
238
 
236
239
  // src/commands/agent.ts
240
+ var IMAGE_MIME = {
241
+ ".png": "image/png",
242
+ ".jpg": "image/jpeg",
243
+ ".jpeg": "image/jpeg",
244
+ ".gif": "image/gif",
245
+ ".webp": "image/webp"
246
+ };
247
+ function loadImages(paths) {
248
+ return paths.map((p) => {
249
+ const mimeType = IMAGE_MIME[extname(p).toLowerCase()];
250
+ if (!mimeType) throw new Error(`unsupported image type: ${p} (png/jpg/gif/webp only)`);
251
+ return { name: basename(p), mimeType, data: readFileSync2(p).toString("base64") };
252
+ });
253
+ }
254
+ var FILE_MIME = {
255
+ ".pdf": "application/pdf",
256
+ ".txt": "text/plain",
257
+ ".md": "text/markdown",
258
+ ".csv": "text/csv",
259
+ ".json": "application/json",
260
+ ".html": "text/html",
261
+ ".zip": "application/zip"
262
+ };
263
+ function loadFiles(paths) {
264
+ return paths.map((p) => ({
265
+ name: basename(p),
266
+ mimeType: FILE_MIME[extname(p).toLowerCase()] ?? "application/octet-stream",
267
+ data: readFileSync2(p).toString("base64")
268
+ }));
269
+ }
270
+ function asPaths(v) {
271
+ return v ? Array.isArray(v) ? v : [v] : [];
272
+ }
237
273
  var spawnCmd = defineCommand({
238
274
  meta: { name: "spawn", description: "Spawn an agent from a profile into a group" },
239
275
  args: {
@@ -266,7 +302,7 @@ var spawnCmd = defineCommand({
266
302
  var editCmd = defineCommand({
267
303
  meta: {
268
304
  name: "edit",
269
- description: "Edit agent settings (name, model override, reasoning level)"
305
+ description: "Edit agent settings (name, model override, reasoning level, telegram mirror)"
270
306
  },
271
307
  args: {
272
308
  id: { type: "positional", required: true, description: "Agent id or prefix" },
@@ -275,11 +311,21 @@ var editCmd = defineCommand({
275
311
  reasoning: {
276
312
  type: "string",
277
313
  description: "Reasoning level: off|minimal|low|medium|high|xhigh"
314
+ },
315
+ mirror: {
316
+ type: "string",
317
+ description: "Telegram mirror verbosity: minimal|verbose"
318
+ },
319
+ "topic-icon": {
320
+ type: "string",
321
+ description: 'Telegram topic emoji (e.g. \u{1F4DA}). Use --topic-icon "" to clear.'
278
322
  }
279
323
  },
280
324
  async run({ args }) {
281
- if (args.name === void 0 && args.model === void 0 && args.reasoning === void 0) {
282
- console.error("agent edit: specify at least one of --name, --model, or --reasoning");
325
+ if (args.name === void 0 && args.model === void 0 && args.reasoning === void 0 && args.mirror === void 0 && args["topic-icon"] === void 0) {
326
+ console.error(
327
+ "agent edit: specify at least one of --name, --model, --reasoning, --mirror, --topic-icon"
328
+ );
283
329
  process.exit(2);
284
330
  }
285
331
  const client = createClient2();
@@ -289,6 +335,16 @@ var editCmd = defineCommand({
289
335
  body.modelOverride = args.model === "" ? null : args.model;
290
336
  }
291
337
  if (args.reasoning !== void 0) body.reasoningLevel = args.reasoning;
338
+ if (args.mirror !== void 0) {
339
+ if (args.mirror !== "minimal" && args.mirror !== "verbose") {
340
+ console.error(`agent edit: --mirror must be 'minimal' or 'verbose'`);
341
+ process.exit(2);
342
+ }
343
+ body.telegramMirrorMode = args.mirror;
344
+ }
345
+ if (args["topic-icon"] !== void 0) {
346
+ body.telegramIconEmoji = args["topic-icon"] === "" ? null : args["topic-icon"];
347
+ }
292
348
  const agent = await client.patch(`/api/agents/${args.id}`, body);
293
349
  console.log(`updated agent ${agent.id} (${agent.name})`);
294
350
  }
@@ -399,6 +455,16 @@ function printEvent(e, state) {
399
455
  case "tool_error":
400
456
  console.log(` [tool error: ${e.name} \u2014 ${e.error}]`);
401
457
  break;
458
+ case "file": {
459
+ if (state.inDeltaStream) {
460
+ process.stdout.write("\n");
461
+ state.inDeltaStream = false;
462
+ }
463
+ const out = basename(e.name).replace(/[^\w.-]/g, "_") || "file";
464
+ writeFileSync(out, Buffer.from(e.data, "base64"));
465
+ console.log(` [file received: saved to ./${out} (${e.mimeType})]`);
466
+ break;
467
+ }
402
468
  case "error":
403
469
  if (state.inDeltaStream) {
404
470
  process.stdout.write("\n");
@@ -408,10 +474,11 @@ function printEvent(e, state) {
408
474
  break;
409
475
  }
410
476
  }
411
- async function streamTurn(client, agentId, message) {
477
+ async function streamTurn(client, agentId, message, attachments) {
412
478
  const state = { inDeltaStream: false };
413
479
  for await (const frame of client.stream("POST", `/api/agents/${agentId}/chat`, {
414
- message
480
+ message,
481
+ ...attachments && attachments.length > 0 ? { attachments } : {}
415
482
  })) {
416
483
  if (frame.kind === "event") {
417
484
  if (frame.event.type !== "user_message") printEvent(frame.event, state);
@@ -428,13 +495,25 @@ var chatCmd = defineCommand({
428
495
  message: {
429
496
  type: "string",
430
497
  description: "Send a single message and exit (one-shot mode)"
498
+ },
499
+ image: {
500
+ type: "string",
501
+ description: "Attach an image file (png/jpg/gif/webp; repeatable). One-shot mode."
502
+ },
503
+ file: {
504
+ type: "string",
505
+ description: "Attach any file \u2014 the agent gets a path reference (repeatable). One-shot mode."
431
506
  }
432
507
  },
433
508
  async run({ args }) {
434
509
  const client = createClient2();
435
510
  const resolved = await client.get(`/api/agents/${args.id}`);
436
- if (args.message) {
437
- await streamTurn(client, resolved.agent.id, args.message);
511
+ const attachments = [
512
+ ...loadImages(asPaths(args.image)),
513
+ ...loadFiles(asPaths(args.file))
514
+ ];
515
+ if (args.message || attachments.length > 0) {
516
+ await streamTurn(client, resolved.agent.id, args.message ?? "", attachments);
438
517
  return;
439
518
  }
440
519
  console.log(`chatting with ${resolved.agent.name} (${resolved.model})`);
@@ -788,7 +867,7 @@ var openaiLoginCmd = defineCommand2({
788
867
  console.log(`access token expires: ${formatExpiry(status.expiresAt)}`);
789
868
  console.log("");
790
869
  console.log(`enable the 'openai-codex' provider on /config and add at least one model`);
791
- console.log("(e.g. gpt-5.1-codex-max, gpt-5.2, gpt-5.3-codex) to start using it.");
870
+ console.log("(e.g. gpt-5.3-codex, gpt-5.4, gpt-5.5) to start using it.");
792
871
  }
793
872
  });
794
873
  var openaiLogoutCmd = defineCommand2({
@@ -1275,7 +1354,7 @@ var doctorCommand = defineCommand6({
1275
1354
  });
1276
1355
 
1277
1356
  // src/commands/group.ts
1278
- import { readFileSync as readFileSync2 } from "fs";
1357
+ import { readFileSync as readFileSync3 } from "fs";
1279
1358
  import { stdin as stdin2 } from "process";
1280
1359
  import { defineCommand as defineCommand7 } from "citty";
1281
1360
  var addCmd = defineCommand7({
@@ -1355,7 +1434,7 @@ var userMdSetCmd = defineCommand7({
1355
1434
  async run({ args }) {
1356
1435
  let content;
1357
1436
  if (args["from-stdin"]) content = await readStdin();
1358
- else if (args.file) content = readFileSync2(args.file, "utf8");
1437
+ else if (args.file) content = readFileSync3(args.file, "utf8");
1359
1438
  else if (args.text !== void 0) content = args.text;
1360
1439
  else {
1361
1440
  console.error("group user-md set: provide --file, --from-stdin, or --text");
@@ -1385,13 +1464,64 @@ var userMdCmd = defineCommand7({
1385
1464
  clear: userMdClearCmd
1386
1465
  }
1387
1466
  });
1467
+ var topicFormatShowCmd = defineCommand7({
1468
+ meta: { name: "show", description: "Print the group's Telegram topic-name template" },
1469
+ args: { id: { type: "positional", required: true } },
1470
+ async run({ args }) {
1471
+ const client = createClient2();
1472
+ const g = await client.get(`/api/groups/${args.id}`);
1473
+ console.log(g.telegramTopicNameFormat ?? "(default naming)");
1474
+ }
1475
+ });
1476
+ var topicFormatSetCmd = defineCommand7({
1477
+ meta: {
1478
+ name: "set",
1479
+ description: "Set the topic-name template. Tokens: {agent.name} {group.name} {group.slug} (must include {agent.name})"
1480
+ },
1481
+ args: {
1482
+ id: { type: "positional", required: true },
1483
+ format: {
1484
+ type: "positional",
1485
+ required: true,
1486
+ description: 'e.g. "{group.name} / {agent.name}"'
1487
+ }
1488
+ },
1489
+ async run({ args }) {
1490
+ const client = createClient2();
1491
+ const body = { format: args.format };
1492
+ const g = await client.put(`/api/groups/${args.id}/topic-format`, body);
1493
+ console.log(`set topic-name template for group ${args.id}: ${g.telegramTopicNameFormat}`);
1494
+ }
1495
+ });
1496
+ var topicFormatClearCmd = defineCommand7({
1497
+ meta: { name: "clear", description: "Clear the template (revert to built-in naming)" },
1498
+ args: { id: { type: "positional", required: true } },
1499
+ async run({ args }) {
1500
+ const client = createClient2();
1501
+ const body = { format: null };
1502
+ await client.put(`/api/groups/${args.id}/topic-format`, body);
1503
+ console.log(`cleared topic-name template for group ${args.id}`);
1504
+ }
1505
+ });
1506
+ var topicFormatCmd = defineCommand7({
1507
+ meta: {
1508
+ name: "topic-format",
1509
+ description: "View or edit a group's Telegram forum-topic name template"
1510
+ },
1511
+ subCommands: {
1512
+ show: topicFormatShowCmd,
1513
+ set: topicFormatSetCmd,
1514
+ clear: topicFormatClearCmd
1515
+ }
1516
+ });
1388
1517
  var groupCommand = defineCommand7({
1389
1518
  meta: { name: "group", description: "Manage groups (collaboration contexts)" },
1390
1519
  subCommands: {
1391
1520
  add: addCmd,
1392
1521
  list: listCmd3,
1393
1522
  rm: rmCmd2,
1394
- "user-md": userMdCmd
1523
+ "user-md": userMdCmd,
1524
+ "topic-format": topicFormatCmd
1395
1525
  }
1396
1526
  });
1397
1527
 
@@ -1472,7 +1602,7 @@ var inboxCommand = defineCommand8({
1472
1602
  });
1473
1603
 
1474
1604
  // src/commands/login.ts
1475
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "fs";
1605
+ import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
1476
1606
  import { defineCommand as defineCommand9 } from "citty";
1477
1607
  function normalizeServer(raw) {
1478
1608
  let url;
@@ -1511,14 +1641,14 @@ var loginCommand = defineCommand9({
1511
1641
  `${paths.authFile} not found. Start the daemon with "bazilion serve" first \u2014 login stores the remote there.`
1512
1642
  );
1513
1643
  }
1514
- const auth = JSON.parse(readFileSync3(paths.authFile, "utf8"));
1644
+ const auth = JSON.parse(readFileSync4(paths.authFile, "utf8"));
1515
1645
  if (args.clear) {
1516
1646
  if (!auth.remote) {
1517
1647
  console.log("no remote stored \u2014 nothing to clear");
1518
1648
  return;
1519
1649
  }
1520
1650
  delete auth.remote;
1521
- writeFileSync(paths.authFile, `${JSON.stringify(auth, null, 2)}
1651
+ writeFileSync2(paths.authFile, `${JSON.stringify(auth, null, 2)}
1522
1652
  `, { mode: 384 });
1523
1653
  console.log("cleared stored remote; CLI will fall back to the local daemon");
1524
1654
  return;
@@ -1533,19 +1663,138 @@ var loginCommand = defineCommand9({
1533
1663
  await verifyToken(server, args.token);
1534
1664
  }
1535
1665
  auth.remote = { server, token: args.token };
1536
- writeFileSync(paths.authFile, `${JSON.stringify(auth, null, 2)}
1666
+ writeFileSync2(paths.authFile, `${JSON.stringify(auth, null, 2)}
1537
1667
  `, { mode: 384 });
1538
1668
  console.log(`saved remote: ${server}`);
1539
1669
  console.log("CLI will now target this server unless BAZILION_SERVER is set in the env.");
1540
1670
  }
1541
1671
  });
1542
1672
 
1543
- // src/commands/memory.ts
1673
+ // src/commands/mcp.ts
1544
1674
  import { defineCommand as defineCommand10 } from "citty";
1675
+ function serverRow(s) {
1676
+ const where = s.transport === "stdio" ? `${s.command} ${s.args.join(" ")}`.trim() : s.url ?? "";
1677
+ return [
1678
+ s.id,
1679
+ s.enabled ? "enabled" : "disabled",
1680
+ s.transport,
1681
+ s.hasAuthToken ? "auth" : "-",
1682
+ s.name,
1683
+ where
1684
+ ];
1685
+ }
1686
+ var addCmd2 = defineCommand10({
1687
+ meta: { name: "add", description: "Register an MCP server" },
1688
+ args: {
1689
+ name: { type: "positional", required: true, description: "Unique name ([a-zA-Z0-9_])" },
1690
+ transport: { type: "string", description: "stdio | http | sse (default stdio)" },
1691
+ command: { type: "string", description: "stdio: executable to run (e.g. npx)" },
1692
+ args: { type: "string", description: "stdio: space-separated args (quote the whole string)" },
1693
+ url: { type: "string", description: "http/sse: endpoint URL" },
1694
+ token: { type: "string", description: "http/sse: bearer token (stored encrypted)" },
1695
+ disabled: { type: "boolean", description: "Create disabled" }
1696
+ },
1697
+ async run({ args }) {
1698
+ const transport = args.transport ?? "stdio";
1699
+ const body = {
1700
+ name: args.name,
1701
+ transport,
1702
+ command: args.command ?? null,
1703
+ args: args.args ? args.args.split(" ").filter(Boolean) : [],
1704
+ url: args.url ?? null,
1705
+ authToken: args.token ?? void 0,
1706
+ enabled: !args.disabled
1707
+ };
1708
+ const client = createClient2();
1709
+ const { server } = await client.post("/api/mcp-servers", body);
1710
+ console.log(`${server.id} ${server.name} ${server.transport}`);
1711
+ }
1712
+ });
1713
+ var listCmd5 = defineCommand10({
1714
+ meta: { name: "list", description: "List MCP servers" },
1715
+ async run() {
1716
+ const client = createClient2();
1717
+ const { servers } = await client.get("/api/mcp-servers");
1718
+ if (servers.length === 0) {
1719
+ console.log("(no MCP servers)");
1720
+ return;
1721
+ }
1722
+ for (const line of columnize(servers.map(serverRow))) console.log(line);
1723
+ }
1724
+ });
1725
+ var showCmd3 = defineCommand10({
1726
+ meta: { name: "show", description: "Show one MCP server" },
1727
+ args: { id: { type: "positional", required: true } },
1728
+ async run({ args }) {
1729
+ const client = createClient2();
1730
+ const { server } = await client.get(`/api/mcp-servers/${args.id}`);
1731
+ console.log(JSON.stringify(server, null, 2));
1732
+ }
1733
+ });
1734
+ var rmCmd3 = defineCommand10({
1735
+ meta: { name: "rm", description: "Delete an MCP server" },
1736
+ args: { id: { type: "positional", required: true } },
1737
+ async run({ args }) {
1738
+ const client = createClient2();
1739
+ await client.del(`/api/mcp-servers/${args.id}`);
1740
+ console.log(`removed MCP server ${args.id}`);
1741
+ }
1742
+ });
1743
+ var enableCmd = defineCommand10({
1744
+ meta: { name: "enable", description: "Enable an MCP server" },
1745
+ args: { id: { type: "positional", required: true } },
1746
+ async run({ args }) {
1747
+ const client = createClient2();
1748
+ await client.patch(`/api/mcp-servers/${args.id}`, { enabled: true });
1749
+ console.log(`enabled MCP server ${args.id}`);
1750
+ }
1751
+ });
1752
+ var disableCmd = defineCommand10({
1753
+ meta: { name: "disable", description: "Disable an MCP server" },
1754
+ args: { id: { type: "positional", required: true } },
1755
+ async run({ args }) {
1756
+ const client = createClient2();
1757
+ await client.patch(`/api/mcp-servers/${args.id}`, { enabled: false });
1758
+ console.log(`disabled MCP server ${args.id}`);
1759
+ }
1760
+ });
1761
+ var testCmd = defineCommand10({
1762
+ meta: { name: "test", description: "Connect to a server and list its tools" },
1763
+ args: { id: { type: "positional", required: true } },
1764
+ async run({ args }) {
1765
+ const client = createClient2();
1766
+ const res = await client.post(
1767
+ `/api/mcp-servers/${args.id}/test`
1768
+ );
1769
+ if (!res.ok) {
1770
+ console.error(`connection failed: ${res.error}`);
1771
+ process.exitCode = 1;
1772
+ return;
1773
+ }
1774
+ const tools = res.tools ?? [];
1775
+ console.log(`connected \u2014 ${tools.length} tool(s):`);
1776
+ for (const t of tools) console.log(` ${t.name} ${t.description}`);
1777
+ }
1778
+ });
1779
+ var mcpCommand = defineCommand10({
1780
+ meta: { name: "mcp", description: "Manage MCP servers" },
1781
+ subCommands: {
1782
+ add: addCmd2,
1783
+ list: listCmd5,
1784
+ show: showCmd3,
1785
+ rm: rmCmd3,
1786
+ enable: enableCmd,
1787
+ disable: disableCmd,
1788
+ test: testCmd
1789
+ }
1790
+ });
1791
+
1792
+ // src/commands/memory.ts
1793
+ import { defineCommand as defineCommand11 } from "citty";
1545
1794
  function encodeKey(key) {
1546
1795
  return key.split("/").map(encodeURIComponent).join("/");
1547
1796
  }
1548
- var writeCmd = defineCommand10({
1797
+ var writeCmd = defineCommand11({
1549
1798
  meta: { name: "write", description: "Write an entry into a group's shared memory" },
1550
1799
  args: {
1551
1800
  group: { type: "positional", required: true, description: "Group slug" },
@@ -1561,7 +1810,7 @@ var writeCmd = defineCommand10({
1561
1810
  console.log(`wrote ${entry2.key} (${entry2.content.length} bytes)`);
1562
1811
  }
1563
1812
  });
1564
- var readCmd2 = defineCommand10({
1813
+ var readCmd2 = defineCommand11({
1565
1814
  meta: { name: "read", description: "Read an entry from a group's shared memory" },
1566
1815
  args: {
1567
1816
  group: { type: "positional", required: true, description: "Group slug" },
@@ -1575,7 +1824,7 @@ var readCmd2 = defineCommand10({
1575
1824
  console.log(entry2.content);
1576
1825
  }
1577
1826
  });
1578
- var searchCmd = defineCommand10({
1827
+ var searchCmd = defineCommand11({
1579
1828
  meta: { name: "search", description: "Search a group's shared memory" },
1580
1829
  args: {
1581
1830
  group: { type: "positional", required: true, description: "Group slug" },
@@ -1596,7 +1845,7 @@ var searchCmd = defineCommand10({
1596
1845
  }
1597
1846
  }
1598
1847
  });
1599
- var listCmd5 = defineCommand10({
1848
+ var listCmd6 = defineCommand11({
1600
1849
  meta: { name: "list", description: "List all entries in a group's shared memory" },
1601
1850
  args: {
1602
1851
  group: { type: "positional", required: true, description: "Group slug" }
@@ -1613,7 +1862,7 @@ var listCmd5 = defineCommand10({
1613
1862
  }
1614
1863
  }
1615
1864
  });
1616
- var rmCmd3 = defineCommand10({
1865
+ var rmCmd4 = defineCommand11({
1617
1866
  meta: { name: "rm", description: "Remove an entry from a group's shared memory" },
1618
1867
  args: {
1619
1868
  group: { type: "positional", required: true, description: "Group slug" },
@@ -1625,7 +1874,7 @@ var rmCmd3 = defineCommand10({
1625
1874
  console.log(`removed ${args.key}`);
1626
1875
  }
1627
1876
  });
1628
- var memoryCommand = defineCommand10({
1877
+ var memoryCommand = defineCommand11({
1629
1878
  meta: {
1630
1879
  name: "memory",
1631
1880
  description: "Manage a group's shared memory (BM25-indexed markdown notes)"
@@ -1634,15 +1883,15 @@ var memoryCommand = defineCommand10({
1634
1883
  write: writeCmd,
1635
1884
  read: readCmd2,
1636
1885
  search: searchCmd,
1637
- list: listCmd5,
1638
- rm: rmCmd3
1886
+ list: listCmd6,
1887
+ rm: rmCmd4
1639
1888
  }
1640
1889
  });
1641
1890
 
1642
1891
  // src/commands/profile.ts
1643
1892
  import { spawn as spawn2 } from "child_process";
1644
1893
  import { randomBytes } from "crypto";
1645
- import { readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
1894
+ import { readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
1646
1895
  import { tmpdir } from "os";
1647
1896
  import { join as join2 } from "path";
1648
1897
 
@@ -1658,7 +1907,7 @@ var PROFILE_FILES = [
1658
1907
  ];
1659
1908
 
1660
1909
  // src/commands/profile.ts
1661
- import { defineCommand as defineCommand11 } from "citty";
1910
+ import { defineCommand as defineCommand12 } from "citty";
1662
1911
  function splitCsv(v) {
1663
1912
  if (!v) return void 0;
1664
1913
  const out = v.split(",").map((s) => s.trim()).filter(Boolean);
@@ -1669,7 +1918,7 @@ function parseSkillsMode(v) {
1669
1918
  if (v === "all" || v === "selected") return v;
1670
1919
  throw new Error(`--skills-mode must be 'all' or 'selected', got '${v}'`);
1671
1920
  }
1672
- var createCmd2 = defineCommand11({
1921
+ var createCmd2 = defineCommand12({
1673
1922
  meta: { name: "create", description: "Create a new profile" },
1674
1923
  args: {
1675
1924
  id: { type: "positional", required: true, description: "Profile slug" },
@@ -1677,7 +1926,7 @@ var createCmd2 = defineCommand11({
1677
1926
  model: {
1678
1927
  type: "string",
1679
1928
  required: true,
1680
- description: "Default model, e.g. anthropic:claude-opus-4-6"
1929
+ description: "Default model, e.g. anthropic:claude-opus-4-8"
1681
1930
  },
1682
1931
  "skills-mode": {
1683
1932
  type: "string",
@@ -1718,7 +1967,7 @@ var createCmd2 = defineCommand11({
1718
1967
  },
1719
1968
  async run({ args }) {
1720
1969
  const skillsMode = parseSkillsMode(args["skills-mode"]);
1721
- const readTemplate = (path) => path ? readFileSync4(path, "utf8") : void 0;
1970
+ const readTemplate = (path) => path ? readFileSync5(path, "utf8") : void 0;
1722
1971
  const body = {
1723
1972
  id: args.id,
1724
1973
  name: args.name,
@@ -1737,7 +1986,7 @@ var createCmd2 = defineCommand11({
1737
1986
  console.log(`created profile ${profile.id} at ${profile.dir}`);
1738
1987
  }
1739
1988
  });
1740
- var listCmd6 = defineCommand11({
1989
+ var listCmd7 = defineCommand12({
1741
1990
  meta: { name: "list", description: "List profiles" },
1742
1991
  async run() {
1743
1992
  const client = createClient2();
@@ -1750,7 +1999,7 @@ var listCmd6 = defineCommand11({
1750
1999
  for (const line of columnize(rows)) console.log(line);
1751
2000
  }
1752
2001
  });
1753
- var showCmd3 = defineCommand11({
2002
+ var showCmd4 = defineCommand12({
1754
2003
  meta: { name: "show", description: "Show profile details" },
1755
2004
  args: {
1756
2005
  id: { type: "positional", required: true }
@@ -1776,7 +2025,7 @@ var showCmd3 = defineCommand11({
1776
2025
  }
1777
2026
  }
1778
2027
  });
1779
- var editCmd2 = defineCommand11({
2028
+ var editCmd2 = defineCommand12({
1780
2029
  meta: { name: "edit", description: "Open a profile file in $EDITOR" },
1781
2030
  args: {
1782
2031
  id: { type: "positional", required: true },
@@ -1796,7 +2045,7 @@ var editCmd2 = defineCommand11({
1796
2045
  `/api/profiles/${args.id}/files/${file}`
1797
2046
  );
1798
2047
  const tmpPath = join2(tmpdir(), `bazilion-${args.id}-${file}-${randomBytes(4).toString("hex")}`);
1799
- writeFileSync2(tmpPath, content);
2048
+ writeFileSync3(tmpPath, content);
1800
2049
  try {
1801
2050
  const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
1802
2051
  const code = await new Promise((resolve3, reject) => {
@@ -1805,7 +2054,7 @@ var editCmd2 = defineCommand11({
1805
2054
  child.on("close", (c) => resolve3(c ?? 0));
1806
2055
  });
1807
2056
  if (code !== 0) throw new Error(`editor exited with code ${code}`);
1808
- const updated = readFileSync4(tmpPath, "utf8");
2057
+ const updated = readFileSync5(tmpPath, "utf8");
1809
2058
  if (updated === content) {
1810
2059
  console.log("(no changes)");
1811
2060
  return;
@@ -1821,7 +2070,7 @@ var editCmd2 = defineCommand11({
1821
2070
  }
1822
2071
  }
1823
2072
  });
1824
- var updateCmd = defineCommand11({
2073
+ var updateCmd = defineCommand12({
1825
2074
  meta: {
1826
2075
  name: "update",
1827
2076
  description: "Update profile settings (name, model, skills-mode, skills)"
@@ -1855,7 +2104,7 @@ var updateCmd = defineCommand11({
1855
2104
  console.log(`updated profile ${profile.id}`);
1856
2105
  }
1857
2106
  });
1858
- var deleteCmd2 = defineCommand11({
2107
+ var deleteCmd2 = defineCommand12({
1859
2108
  meta: { name: "delete", description: "Permanently delete a profile and its files" },
1860
2109
  args: {
1861
2110
  id: { type: "positional", required: true }
@@ -1866,12 +2115,12 @@ var deleteCmd2 = defineCommand11({
1866
2115
  console.log(`deleted profile ${args.id}`);
1867
2116
  }
1868
2117
  });
1869
- var profileCommand = defineCommand11({
2118
+ var profileCommand = defineCommand12({
1870
2119
  meta: { name: "profile", description: "Manage profiles" },
1871
2120
  subCommands: {
1872
2121
  create: createCmd2,
1873
- list: listCmd6,
1874
- show: showCmd3,
2122
+ list: listCmd7,
2123
+ show: showCmd4,
1875
2124
  edit: editCmd2,
1876
2125
  update: updateCmd,
1877
2126
  delete: deleteCmd2
@@ -1881,11 +2130,11 @@ var profileCommand = defineCommand11({
1881
2130
  // src/commands/profile-group.ts
1882
2131
  import { spawn as spawn3 } from "child_process";
1883
2132
  import { randomBytes as randomBytes2 } from "crypto";
1884
- import { readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
2133
+ import { readFileSync as readFileSync6, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
1885
2134
  import { tmpdir as tmpdir2 } from "os";
1886
2135
  import { join as join3 } from "path";
1887
- import { defineCommand as defineCommand12 } from "citty";
1888
- var createCmd3 = defineCommand12({
2136
+ import { defineCommand as defineCommand13 } from "citty";
2137
+ var createCmd3 = defineCommand13({
1889
2138
  meta: { name: "create", description: "Create a new profile group (team template)" },
1890
2139
  args: {
1891
2140
  id: { type: "positional", required: true, description: "Profile group slug" },
@@ -1898,13 +2147,13 @@ var createCmd3 = defineCommand12({
1898
2147
  async run({ args }) {
1899
2148
  const body = { id: args.id };
1900
2149
  if (args.name) body.name = args.name;
1901
- if (args["user-md-file"]) body.userMd = readFileSync5(args["user-md-file"], "utf8");
2150
+ if (args["user-md-file"]) body.userMd = readFileSync6(args["user-md-file"], "utf8");
1902
2151
  const client = createClient2();
1903
2152
  const created = await client.post("/api/profile-groups", body);
1904
2153
  console.log(`created profile group ${created.id}`);
1905
2154
  }
1906
2155
  });
1907
- var listCmd7 = defineCommand12({
2156
+ var listCmd8 = defineCommand13({
1908
2157
  meta: { name: "list", description: "List profile groups" },
1909
2158
  async run() {
1910
2159
  const client = createClient2();
@@ -1917,7 +2166,7 @@ var listCmd7 = defineCommand12({
1917
2166
  for (const line of columnize(rows)) console.log(line);
1918
2167
  }
1919
2168
  });
1920
- var showCmd4 = defineCommand12({
2169
+ var showCmd5 = defineCommand13({
1921
2170
  meta: { name: "show", description: "Show profile group details + members" },
1922
2171
  args: {
1923
2172
  id: { type: "positional", required: true },
@@ -1954,7 +2203,7 @@ var showCmd4 = defineCommand12({
1954
2203
  for (const line of columnize(rows)) console.log(` ${line}`);
1955
2204
  }
1956
2205
  });
1957
- var updateCmd2 = defineCommand12({
2206
+ var updateCmd2 = defineCommand13({
1958
2207
  meta: { name: "update", description: "Update profile group basics (name, user-md)" },
1959
2208
  args: {
1960
2209
  id: { type: "positional", required: true },
@@ -1968,7 +2217,7 @@ var updateCmd2 = defineCommand12({
1968
2217
  const body = {};
1969
2218
  if (args.name !== void 0) body.name = args.name;
1970
2219
  if (args["user-md-file"] !== void 0) {
1971
- body.userMd = args["user-md-file"] === "" ? null : readFileSync5(args["user-md-file"], "utf8");
2220
+ body.userMd = args["user-md-file"] === "" ? null : readFileSync6(args["user-md-file"], "utf8");
1972
2221
  }
1973
2222
  if (Object.keys(body).length === 0) {
1974
2223
  throw new Error("nothing to update \u2014 pass at least one of --name/--user-md-file");
@@ -1978,7 +2227,7 @@ var updateCmd2 = defineCommand12({
1978
2227
  console.log(`updated profile group ${updated.id}`);
1979
2228
  }
1980
2229
  });
1981
- var editCmd3 = defineCommand12({
2230
+ var editCmd3 = defineCommand13({
1982
2231
  meta: { name: "edit", description: "Edit the member array in $EDITOR (JSON)" },
1983
2232
  args: {
1984
2233
  id: { type: "positional", required: true }
@@ -1998,7 +2247,7 @@ var editCmd3 = defineCommand12({
1998
2247
  tmpdir2(),
1999
2248
  `bazilion-profile-group-${args.id}-${randomBytes2(4).toString("hex")}.json`
2000
2249
  );
2001
- writeFileSync3(tmpPath, before);
2250
+ writeFileSync4(tmpPath, before);
2002
2251
  try {
2003
2252
  const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
2004
2253
  const code = await new Promise((resolve3, reject) => {
@@ -2007,7 +2256,7 @@ var editCmd3 = defineCommand12({
2007
2256
  child.on("close", (c) => resolve3(c ?? 0));
2008
2257
  });
2009
2258
  if (code !== 0) throw new Error(`editor exited with code ${code}`);
2010
- const after = readFileSync5(tmpPath, "utf8");
2259
+ const after = readFileSync6(tmpPath, "utf8");
2011
2260
  if (after === before) {
2012
2261
  console.log("(no changes)");
2013
2262
  return;
@@ -2045,7 +2294,7 @@ var editCmd3 = defineCommand12({
2045
2294
  }
2046
2295
  }
2047
2296
  });
2048
- var deleteCmd3 = defineCommand12({
2297
+ var deleteCmd3 = defineCommand13({
2049
2298
  meta: { name: "delete", description: "Delete a profile group (does not affect spawned agents)" },
2050
2299
  args: {
2051
2300
  id: { type: "positional", required: true }
@@ -2056,7 +2305,7 @@ var deleteCmd3 = defineCommand12({
2056
2305
  console.log(`deleted profile group ${args.id}`);
2057
2306
  }
2058
2307
  });
2059
- var spawnCmd2 = defineCommand12({
2308
+ var spawnCmd2 = defineCommand13({
2060
2309
  meta: { name: "spawn", description: "Spawn the whole team into a group (transactional)" },
2061
2310
  args: {
2062
2311
  id: { type: "positional", required: true },
@@ -2072,7 +2321,7 @@ var spawnCmd2 = defineCommand12({
2072
2321
  async run({ args }) {
2073
2322
  const body = {};
2074
2323
  if (args.group) body.groupSlug = args.group;
2075
- if (args["user-md-file"]) body.userMd = readFileSync5(args["user-md-file"], "utf8");
2324
+ if (args["user-md-file"]) body.userMd = readFileSync6(args["user-md-file"], "utf8");
2076
2325
  const client = createClient2();
2077
2326
  const result = await client.post(
2078
2327
  `/api/profile-groups/${args.id}/spawn`,
@@ -2089,12 +2338,12 @@ var spawnCmd2 = defineCommand12({
2089
2338
  }
2090
2339
  }
2091
2340
  });
2092
- var profileGroupCommand = defineCommand12({
2341
+ var profileGroupCommand = defineCommand13({
2093
2342
  meta: { name: "profile-group", description: "Manage profile groups" },
2094
2343
  subCommands: {
2095
2344
  create: createCmd3,
2096
- list: listCmd7,
2097
- show: showCmd4,
2345
+ list: listCmd8,
2346
+ show: showCmd5,
2098
2347
  update: updateCmd2,
2099
2348
  edit: editCmd3,
2100
2349
  delete: deleteCmd3,
@@ -2103,8 +2352,8 @@ var profileGroupCommand = defineCommand12({
2103
2352
  });
2104
2353
 
2105
2354
  // src/commands/provider.ts
2106
- import { defineCommand as defineCommand13 } from "citty";
2107
- var listCmd8 = defineCommand13({
2355
+ import { defineCommand as defineCommand14 } from "citty";
2356
+ var listCmd9 = defineCommand14({
2108
2357
  meta: {
2109
2358
  name: "list",
2110
2359
  description: "List all providers with enabled/disabled state and curated model counts"
@@ -2130,7 +2379,7 @@ var listCmd8 = defineCommand13({
2130
2379
  for (const line of columnize(rows)) console.log(line);
2131
2380
  }
2132
2381
  });
2133
- var modelsCmd = defineCommand13({
2382
+ var modelsCmd = defineCommand14({
2134
2383
  meta: {
2135
2384
  name: "models",
2136
2385
  description: "Show curated + catalog + live models for one provider"
@@ -2162,7 +2411,7 @@ var modelsCmd = defineCommand13({
2162
2411
  }
2163
2412
  }
2164
2413
  });
2165
- var modelsSetCmd = defineCommand13({
2414
+ var modelsSetCmd = defineCommand14({
2166
2415
  meta: {
2167
2416
  name: "models-set",
2168
2417
  description: "Replace the curated model list for a provider (comma-separated)"
@@ -2187,7 +2436,7 @@ var modelsSetCmd = defineCommand13({
2187
2436
  for (const m of saved.models) console.log(` ${m}`);
2188
2437
  }
2189
2438
  });
2190
- var enableCmd = defineCommand13({
2439
+ var enableCmd2 = defineCommand14({
2191
2440
  meta: { name: "enable", description: "Toggle a provider on so agents can use it" },
2192
2441
  args: {
2193
2442
  name: { type: "positional", required: true, description: "Provider id (e.g. anthropic)" }
@@ -2201,7 +2450,7 @@ var enableCmd = defineCommand13({
2201
2450
  console.log(`${res.name}: enabled`);
2202
2451
  }
2203
2452
  });
2204
- var disableCmd = defineCommand13({
2453
+ var disableCmd2 = defineCommand14({
2205
2454
  meta: {
2206
2455
  name: "disable",
2207
2456
  description: "Toggle a provider off \u2014 agents will refuse its model strings"
@@ -2218,13 +2467,13 @@ var disableCmd = defineCommand13({
2218
2467
  console.log(`${res.name}: disabled`);
2219
2468
  }
2220
2469
  });
2221
- var testCmd = defineCommand13({
2470
+ var testCmd2 = defineCommand14({
2222
2471
  meta: { name: "test", description: "Send a single chat to a model and print the reply" },
2223
2472
  args: {
2224
2473
  model: {
2225
2474
  type: "positional",
2226
2475
  required: true,
2227
- description: "Model string, e.g. anthropic:claude-opus-4-6"
2476
+ description: "Model string, e.g. anthropic:claude-opus-4-8"
2228
2477
  },
2229
2478
  message: { type: "string", description: 'Message text (default "say hi briefly")' }
2230
2479
  },
@@ -2239,21 +2488,21 @@ var testCmd = defineCommand13({
2239
2488
  }
2240
2489
  }
2241
2490
  });
2242
- var providerCommand = defineCommand13({
2491
+ var providerCommand = defineCommand14({
2243
2492
  meta: { name: "provider", description: "Manage and test LLM providers" },
2244
2493
  subCommands: {
2245
- list: listCmd8,
2246
- enable: enableCmd,
2247
- disable: disableCmd,
2494
+ list: listCmd9,
2495
+ enable: enableCmd2,
2496
+ disable: disableCmd2,
2248
2497
  models: modelsCmd,
2249
2498
  "models-set": modelsSetCmd,
2250
- test: testCmd
2499
+ test: testCmd2
2251
2500
  }
2252
2501
  });
2253
2502
 
2254
2503
  // src/commands/send.ts
2255
- import { defineCommand as defineCommand14 } from "citty";
2256
- var sendCommand = defineCommand14({
2504
+ import { defineCommand as defineCommand15 } from "citty";
2505
+ var sendCommand = defineCommand15({
2257
2506
  meta: {
2258
2507
  name: "send",
2259
2508
  description: "Send a message from one agent to another"
@@ -2278,11 +2527,11 @@ var sendCommand = defineCommand14({
2278
2527
  import { spawn as spawn4 } from "child_process";
2279
2528
  import { existsSync as existsSync4 } from "fs";
2280
2529
  import { join as join4 } from "path";
2281
- import { defineCommand as defineCommand15 } from "citty";
2530
+ import { defineCommand as defineCommand16 } from "citty";
2282
2531
  var bundledDaemonEntry = join4(import.meta.dirname, "daemon.js");
2283
2532
  var sourceDaemonEntry = join4(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
2284
2533
  var daemonEntry = existsSync4(bundledDaemonEntry) ? bundledDaemonEntry : sourceDaemonEntry;
2285
- var serveCommand = defineCommand15({
2534
+ var serveCommand = defineCommand16({
2286
2535
  meta: {
2287
2536
  name: "serve",
2288
2537
  description: "Start the bazilion daemon (HTTP API)"
@@ -2349,10 +2598,10 @@ var serveCommand = defineCommand15({
2349
2598
  });
2350
2599
 
2351
2600
  // src/commands/skill.ts
2352
- import { existsSync as existsSync5, readFileSync as readFileSync6, statSync } from "fs";
2353
- import { basename, resolve as resolve2 } from "path";
2354
- import { defineCommand as defineCommand16 } from "citty";
2355
- var listCmd9 = defineCommand16({
2601
+ import { existsSync as existsSync5, readFileSync as readFileSync7, statSync } from "fs";
2602
+ import { basename as basename2, resolve as resolve2 } from "path";
2603
+ import { defineCommand as defineCommand17 } from "citty";
2604
+ var listCmd10 = defineCommand17({
2356
2605
  meta: { name: "list", description: "List installed skills (or those attached to an agent)" },
2357
2606
  args: {
2358
2607
  agent: { type: "string", description: "Filter to skills attached to this agent" }
@@ -2384,7 +2633,7 @@ var listCmd9 = defineCommand16({
2384
2633
  for (const line of columnize(rows)) console.log(line);
2385
2634
  }
2386
2635
  });
2387
- var importCmd = defineCommand16({
2636
+ var importCmd = defineCommand17({
2388
2637
  meta: {
2389
2638
  name: "import",
2390
2639
  description: "Import skills from openclaw, a directory, or a local .zip archive"
@@ -2403,8 +2652,8 @@ var importCmd = defineCommand16({
2403
2652
  const isLocalZip = args.from.toLowerCase().endsWith(".zip") && existsSync5(absFrom) && statSync(absFrom).isFile();
2404
2653
  let result;
2405
2654
  if (isLocalZip) {
2406
- const bytes = readFileSync6(absFrom);
2407
- const file = new File([bytes], basename(absFrom), { type: "application/zip" });
2655
+ const bytes = readFileSync7(absFrom);
2656
+ const file = new File([bytes], basename2(absFrom), { type: "application/zip" });
2408
2657
  const fd = new FormData();
2409
2658
  fd.set("file", file);
2410
2659
  if (args.force) fd.set("force", "true");
@@ -2428,7 +2677,7 @@ var importCmd = defineCommand16({
2428
2677
  }
2429
2678
  }
2430
2679
  });
2431
- var rmCmd4 = defineCommand16({
2680
+ var rmCmd5 = defineCommand17({
2432
2681
  meta: { name: "rm", description: "Remove an installed skill" },
2433
2682
  args: {
2434
2683
  name: { type: "positional", required: true }
@@ -2439,18 +2688,292 @@ var rmCmd4 = defineCommand16({
2439
2688
  console.log(`removed skill ${args.name}`);
2440
2689
  }
2441
2690
  });
2442
- var skillCommand = defineCommand16({
2691
+ var skillCommand = defineCommand17({
2443
2692
  meta: { name: "skill", description: "Manage the skill library" },
2444
2693
  subCommands: {
2445
- list: listCmd9,
2694
+ list: listCmd10,
2446
2695
  import: importCmd,
2447
- rm: rmCmd4
2696
+ rm: rmCmd5
2697
+ }
2698
+ });
2699
+
2700
+ // src/commands/telegram.ts
2701
+ import { defineCommand as defineCommand18 } from "citty";
2702
+ var setCmd2 = defineCommand18({
2703
+ meta: {
2704
+ name: "set",
2705
+ description: "Save bot token + supergroup chat ID (paired write)"
2706
+ },
2707
+ args: {
2708
+ token: { type: "string", required: true, description: "Bot token from @BotFather" },
2709
+ chat: { type: "string", required: true, description: "Numeric supergroup chat ID" }
2710
+ },
2711
+ async run({ args }) {
2712
+ const client = createClient2();
2713
+ const state = await client.put("/api/config/telegram", {
2714
+ botToken: args.token,
2715
+ chatId: args.chat
2716
+ });
2717
+ console.log(`saved \xB7 token ${state.botTokenPreview} \xB7 chat ${state.chatId}`);
2718
+ }
2719
+ });
2720
+ var clearCmd = defineCommand18({
2721
+ meta: {
2722
+ name: "clear",
2723
+ description: "Remove stored bot token + chat ID"
2724
+ },
2725
+ async run() {
2726
+ const client = createClient2();
2727
+ await client.del("/api/config/telegram");
2728
+ console.log("cleared");
2729
+ }
2730
+ });
2731
+ var showCmd6 = defineCommand18({
2732
+ meta: {
2733
+ name: "show",
2734
+ description: "Show what credentials are stored (token is masked)"
2735
+ },
2736
+ async run() {
2737
+ const client = createClient2();
2738
+ const state = await client.get("/api/config/telegram");
2739
+ if (!state.configured) {
2740
+ console.log("(no credentials saved \u2014 run `bazilion telegram config set --token \u2026 --chat \u2026`)");
2741
+ return;
2742
+ }
2743
+ console.log(`token: ${state.botTokenPreview}`);
2744
+ console.log(`chat: ${state.chatId}`);
2745
+ if (state.migratedChatId) {
2746
+ console.log(
2747
+ `\u26A0 supergroup migrated \u2192 ${state.migratedChatId}. Run \`bazilion telegram reconnect\` to apply.`
2748
+ );
2749
+ }
2750
+ }
2751
+ });
2752
+ var reconnectCmd = defineCommand18({
2753
+ meta: {
2754
+ name: "reconnect",
2755
+ description: "Apply a pending supergroup chat-id migration + re-activate the bot"
2756
+ },
2757
+ async run() {
2758
+ const client = createClient2();
2759
+ const state = await client.post("/api/config/telegram/reconnect");
2760
+ console.log(`reconnected \xB7 chat ${state.chatId}`);
2761
+ }
2762
+ });
2763
+ var configCmd = defineCommand18({
2764
+ meta: {
2765
+ name: "config",
2766
+ description: "Manage Telegram credentials (bot token + chat ID)"
2767
+ },
2768
+ subCommands: {
2769
+ set: setCmd2,
2770
+ clear: clearCmd,
2771
+ show: showCmd6
2772
+ }
2773
+ });
2774
+ var healthCmd = defineCommand18({
2775
+ meta: {
2776
+ name: "health",
2777
+ description: "Run the four-step preflight against the Telegram Bot API"
2778
+ },
2779
+ async run() {
2780
+ const client = createClient2();
2781
+ const h = await client.get("/api/config/telegram/health");
2782
+ if (!h.configured) {
2783
+ console.log("not configured \u2014 run `bazilion telegram config set` first");
2784
+ process.exitCode = 1;
2785
+ return;
2786
+ }
2787
+ if (h.error) {
2788
+ console.error(`error at ${h.error.step}: ${h.error.message}`);
2789
+ process.exitCode = 1;
2790
+ return;
2791
+ }
2792
+ if (!h.preflight) {
2793
+ console.error("preflight returned no data");
2794
+ process.exitCode = 1;
2795
+ return;
2796
+ }
2797
+ const p = h.preflight;
2798
+ const line = (ok, label, detail) => `${ok ? "\u2713" : "\u2715"} ${label.padEnd(30)} ${detail}`;
2799
+ console.log(line(p.botUsername.length > 0, "bot identity", `@${p.botUsername}`));
2800
+ console.log(line(p.chatTitle.length > 0, "supergroup reachable", p.chatTitle));
2801
+ console.log(line(p.isForum, "forum topics enabled", String(p.isForum)));
2802
+ console.log(line(p.hasManageTopics, "can_manage_topics", String(p.hasManageTopics)));
2803
+ console.log(line(p.privacyModeOff, "Privacy Mode is OFF", String(p.privacyModeOff)));
2804
+ const allOk = p.botUsername.length > 0 && p.chatTitle.length > 0 && p.isForum && p.hasManageTopics && p.privacyModeOff;
2805
+ if (!allOk) process.exitCode = 1;
2806
+ }
2807
+ });
2808
+ var botStatusCmd = defineCommand18({
2809
+ meta: {
2810
+ name: "status",
2811
+ description: "Show polling state of the live bot"
2812
+ },
2813
+ async run() {
2814
+ const client = createClient2();
2815
+ const h = await client.get("/api/config/telegram/health");
2816
+ if (!h.polling) {
2817
+ console.log("bot: not running");
2818
+ process.exitCode = 1;
2819
+ return;
2820
+ }
2821
+ const p = h.polling;
2822
+ const startedAt = p.startedAt ? new Date(p.startedAt).toISOString() : "(never)";
2823
+ const lastPoll = p.lastSuccessfulPollAt ? new Date(p.lastSuccessfulPollAt).toISOString() : "(never)";
2824
+ console.log(`running: ${p.running}`);
2825
+ console.log(`activated: ${p.activated}`);
2826
+ console.log(`started at: ${startedAt}`);
2827
+ console.log(`last update id: ${p.lastUpdateId ?? "(none)"}`);
2828
+ console.log(`last successful: ${lastPoll}`);
2829
+ if (p.error) console.log(`error: ${p.error}`);
2830
+ if (!p.running) process.exitCode = 1;
2831
+ }
2832
+ });
2833
+ var botRestartCmd = defineCommand18({
2834
+ meta: {
2835
+ name: "restart",
2836
+ description: "Force-restart the bot (tears down + brings up from current creds)"
2837
+ },
2838
+ async run() {
2839
+ const client = createClient2();
2840
+ await client.post("/api/config/telegram/restart");
2841
+ console.log("restart requested");
2842
+ }
2843
+ });
2844
+ var botCmd = defineCommand18({
2845
+ meta: {
2846
+ name: "bot",
2847
+ description: "Inspect / control the live polling bot"
2848
+ },
2849
+ subCommands: {
2850
+ status: botStatusCmd,
2851
+ restart: botRestartCmd
2852
+ }
2853
+ });
2854
+ var bindCmd = defineCommand18({
2855
+ meta: {
2856
+ name: "bind",
2857
+ description: "Create a Telegram topic for an agent (manual fallback for /talk)"
2858
+ },
2859
+ args: {
2860
+ agent: { type: "positional", required: true, description: "Agent id or prefix" }
2861
+ },
2862
+ async run({ args }) {
2863
+ const client = createClient2();
2864
+ const result = await client.post(
2865
+ `/api/agents/${args.agent}/telegram/bind`
2866
+ );
2867
+ const verb = result.created ? "created topic" : "already bound to";
2868
+ console.log(`${verb} #${result.topicId} for agent ${result.agent.name} (${result.agent.id})`);
2869
+ console.log(` ${result.deepLink}`);
2870
+ }
2871
+ });
2872
+ var unbindCmd = defineCommand18({
2873
+ meta: {
2874
+ name: "unbind",
2875
+ description: "Clear an agent's Telegram topic binding (topic stays in Telegram as orphan)"
2876
+ },
2877
+ args: {
2878
+ agent: { type: "positional", required: true, description: "Agent id or prefix" }
2879
+ },
2880
+ async run({ args }) {
2881
+ const client = createClient2();
2882
+ await client.del(`/api/agents/${args.agent}/telegram/binding`);
2883
+ console.log(`unbound agent ${args.agent}`);
2884
+ }
2885
+ });
2886
+ var listBindingsCmd = defineCommand18({
2887
+ meta: {
2888
+ name: "list",
2889
+ description: "List agents and their Telegram topic bindings"
2890
+ },
2891
+ async run() {
2892
+ const client = createClient2();
2893
+ const agents = await client.get("/api/agents");
2894
+ const bound = agents.filter((a) => a.telegramTopicId !== null);
2895
+ const unbound = agents.filter((a) => a.telegramTopicId === null);
2896
+ if (bound.length === 0 && unbound.length === 0) {
2897
+ console.log("(no agents)");
2898
+ return;
2899
+ }
2900
+ if (bound.length > 0) {
2901
+ console.log("bound:");
2902
+ for (const a of bound) {
2903
+ console.log(` #${a.telegramTopicId} ${a.name} (group: ${a.groupId})`);
2904
+ }
2905
+ }
2906
+ if (unbound.length > 0) {
2907
+ console.log("unbound:");
2908
+ for (const a of unbound) {
2909
+ console.log(` \u2014 ${a.name} (group: ${a.groupId})`);
2910
+ }
2911
+ }
2912
+ }
2913
+ });
2914
+ var allowCmd = defineCommand18({
2915
+ meta: { name: "allow", description: "Add a Telegram user id to the allowlist" },
2916
+ args: {
2917
+ userId: { type: "positional", required: true, description: "Numeric Telegram user id" },
2918
+ label: { type: "string", description: "Optional human label" },
2919
+ owner: { type: "boolean", description: "Grant owner role (can manage the allowlist)" }
2920
+ },
2921
+ async run({ args }) {
2922
+ const client = createClient2();
2923
+ const u = await client.post("/api/config/telegram/acl", {
2924
+ userId: Number(args.userId),
2925
+ label: args.label ?? null,
2926
+ role: args.owner ? "owner" : "member"
2927
+ });
2928
+ console.log(`allowed ${u.userId} (${u.role})`);
2929
+ }
2930
+ });
2931
+ var denyCmd = defineCommand18({
2932
+ meta: { name: "deny", description: "Remove a Telegram user id from the allowlist" },
2933
+ args: { userId: { type: "positional", required: true } },
2934
+ async run({ args }) {
2935
+ const client = createClient2();
2936
+ await client.del(`/api/config/telegram/acl/${Number(args.userId)}`);
2937
+ console.log(`removed ${args.userId}`);
2938
+ }
2939
+ });
2940
+ var allowedCmd = defineCommand18({
2941
+ meta: { name: "allowed", description: "List allowlisted Telegram users" },
2942
+ async run() {
2943
+ const client = createClient2();
2944
+ const users = await client.get("/api/config/telegram/acl");
2945
+ if (users.length === 0) {
2946
+ console.log("(allowlist empty \u2014 open; first user to message becomes owner)");
2947
+ return;
2948
+ }
2949
+ for (const u of users) {
2950
+ const who = u.label ?? (u.username ? `@${u.username}` : "\u2014");
2951
+ console.log(`${u.userId} ${u.role} ${who}`);
2952
+ }
2953
+ }
2954
+ });
2955
+ var telegramCommand = defineCommand18({
2956
+ meta: {
2957
+ name: "telegram",
2958
+ description: "Telegram integration: credentials, health, bot lifecycle, bindings, access"
2959
+ },
2960
+ subCommands: {
2961
+ config: configCmd,
2962
+ health: healthCmd,
2963
+ bot: botCmd,
2964
+ reconnect: reconnectCmd,
2965
+ bind: bindCmd,
2966
+ unbind: unbindCmd,
2967
+ list: listBindingsCmd,
2968
+ allow: allowCmd,
2969
+ deny: denyCmd,
2970
+ allowed: allowedCmd
2448
2971
  }
2449
2972
  });
2450
2973
 
2451
2974
  // src/commands/token.ts
2452
2975
  import { networkInterfaces } from "os";
2453
- import { defineCommand as defineCommand17 } from "citty";
2976
+ import { defineCommand as defineCommand19 } from "citty";
2454
2977
  import qrcode from "qrcode-terminal";
2455
2978
  function tokenRow(t) {
2456
2979
  const last = t.lastUsedAt ? new Date(t.lastUsedAt).toISOString() : "(never)";
@@ -2484,7 +3007,7 @@ function resolveQrServer(override) {
2484
3007
  if (detected.warning) console.warn(`\u26A0 ${detected.warning}`);
2485
3008
  return detected.origin;
2486
3009
  }
2487
- var createCmd4 = defineCommand17({
3010
+ var createCmd4 = defineCommand19({
2488
3011
  meta: { name: "create", description: "Mint a new web token (shown once)" },
2489
3012
  args: {
2490
3013
  label: { type: "positional", required: true, description: "Human-readable label" },
@@ -2515,7 +3038,7 @@ var createCmd4 = defineCommand17({
2515
3038
  qrcode.generate(pairUrl, { small: true }, (qr) => console.log(qr));
2516
3039
  }
2517
3040
  });
2518
- var listCmd10 = defineCommand17({
3041
+ var listCmd11 = defineCommand19({
2519
3042
  meta: { name: "list", description: "List web tokens" },
2520
3043
  args: {
2521
3044
  all: { type: "boolean", description: "Include revoked tokens" }
@@ -2531,7 +3054,7 @@ var listCmd10 = defineCommand17({
2531
3054
  for (const line of columnize(tokens.map(tokenRow))) console.log(line);
2532
3055
  }
2533
3056
  });
2534
- var showLocalCmd = defineCommand17({
3057
+ var showLocalCmd = defineCommand19({
2535
3058
  meta: {
2536
3059
  name: "show-local",
2537
3060
  description: "Print the bootstrap web token stored in ~/.bazilion/auth.json"
@@ -2541,7 +3064,7 @@ var showLocalCmd = defineCommand17({
2541
3064
  console.log(readAuthFile(paths.authFile).token);
2542
3065
  }
2543
3066
  });
2544
- var revokeCmd = defineCommand17({
3067
+ var revokeCmd = defineCommand19({
2545
3068
  meta: { name: "revoke", description: "Revoke a web token" },
2546
3069
  args: {
2547
3070
  id: { type: "positional", required: true }
@@ -2552,19 +3075,19 @@ var revokeCmd = defineCommand17({
2552
3075
  console.log(`revoked token ${args.id}`);
2553
3076
  }
2554
3077
  });
2555
- var tokenCommand = defineCommand17({
3078
+ var tokenCommand = defineCommand19({
2556
3079
  meta: { name: "token", description: "Manage web tokens for API/CLI clients" },
2557
3080
  subCommands: {
2558
3081
  create: createCmd4,
2559
- list: listCmd10,
3082
+ list: listCmd11,
2560
3083
  revoke: revokeCmd,
2561
3084
  "show-local": showLocalCmd
2562
3085
  }
2563
3086
  });
2564
3087
 
2565
3088
  // src/commands/trigger.ts
2566
- import { defineCommand as defineCommand18 } from "citty";
2567
- var addCmd2 = defineCommand18({
3089
+ import { defineCommand as defineCommand20 } from "citty";
3090
+ var addCmd3 = defineCommand20({
2568
3091
  meta: { name: "add", description: "Add a heartbeat / cron trigger to an agent" },
2569
3092
  args: {
2570
3093
  agent: { type: "positional", required: true },
@@ -2612,7 +3135,7 @@ function triggerRow(t) {
2612
3135
  const msgPreview = t.message.length > 60 ? `${t.message.slice(0, 60)}\u2026` : t.message;
2613
3136
  return [t.id, state, spec, `last: ${last}`, `"${msgPreview}"`];
2614
3137
  }
2615
- var listCmd11 = defineCommand18({
3138
+ var listCmd12 = defineCommand20({
2616
3139
  meta: { name: "list", description: "List triggers for an agent" },
2617
3140
  args: {
2618
3141
  agent: { type: "positional", required: true }
@@ -2629,7 +3152,7 @@ var listCmd11 = defineCommand18({
2629
3152
  for (const line of columnize(triggers.map(triggerRow))) console.log(line);
2630
3153
  }
2631
3154
  });
2632
- var rmCmd5 = defineCommand18({
3155
+ var rmCmd6 = defineCommand20({
2633
3156
  meta: { name: "rm", description: "Delete a trigger" },
2634
3157
  args: {
2635
3158
  id: { type: "positional", required: true }
@@ -2640,7 +3163,7 @@ var rmCmd5 = defineCommand18({
2640
3163
  console.log(`removed trigger ${args.id}`);
2641
3164
  }
2642
3165
  });
2643
- var enableCmd2 = defineCommand18({
3166
+ var enableCmd3 = defineCommand20({
2644
3167
  meta: { name: "enable", description: "Enable a trigger" },
2645
3168
  args: {
2646
3169
  id: { type: "positional", required: true }
@@ -2652,7 +3175,7 @@ var enableCmd2 = defineCommand18({
2652
3175
  console.log(`enabled trigger ${args.id}`);
2653
3176
  }
2654
3177
  });
2655
- var disableCmd2 = defineCommand18({
3178
+ var disableCmd3 = defineCommand20({
2656
3179
  meta: { name: "disable", description: "Disable a trigger" },
2657
3180
  args: {
2658
3181
  id: { type: "positional", required: true }
@@ -2664,21 +3187,21 @@ var disableCmd2 = defineCommand18({
2664
3187
  console.log(`disabled trigger ${args.id}`);
2665
3188
  }
2666
3189
  });
2667
- var triggerCommand = defineCommand18({
3190
+ var triggerCommand = defineCommand20({
2668
3191
  meta: { name: "trigger", description: "Manage agent heartbeats / cron triggers" },
2669
3192
  subCommands: {
2670
- add: addCmd2,
2671
- list: listCmd11,
2672
- rm: rmCmd5,
2673
- enable: enableCmd2,
2674
- disable: disableCmd2
3193
+ add: addCmd3,
3194
+ list: listCmd12,
3195
+ rm: rmCmd6,
3196
+ enable: enableCmd3,
3197
+ disable: disableCmd3
2675
3198
  }
2676
3199
  });
2677
3200
 
2678
3201
  // src/commands/uninstall.ts
2679
3202
  import { existsSync as existsSync6, readdirSync as readdirSync2, rmSync as rmSync4 } from "fs";
2680
3203
  import { join as join5 } from "path";
2681
- import { defineCommand as defineCommand19 } from "citty";
3204
+ import { defineCommand as defineCommand21 } from "citty";
2682
3205
  function makeLineReader() {
2683
3206
  let buffer = "";
2684
3207
  let ended = false;
@@ -2726,7 +3249,7 @@ function removePath(p) {
2726
3249
  rmSync4(p, { recursive: true, force: true });
2727
3250
  return true;
2728
3251
  }
2729
- var uninstallCommand = defineCommand19({
3252
+ var uninstallCommand = defineCommand21({
2730
3253
  meta: {
2731
3254
  name: "uninstall",
2732
3255
  description: "Wipe bazilion state from ~/.bazilion (or BAZILION_HOME)"
@@ -2804,7 +3327,7 @@ var uninstallCommand = defineCommand19({
2804
3327
 
2805
3328
  // src/index.ts
2806
3329
  var VERSION = package_default.version;
2807
- var main = defineCommand20({
3330
+ var main = defineCommand22({
2808
3331
  meta: {
2809
3332
  name: "bazilion",
2810
3333
  version: VERSION,
@@ -2818,6 +3341,7 @@ var main = defineCommand20({
2818
3341
  agent: agentCommand,
2819
3342
  skill: skillCommand,
2820
3343
  memory: memoryCommand,
3344
+ mcp: mcpCommand,
2821
3345
  provider: providerCommand,
2822
3346
  send: sendCommand,
2823
3347
  inbox: inboxCommand,
@@ -2828,6 +3352,7 @@ var main = defineCommand20({
2828
3352
  trigger: triggerCommand,
2829
3353
  token: tokenCommand,
2830
3354
  auth: authCommand,
3355
+ telegram: telegramCommand,
2831
3356
  uninstall: uninstallCommand
2832
3357
  }
2833
3358
  });
@@ -2903,6 +3428,10 @@ function printTopLevelHelp() {
2903
3428
  ["trigger", "Manage agent heartbeats / cron triggers"]
2904
3429
  ]
2905
3430
  },
3431
+ {
3432
+ title: "integrations",
3433
+ items: [["telegram", "Telegram bot setup, health, lifecycle"]]
3434
+ },
2906
3435
  {
2907
3436
  title: "ops",
2908
3437
  items: [["backup", "Download a tar.gz backup of ~/.bazilion"]]