bazilion 0.7.0 → 0.9.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.
Files changed (166) hide show
  1. package/README.md +47 -5
  2. package/dist/cli.js +1257 -638
  3. package/dist/cli.js.map +1 -1
  4. package/dist/daemon.js +5334 -1594
  5. package/dist/daemon.js.map +1 -1
  6. package/dist/migrations/0001_init.sql +318 -88
  7. package/dist/web/client/assets/{FieldRow-CNKma5LE.js → FieldRow-DmwAFfbF.js} +1 -1
  8. package/dist/web/client/assets/ProductionTeamPolicyEditor-1a5jQqUB.js +7 -0
  9. package/dist/web/client/assets/ProductionTeamPolicyEditor-DLioOiRN.css +1 -0
  10. package/dist/web/client/assets/ProfileCommunicationEditor-D1OZ8WE5.js +1 -0
  11. package/dist/web/client/assets/RecoveryState-QfMSuwy3.js +1 -0
  12. package/dist/web/client/assets/TeamTabs-BViZ4sti.js +1 -0
  13. package/dist/web/client/assets/TemplatesTabs-DVcY9pMD.js +1 -0
  14. package/dist/web/client/assets/_id-8P7brhGy.js +1 -0
  15. package/dist/web/client/assets/_id-C3o3MHq8.js +1 -0
  16. package/dist/web/client/assets/_id-DGRrSF1e.js +1 -0
  17. package/dist/web/client/assets/_id-DGyKURCp.js +1 -0
  18. package/dist/web/client/assets/_id-KnJe-aW9.js +1 -0
  19. package/dist/web/client/assets/activity-DJuhhQCb.js +1 -0
  20. package/dist/web/client/assets/activity-WWvJSo4t.js +1 -0
  21. package/dist/web/client/assets/agents-C32T1voV.js +1 -0
  22. package/dist/web/client/assets/agents-nH4m4gZ1.js +1 -0
  23. package/dist/web/client/assets/approvals-DGi0PSx8.js +1 -0
  24. package/dist/web/client/assets/approvals-l8jIZjqz.js +1 -0
  25. package/dist/web/client/assets/{config-BSAVT-17.js → config-C7wvi1nR.js} +2 -2
  26. package/dist/web/client/assets/context-BEGWE3RC.js +1 -0
  27. package/dist/web/client/assets/inbox--4aBaAgG.js +1 -0
  28. package/dist/web/client/assets/index-BCXoh1c8.js +12 -0
  29. package/dist/web/client/assets/{login-D8lNr2SX.js → login-Bk2wwIHQ.js} +1 -1
  30. package/dist/web/client/assets/{mcp-BLnngDsj.js → mcp-vM7xgh9e.js} +1 -1
  31. package/dist/web/client/assets/members-cPKfnrSL.js +1 -0
  32. package/dist/web/client/assets/memory-BOcsaemD.js +1 -0
  33. package/dist/web/client/assets/policy-BGLCJYvS.js +1 -0
  34. package/dist/web/client/assets/policy-K4hIbbIN.js +1 -0
  35. package/dist/web/client/assets/{preload-helper-CvnapA2_.js → preload-helper-eOOCz1Fu.js} +1 -1
  36. package/dist/web/client/assets/routes-DnrP3dwv.js +1 -0
  37. package/dist/web/client/assets/services-C2_O3ifw.js +1 -0
  38. package/dist/web/client/assets/skills-B__fLZjx.js +1 -0
  39. package/dist/web/client/assets/styles-Dn24-ZvP.css +2 -0
  40. package/dist/web/client/assets/team-policy-BdX340m4.js +1 -0
  41. package/dist/web/client/assets/teams-CSNyLz3l.js +1 -0
  42. package/dist/web/client/assets/teams-DZMB4_iw.js +1 -0
  43. package/dist/web/client/assets/teams-rpaYKNIb.js +1 -0
  44. package/dist/web/client/assets/telegram-B1O4Ko0V.js +1 -0
  45. package/dist/web/client/assets/{tokens-D2_O9ARe.js → tokens-D7FH9VgA.js} +1 -1
  46. package/dist/web/client/assets/triggers-3PLy2_Fo.js +1 -0
  47. package/dist/web/client/assets/welcome-B-QQobzq.js +1 -0
  48. package/dist/web/client/assets/{ChatPane-DzEgOEqS.js → wire-constants-BY9Q9Z7d.js} +4 -4
  49. package/dist/web/server/assets/{ChatPane-BvpswYvF.js → ChatPane-Dh3qxzdb.js} +23 -12
  50. package/dist/web/server/assets/ProductionTeamPolicyEditor-Bke5doyl.js +1009 -0
  51. package/dist/web/server/assets/ProfileCommunicationEditor-C2RU-2QB.js +107 -0
  52. package/dist/web/server/assets/RecoveryState-B2SG-mrY.js +37 -0
  53. package/dist/web/server/assets/{Sidebar-DmEiewRN.js → Sidebar-CGmtCnYU.js} +372 -48
  54. package/dist/web/server/assets/TeamTabs-BPxDBfqy.js +50 -0
  55. package/dist/web/server/assets/{TemplatesTabs---7h5GYa.js → TemplatesTabs-zf4YhStd.js} +6 -6
  56. package/dist/web/server/assets/{_id-CXg-Blec.js → _id-5lLzLwcv.js} +52 -40
  57. package/dist/web/server/assets/_id-A8Xiv6Lc.js +11 -0
  58. package/dist/web/server/assets/{_id-BqnDy_Ca.js → _id-B04VaQlh.js} +6 -5
  59. package/dist/web/server/assets/{_id-D0ytyXGY.js → _id-B6g9wmPR.js} +167 -31
  60. package/dist/web/server/assets/_id-ButXHnRH.js +14 -0
  61. package/dist/web/server/assets/_id-C4AOhstq.js +44 -0
  62. package/dist/web/server/assets/{_id-DDixKEud.js → _id-CCHA0gdR.js} +72 -12
  63. package/dist/web/server/assets/{_id-D_Ew11ED.js → _id-CUWgTqMS.js} +8 -8
  64. package/dist/web/server/assets/_id-DJkzwHjM.js +42 -0
  65. package/dist/web/server/assets/{_id-CnQflrRv.js → _id-DdC9wpNN.js} +5 -5
  66. package/dist/web/server/assets/{_id-81NrHA5d.js → _id-DkFgCIb-.js} +9 -1
  67. package/dist/web/server/assets/{_id-D8duqgd5.js → _id-_nFwi9gD.js} +5 -4
  68. package/dist/web/server/assets/{_id-Sjw0zhA6.js → _id-fpFQ9_Ya.js} +4 -4
  69. package/dist/web/server/assets/_tanstack-start-manifest_v-Div-TukY.js +241 -0
  70. package/dist/web/server/assets/activity-C2ZKg1Q9.js +170 -0
  71. package/dist/web/server/assets/activity-CGCf8BQf.js +11 -0
  72. package/dist/web/server/assets/activity-DedraoFj.js +14 -0
  73. package/dist/web/server/assets/activity-GPx8NCeB.js +12 -0
  74. package/dist/web/server/assets/{profiles-CZ5NkmVw.js → agents-B8kinIPW.js} +4 -4
  75. package/dist/web/server/assets/{agents-k5QURC4I.js → agents-BR2qXlXF.js} +4 -4
  76. package/dist/web/server/assets/{agents-ChcAJUI5.js → agents-Bp1nsVs2.js} +1 -1
  77. package/dist/web/server/assets/{profiles-LxcC_L6n.js → agents-CUQmWhTp.js} +36 -10
  78. package/dist/web/server/assets/{agents-C7SBPN0M.js → agents-DU9Hqs58.js} +51 -12
  79. package/dist/web/server/assets/{profiles-C6a3RKgu.js → agents-LHowEI6S.js} +4 -4
  80. package/dist/web/server/assets/approvals-CbFXFvG8.js +11 -0
  81. package/dist/web/server/assets/approvals-DHgARzd8.js +242 -0
  82. package/dist/web/server/assets/approvals-Dw2LJoSA.js +14 -0
  83. package/dist/web/server/assets/approvals-VPc0YpLN.js +12 -0
  84. package/dist/web/server/assets/{auth-DzRAMwVt.js → auth-l-Vf8wlu.js} +5 -1
  85. package/dist/web/server/assets/{config-CdVjqjin.js → config-BvKctDOX.js} +4 -4
  86. package/dist/web/server/assets/{config-Bq3o924J.js → config-QvHaxGlP.js} +1 -1
  87. package/dist/web/server/assets/context-5lrf2ame.js +12 -0
  88. package/dist/web/server/assets/context-CEr4-xiA.js +49 -0
  89. package/dist/web/server/assets/context-D3Egm-vY.js +12 -0
  90. package/dist/web/server/assets/members-40DxRdVj.js +48 -0
  91. package/dist/web/server/assets/members-DlGBKZNl.js +12 -0
  92. package/dist/web/server/assets/members-ksELRsyk.js +12 -0
  93. package/dist/web/server/assets/{memory-Ns2-Z31p.js → memory-B5moRnnp.js} +5 -5
  94. package/dist/web/server/assets/{memory-BaYnfm7K.js → memory-CO0jKGzJ.js} +8 -8
  95. package/dist/web/server/assets/memory-CiTl4cN9.js +289 -0
  96. package/dist/web/server/assets/policy-BYVXqsan.js +11 -0
  97. package/dist/web/server/assets/policy-DNcGZLOB.js +21 -0
  98. package/dist/web/server/assets/policy-Dr55y-Mh.js +496 -0
  99. package/dist/web/server/assets/policy-Dxs78_GO.js +40 -0
  100. package/dist/web/server/assets/{router-BpBZgRwn.js → router-_izWQUeG.js} +156 -101
  101. package/dist/web/server/assets/{routes-Ce2VWrU9.js → routes-BSSKp3Rv.js} +4 -4
  102. package/dist/web/server/assets/{routes-C61gBiXa.js → routes-BrTOoeth.js} +5 -5
  103. package/dist/web/server/assets/{routes-V9URcp1v.js → routes-DOj6ljcm.js} +1 -1
  104. package/dist/web/server/assets/{services-B91w2f-X.js → services-CHe4ihJk.js} +11 -11
  105. package/dist/web/server/assets/{services-Ccc5s2bS.js → services-Pv_V88VA.js} +3 -3
  106. package/dist/web/server/assets/{skills-dLyBZb3B.js → skills-D89ND2kR.js} +67 -7
  107. package/dist/web/server/assets/{skills-CpsyR_WA.js → skills-l2cyQ3zS.js} +1 -1
  108. package/dist/web/server/assets/{start-CYDpZ6cb.js → start-DlHq0RaQ.js} +1 -1
  109. package/dist/web/server/assets/team-policy-Csvc5EDd.js +180 -0
  110. package/dist/web/server/assets/teams-35Oprf6e.js +14 -0
  111. package/dist/web/server/assets/teams-3im0oQnS.js +11 -0
  112. package/dist/web/server/assets/teams-B5IF65p2.js +12 -0
  113. package/dist/web/server/assets/teams-B9O-WDH5.js +108 -0
  114. package/dist/web/server/assets/teams-DFkN7ic7.js +36 -0
  115. package/dist/web/server/assets/teams-DH1CvWmT.js +12 -0
  116. package/dist/web/server/assets/teams-zcm9XaQU.js +174 -0
  117. package/dist/web/server/assets/{telegram-DfAddLdv.js → telegram-C9sQFwWj.js} +7 -7
  118. package/dist/web/server/assets/{telegram-T3l9KtiE.js → telegram-mTnJCOmn.js} +1 -1
  119. package/dist/web/server/assets/{welcome-CP4CZ9B6.js → welcome-CDGE2Sdk.js} +2 -2
  120. package/dist/web/server/assets/{wire-constants-Deb4NxBb.js → wire-constants-C8nBJcU3.js} +3 -3
  121. package/dist/web/server/server.js +64 -42
  122. package/dist/worker.js +180 -128
  123. package/dist/worker.js.map +1 -1
  124. package/package.json +7 -7
  125. package/dist/migrations/0002_profile_groups.sql +0 -38
  126. package/dist/migrations/0003_agent_telegram.sql +0 -40
  127. package/dist/migrations/0004_agent_mirror_mode.sql +0 -17
  128. package/dist/migrations/0005_group_topic_name_format.sql +0 -15
  129. package/dist/migrations/0006_telegram_acl.sql +0 -18
  130. package/dist/migrations/0007_mcp_servers.sql +0 -30
  131. package/dist/migrations/0008_seed_user_md.sql +0 -39
  132. package/dist/web/client/assets/MembersEditor-C6UpqDdV.js +0 -1
  133. package/dist/web/client/assets/SpawnTeamModal-BEkNCKXm.js +0 -1
  134. package/dist/web/client/assets/TemplatesTabs-Da7mg9FI.js +0 -1
  135. package/dist/web/client/assets/_id-BdKmo0gb.js +0 -1
  136. package/dist/web/client/assets/_id-LT6Ejjr0.js +0 -1
  137. package/dist/web/client/assets/_id-MR2XjWh0.js +0 -1
  138. package/dist/web/client/assets/_id-_6jIt0_-.js +0 -1
  139. package/dist/web/client/assets/agents-0arKbVYG.js +0 -1
  140. package/dist/web/client/assets/groups-BqTkhHes.js +0 -1
  141. package/dist/web/client/assets/inbox-ozoCXzr5.js +0 -1
  142. package/dist/web/client/assets/index-iayCEuU2.js +0 -12
  143. package/dist/web/client/assets/memory-D1GQjEvN.js +0 -1
  144. package/dist/web/client/assets/profile-groups-C2yJPTaE.js +0 -1
  145. package/dist/web/client/assets/profiles-BV7AAZjj.js +0 -1
  146. package/dist/web/client/assets/routes-DSHQLA7K.js +0 -1
  147. package/dist/web/client/assets/services-BbCJe1Du.js +0 -1
  148. package/dist/web/client/assets/skills-C6czKR5I.js +0 -1
  149. package/dist/web/client/assets/styles-C06axZZk.css +0 -2
  150. package/dist/web/client/assets/telegram-gE4j8gte.js +0 -1
  151. package/dist/web/client/assets/triggers-WljnfEfJ.js +0 -1
  152. package/dist/web/client/assets/welcome-Dn-zvmBE.js +0 -1
  153. package/dist/web/client/assets/wire-constants-BkT5-597.js +0 -1
  154. package/dist/web/server/assets/MembersEditor-BWQztvrX.js +0 -131
  155. package/dist/web/server/assets/SpawnTeamModal-dSN421k_.js +0 -107
  156. package/dist/web/server/assets/_id-BKev9H1p.js +0 -12
  157. package/dist/web/server/assets/_id-BNwlbWHP.js +0 -24
  158. package/dist/web/server/assets/_id-CRqqi8IE.js +0 -161
  159. package/dist/web/server/assets/_tanstack-start-manifest_v-DBlFH2gg.js +0 -178
  160. package/dist/web/server/assets/groups-CbSwND2r.js +0 -12
  161. package/dist/web/server/assets/groups-CeRRlZaZ.js +0 -150
  162. package/dist/web/server/assets/groups-pk4CYSuf.js +0 -21
  163. package/dist/web/server/assets/memory-CQaqWnyM.js +0 -284
  164. package/dist/web/server/assets/profile-groups-CiU06yN1.js +0 -28
  165. package/dist/web/server/assets/profile-groups-D21MYoLM.js +0 -208
  166. package/dist/web/server/assets/profile-groups-aoJleXHP.js +0 -12
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { defineCommand as defineCommand23, runCommand, showUsage } from "citty";
4
+ import { defineCommand as defineCommand25, runCommand, showUsage } from "citty";
5
5
 
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "bazilion",
9
- version: "0.7.0",
10
- description: "Multi-agent runtime CLI \u2014 spawn LLM agents, manage profiles/groups/skills, and run the local daemon.",
9
+ version: "0.9.0",
10
+ description: "Multi-agent runtime CLI \u2014 spawn LLM agents, manage profiles/teams/skills, and run the local daemon.",
11
11
  license: "MIT",
12
12
  repository: {
13
13
  type: "git",
@@ -49,9 +49,9 @@ var package_default = {
49
49
  access: "public"
50
50
  },
51
51
  dependencies: {
52
- "@earendil-works/pi-agent-core": "^0.79.10",
53
- "@earendil-works/pi-ai": "^0.79.10",
54
- "@earendil-works/pi-coding-agent": "^0.79.10",
52
+ "@earendil-works/pi-agent-core": "^0.80.6",
53
+ "@earendil-works/pi-ai": "^0.80.6",
54
+ "@earendil-works/pi-coding-agent": "^0.80.6",
55
55
  "@hono/node-server": "^2.0.6",
56
56
  "@mozilla/readability": "^0.6.0",
57
57
  "@tanstack/react-router": "1.170.16",
@@ -277,13 +277,13 @@ function asPaths(v) {
277
277
  return v ? Array.isArray(v) ? v : [v] : [];
278
278
  }
279
279
  var spawnCmd = defineCommand({
280
- meta: { name: "spawn", description: "Spawn an agent from a profile into a group" },
280
+ meta: { name: "spawn", description: "Spawn an agent from a profile into a team" },
281
281
  args: {
282
282
  profile: { type: "string", required: true, description: "Profile id" },
283
283
  name: { type: "string", description: "Agent name (defaults to profile name)" },
284
- group: {
284
+ team: {
285
285
  type: "string",
286
- description: "Group to join (defaults to 'default')"
286
+ description: "Team to join (defaults to 'default')"
287
287
  },
288
288
  model: { type: "string", description: "Override profile default model" },
289
289
  reasoning: {
@@ -293,14 +293,21 @@ var spawnCmd = defineCommand({
293
293
  },
294
294
  async run({ args }) {
295
295
  const client = createClient2();
296
+ const teamId = args.team ?? "default";
297
+ const policy = await client.get(
298
+ `/api/teams/${encodeURIComponent(teamId)}/policy`
299
+ );
296
300
  const body = {
297
301
  profileId: args.profile,
298
302
  name: args.name,
299
303
  model: args.model,
300
304
  reasoningLevel: args.reasoning,
301
- groupId: args.group
305
+ teamId,
306
+ teamExpectedRevision: policy.teamPolicy.revision,
307
+ placement: "open"
302
308
  };
303
- const agent = await client.post("/api/agents", body);
309
+ const response = await client.post("/api/agents", body);
310
+ const agent = response.agent;
304
311
  console.log(`spawned agent ${agent.id} (${agent.name})`);
305
312
  console.log(`dir: ${agent.dir}`);
306
313
  }
@@ -364,12 +371,12 @@ var listCmd = defineCommand({
364
371
  async run({ args }) {
365
372
  const client = createClient2();
366
373
  const q = args.all ? "?includeArchived=true" : "";
367
- const list = await client.get(`/api/agents${q}`);
368
- if (list.length === 0) {
374
+ const list3 = await client.get(`/api/agents${q}`);
375
+ if (list3.length === 0) {
369
376
  console.log("(no agents)");
370
377
  return;
371
378
  }
372
- const rows = list.map(
379
+ const rows = list3.map(
373
380
  (a) => args.long ? [a.id, a.status, a.name, a.profileId] : (
374
381
  // Short UUID prefix — all CLI commands accept 4+ char prefixes now.
375
382
  [a.id.slice(0, 8), a.status, a.name]
@@ -392,7 +399,7 @@ var showCmd = defineCommand({
392
399
  console.log(`profile: ${r.profile.id}`);
393
400
  console.log(`model: ${r.model}`);
394
401
  console.log(`dir: ${r.agent.dir}`);
395
- console.log(`group: ${r.group.id} ${r.group.path}`);
402
+ console.log(`team: ${r.team.id} ${r.team.path}`);
396
403
  console.log("skills:");
397
404
  if (r.skills.length === 0) {
398
405
  console.log(" (none)");
@@ -430,7 +437,13 @@ var deleteCmd = defineCommand({
430
437
  },
431
438
  async run({ args }) {
432
439
  const client = createClient2();
433
- await client.del(`/api/agents/${args.id}`);
440
+ const agent = await client.get(`/api/agents/${encodeURIComponent(args.id)}`);
441
+ const policy = await client.get(
442
+ `/api/teams/${encodeURIComponent(agent.team.id)}/policy`
443
+ );
444
+ await client.del(
445
+ `/api/agents/${encodeURIComponent(args.id)}?expectedTeamRevision=${policy.teamPolicy.revision}`
446
+ );
434
447
  console.log(`deleted agent ${args.id}`);
435
448
  }
436
449
  });
@@ -632,8 +645,8 @@ var chatContextCmd = defineCommand({
632
645
  if (ctx.systemPrompt.skillsListChars > 0) {
633
646
  console.log(` skills line: ${ctx.systemPrompt.skillsListChars.toLocaleString()} chars`);
634
647
  }
635
- if (ctx.systemPrompt.groupListChars > 0) {
636
- console.log(` group block: ${ctx.systemPrompt.groupListChars.toLocaleString()} chars`);
648
+ if (ctx.systemPrompt.teamListChars > 0) {
649
+ console.log(` team block: ${ctx.systemPrompt.teamListChars.toLocaleString()} chars`);
637
650
  }
638
651
  if (ctx.systemPrompt.userMdChars > 0) {
639
652
  console.log(` user_md block: ${ctx.systemPrompt.userMdChars.toLocaleString()} chars`);
@@ -662,10 +675,10 @@ var chatContextCmd = defineCommand({
662
675
  }
663
676
  console.log("");
664
677
  }
665
- console.log("## group");
666
- console.log(` - ${ctx.group.id} (${ctx.group.name}): ${ctx.group.path}`);
667
- if (ctx.group.userMdChars > 0) {
668
- console.log(` user_md: ${ctx.group.userMdChars.toLocaleString()} chars`);
678
+ console.log("## team");
679
+ console.log(` - ${ctx.team.id} (${ctx.team.name}): ${ctx.team.path}`);
680
+ if (ctx.team.userMdChars > 0) {
681
+ console.log(` user_md: ${ctx.team.userMdChars.toLocaleString()} chars`);
669
682
  }
670
683
  console.log("");
671
684
  console.log("## history");
@@ -736,15 +749,38 @@ var skillAddCmd = defineCommand({
736
749
  meta: { name: "add", description: "Attach a skill to an agent" },
737
750
  args: {
738
751
  agent: { type: "positional", required: true },
739
- skill: { type: "positional", required: true }
752
+ skill: { type: "positional", required: true },
753
+ "allow-warnings": {
754
+ type: "boolean",
755
+ description: "Attach even when the static skill scan reports findings"
756
+ }
740
757
  },
741
758
  async run({ args }) {
742
759
  const client = createClient2();
743
- const body = { skill: args.skill };
744
- await client.post(`/api/agents/${args.agent}/skills`, body);
760
+ const body = { skill: args.skill, allowFindings: args["allow-warnings"] };
761
+ try {
762
+ await client.post(`/api/agents/${args.agent}/skills`, body);
763
+ } catch (err) {
764
+ if (err instanceof ApiClientError && err.body.code === "skill_scan_blocked") {
765
+ console.error(`error: ${err.body.error}`);
766
+ printSkillFindings(err.body.findings ?? []);
767
+ console.error(" hint: inspect the skill, then rerun with --allow-warnings to confirm");
768
+ process.exitCode = 1;
769
+ return;
770
+ }
771
+ throw err;
772
+ }
745
773
  console.log(`attached skill ${args.skill} to ${args.agent}`);
746
774
  }
747
775
  });
776
+ function printSkillFindings(findings) {
777
+ if (findings.length === 0) return;
778
+ console.error("scan findings:");
779
+ for (const f of findings) {
780
+ const line = f.line ? ` line ${f.line}` : "";
781
+ console.error(` ${f.severity}: ${f.code}${line} - ${f.message}`);
782
+ }
783
+ }
748
784
  var skillRmCmd = defineCommand({
749
785
  meta: { name: "rm", description: "Detach a skill from an agent" },
750
786
  args: {
@@ -765,16 +801,28 @@ var skillCmd = defineCommand({
765
801
  }
766
802
  });
767
803
  var moveCmd = defineCommand({
768
- meta: { name: "move", description: "Move an agent to a different group" },
804
+ meta: { name: "move", description: "Move an agent to a different team" },
769
805
  args: {
770
806
  agent: { type: "positional", required: true },
771
- group: { type: "positional", required: true }
807
+ team: { type: "positional", required: true }
772
808
  },
773
809
  async run({ args }) {
774
810
  const client = createClient2();
775
- const body = { groupId: args.group };
776
- await client.patch(`/api/agents/${args.agent}/group`, body);
777
- console.log(`moved ${args.agent} to group ${args.group}`);
811
+ const [agent, destination] = await Promise.all([
812
+ client.get(`/api/agents/${encodeURIComponent(args.agent)}`),
813
+ client.get(`/api/teams/${encodeURIComponent(args.team)}/policy`)
814
+ ]);
815
+ const source = await client.get(
816
+ `/api/teams/${encodeURIComponent(agent.team.id)}/policy`
817
+ );
818
+ const body = {
819
+ teamId: args.team,
820
+ sourceExpectedRevision: source.teamPolicy.revision,
821
+ destinationExpectedRevision: destination.teamPolicy.revision,
822
+ placement: "open"
823
+ };
824
+ await client.patch(`/api/agents/${args.agent}/team`, body);
825
+ console.log(`moved ${args.agent} to team ${args.team}`);
778
826
  }
779
827
  });
780
828
  var sessionHeadCmd = defineCommand({
@@ -829,15 +877,102 @@ var agentCommand = defineCommand({
829
877
  }
830
878
  });
831
879
 
880
+ // src/commands/approval.ts
881
+ import { defineCommand as defineCommand2 } from "citty";
882
+ var list = defineCommand2({
883
+ meta: { name: "list", description: "List communication approval queue/history" },
884
+ args: {
885
+ status: { type: "string", default: "pending" },
886
+ team: { type: "string" },
887
+ json: { type: "boolean" }
888
+ },
889
+ async run({ args }) {
890
+ const query = new URLSearchParams({ status: args.status, limit: "100" });
891
+ if (args.team) query.set("teamId", args.team);
892
+ const body = await createClient2().get(
893
+ `/api/approvals?${query}`
894
+ );
895
+ if (args.json) return console.log(JSON.stringify(body, null, 2));
896
+ if (!body.approvals.length) return console.log("(no approvals)");
897
+ for (const line of columnize([
898
+ ["id", "status", "path", "origin", "expires"],
899
+ ...body.approvals.map((item) => [
900
+ item.id,
901
+ item.status,
902
+ `${endpoint(item.source)} -> ${endpoint(item.target)}`,
903
+ item.origin,
904
+ new Date(item.expiresAt).toISOString()
905
+ ])
906
+ ]))
907
+ console.log(line);
908
+ }
909
+ });
910
+ var show = defineCommand2({
911
+ meta: { name: "show", description: "Show one approval including payload and audit events" },
912
+ args: { id: { type: "positional", required: true }, json: { type: "boolean" } },
913
+ async run({ args }) {
914
+ const item = await createClient2().get(
915
+ `/api/approvals/${encodeURIComponent(args.id)}`
916
+ );
917
+ if (args.json) return console.log(JSON.stringify(item, null, 2));
918
+ console.log(`# ${item.id}`);
919
+ console.log(`status: ${item.status}`);
920
+ console.log(`attempt: ${item.attemptKind}:${item.attemptId}`);
921
+ console.log(`path: ${endpoint(item.source)} -> ${endpoint(item.target)}`);
922
+ console.log(`origin: ${item.origin}`);
923
+ console.log(`expires: ${new Date(item.expiresAt).toISOString()}`);
924
+ console.log(
925
+ `revisions: ${item.policyRefs.map((ref) => `${ref.teamId}@${ref.revision}`).join(", ")}`
926
+ );
927
+ console.log(`events: ${item.events.map((event) => event.event).join(" -> ")}`);
928
+ }
929
+ });
930
+ function decision(name) {
931
+ return defineCommand2({
932
+ meta: {
933
+ name,
934
+ description: name === "approve" ? "Approve and deliver one captured attempt" : `${name === "deny" ? "Deny" : "Cancel"} one pending attempt`
935
+ },
936
+ args: {
937
+ id: { type: "positional", required: true },
938
+ reason: { type: "string" },
939
+ yes: { type: "boolean", description: "Required explicit non-interactive confirmation" },
940
+ json: { type: "boolean" }
941
+ },
942
+ async run({ args }) {
943
+ if (!args.yes) throw new Error(`refusing ${name}: review with approval show, then pass --yes`);
944
+ const item = await createClient2().post(
945
+ `/api/approvals/${encodeURIComponent(args.id)}/${name}`,
946
+ args.reason ? { reason: args.reason } : {}
947
+ );
948
+ if (args.json) console.log(JSON.stringify(item, null, 2));
949
+ else console.log(`${item.id}: ${item.status}`);
950
+ }
951
+ });
952
+ }
953
+ function endpoint(value) {
954
+ return value.kind === "agent" ? `agent:${value.id}` : value.kind === "user" ? `user:${value.teamId}` : `outside:${value.teamId}`;
955
+ }
956
+ var approvalCommand = defineCommand2({
957
+ meta: { name: "approval", description: "Manage communication approval queue and history" },
958
+ subCommands: {
959
+ list,
960
+ show,
961
+ approve: decision("approve"),
962
+ deny: decision("deny"),
963
+ cancel: decision("cancel")
964
+ }
965
+ });
966
+
832
967
  // src/commands/auth.ts
833
968
  import { loginOpenAICodex } from "@earendil-works/pi-ai/oauth";
834
- import { defineCommand as defineCommand2 } from "citty";
969
+ import { defineCommand as defineCommand3 } from "citty";
835
970
  function formatExpiry(ms) {
836
971
  if (!ms) return "(unknown)";
837
972
  const d = new Date(ms);
838
973
  return d.toISOString().replace(/\.\d+Z$/, "Z");
839
974
  }
840
- var openaiLoginCmd = defineCommand2({
975
+ var openaiLoginCmd = defineCommand3({
841
976
  meta: {
842
977
  name: "login",
843
978
  description: "Connect your ChatGPT account via OAuth (browser sign-in)"
@@ -879,7 +1014,7 @@ var openaiLoginCmd = defineCommand2({
879
1014
  console.log(" bazilion provider models-set openai-codex gpt-5.3-codex-spark");
880
1015
  }
881
1016
  });
882
- var openaiLogoutCmd = defineCommand2({
1017
+ var openaiLogoutCmd = defineCommand3({
883
1018
  meta: {
884
1019
  name: "logout",
885
1020
  description: "Forget the stored ChatGPT OAuth credentials"
@@ -890,7 +1025,7 @@ var openaiLogoutCmd = defineCommand2({
890
1025
  console.log("disconnected ChatGPT OAuth credentials");
891
1026
  }
892
1027
  });
893
- var openaiStatusCmd = defineCommand2({
1028
+ var openaiStatusCmd = defineCommand3({
894
1029
  meta: {
895
1030
  name: "status",
896
1031
  description: "Show ChatGPT OAuth connection status"
@@ -907,7 +1042,7 @@ var openaiStatusCmd = defineCommand2({
907
1042
  console.log(`access token expires: ${formatExpiry(status.expiresAt)}`);
908
1043
  }
909
1044
  });
910
- var openaiCmd = defineCommand2({
1045
+ var openaiCmd = defineCommand3({
911
1046
  meta: {
912
1047
  name: "openai",
913
1048
  description: "Manage ChatGPT (OAuth) authentication"
@@ -918,7 +1053,7 @@ var openaiCmd = defineCommand2({
918
1053
  status: openaiStatusCmd
919
1054
  }
920
1055
  });
921
- var authCommand = defineCommand2({
1056
+ var authCommand = defineCommand3({
922
1057
  meta: {
923
1058
  name: "auth",
924
1059
  description: "OAuth-based provider authentication (ChatGPT account, etc.)"
@@ -934,8 +1069,8 @@ import { createWriteStream, existsSync as existsSync2, mkdirSync, readdirSync, r
934
1069
  import { resolve } from "path";
935
1070
  import { Readable } from "stream";
936
1071
  import { pipeline } from "stream/promises";
937
- import { defineCommand as defineCommand3 } from "citty";
938
- var createCmd = defineCommand3({
1072
+ import { defineCommand as defineCommand4 } from "citty";
1073
+ var createCmd = defineCommand4({
939
1074
  meta: { name: "create", description: "Download a tar.gz backup of ~/.bazilion from the server" },
940
1075
  args: {
941
1076
  output: {
@@ -976,7 +1111,7 @@ async function probeServerRunning(port) {
976
1111
  return false;
977
1112
  }
978
1113
  }
979
- var restoreCmd = defineCommand3({
1114
+ var restoreCmd = defineCommand4({
980
1115
  meta: {
981
1116
  name: "restore",
982
1117
  description: "Extract a backup tar.gz into ~/.bazilion (offline; server must be stopped)"
@@ -1029,7 +1164,7 @@ var restoreCmd = defineCommand3({
1029
1164
  console.log("start the server with: bazilion serve (migrations apply automatically)");
1030
1165
  }
1031
1166
  });
1032
- var backupCommand = defineCommand3({
1167
+ var backupCommand = defineCommand4({
1033
1168
  meta: { name: "backup", description: "Create or restore a ~/.bazilion tar.gz backup" },
1034
1169
  subCommands: {
1035
1170
  create: createCmd,
@@ -1043,7 +1178,7 @@ var backupCommand = defineCommand3({
1043
1178
  });
1044
1179
 
1045
1180
  // src/commands/completion.ts
1046
- import { defineCommand as defineCommand4 } from "citty";
1181
+ import { defineCommand as defineCommand5 } from "citty";
1047
1182
  async function walk(cmd, path, out) {
1048
1183
  const subsRaw = cmd.subCommands ?? {};
1049
1184
  const subNames = Object.keys(subsRaw);
@@ -1148,7 +1283,7 @@ function fishScript(flat) {
1148
1283
  `;
1149
1284
  }
1150
1285
  function completionCommand(main2) {
1151
- return defineCommand4({
1286
+ return defineCommand5({
1152
1287
  meta: {
1153
1288
  name: "completion",
1154
1289
  description: "Print a shell completion script (bash, zsh, or fish)"
@@ -1173,13 +1308,13 @@ function completionCommand(main2) {
1173
1308
  }
1174
1309
 
1175
1310
  // src/commands/config.ts
1176
- import { defineCommand as defineCommand5 } from "citty";
1311
+ import { defineCommand as defineCommand6 } from "citty";
1177
1312
  function displayValue(f) {
1178
1313
  if (!f.set) return "(unset)";
1179
1314
  if (f.kind === "secret") return f.preview ?? "(set)";
1180
1315
  return f.value ?? "(set)";
1181
1316
  }
1182
- var listCmd2 = defineCommand5({
1317
+ var listCmd2 = defineCommand6({
1183
1318
  meta: {
1184
1319
  name: "list",
1185
1320
  description: "List every configurable field (credentials + URLs) across all services"
@@ -1202,7 +1337,7 @@ var listCmd2 = defineCommand5({
1202
1337
  for (const line of columnize(rows)) console.log(line);
1203
1338
  }
1204
1339
  });
1205
- var setCmd = defineCommand5({
1340
+ var setCmd = defineCommand6({
1206
1341
  meta: {
1207
1342
  name: "set",
1208
1343
  description: "Set a configurable field (auto-routes to secrets or plaintext store)"
@@ -1229,7 +1364,7 @@ var setCmd = defineCommand5({
1229
1364
  console.log(`${state.envVar} (${state.kind}): ${displayValue(state)}`);
1230
1365
  }
1231
1366
  });
1232
- var rmCmd = defineCommand5({
1367
+ var rmCmd = defineCommand6({
1233
1368
  meta: { name: "rm", description: "Remove a configurable field value" },
1234
1369
  args: {
1235
1370
  envVar: { type: "positional", required: true, description: "Env var name to clear" }
@@ -1240,7 +1375,7 @@ var rmCmd = defineCommand5({
1240
1375
  console.log(`removed ${args.envVar}`);
1241
1376
  }
1242
1377
  });
1243
- var configCommand = defineCommand5({
1378
+ var configCommand = defineCommand6({
1244
1379
  meta: {
1245
1380
  name: "config",
1246
1381
  description: "Manage service configuration \u2014 credentials (encrypted) and URLs/IDs (plaintext), unified under one CLI"
@@ -1257,7 +1392,7 @@ import { spawn as spawn2 } from "child_process";
1257
1392
  import { existsSync as existsSync3 } from "fs";
1258
1393
  import { connect } from "net";
1259
1394
  import { join as join2 } from "path";
1260
- import { defineCommand as defineCommand6 } from "citty";
1395
+ import { defineCommand as defineCommand7 } from "citty";
1261
1396
  var bundledDaemonEntry = join2(import.meta.dirname, "daemon.js");
1262
1397
  var sourceDaemonEntry = join2(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
1263
1398
  var daemonEntry = existsSync3(bundledDaemonEntry) ? bundledDaemonEntry : sourceDaemonEntry;
@@ -1351,7 +1486,7 @@ function spawnProcess(label, entry2, env) {
1351
1486
  stdio: "inherit"
1352
1487
  });
1353
1488
  }
1354
- var dashboardCommand = defineCommand6({
1489
+ var dashboardCommand = defineCommand7({
1355
1490
  meta: {
1356
1491
  name: "dashboard",
1357
1492
  description: "Start the bazilion daemon and bundled web UI"
@@ -1470,8 +1605,8 @@ var dashboardCommand = defineCommand6({
1470
1605
  });
1471
1606
 
1472
1607
  // src/commands/doctor.ts
1473
- import { defineCommand as defineCommand7 } from "citty";
1474
- var doctorCommand = defineCommand7({
1608
+ import { defineCommand as defineCommand8 } from "citty";
1609
+ var doctorCommand = defineCommand8({
1475
1610
  meta: { name: "doctor", description: "Diagnose your bazilion install" },
1476
1611
  async run() {
1477
1612
  const client = createClient2();
@@ -1498,7 +1633,7 @@ var doctorCommand = defineCommand7({
1498
1633
  console.log(
1499
1634
  ` ${r.database.activeAgents} active agent(s) (${r.database.totalAgents} total)`
1500
1635
  );
1501
- console.log(` ${r.database.groups} group(s)`);
1636
+ console.log(` ${r.database.teams} team(s)`);
1502
1637
  } else {
1503
1638
  check("open database", false, r.database.error);
1504
1639
  }
@@ -1582,178 +1717,6 @@ var doctorCommand = defineCommand7({
1582
1717
  }
1583
1718
  });
1584
1719
 
1585
- // src/commands/group.ts
1586
- import { readFileSync as readFileSync3 } from "fs";
1587
- import { stdin as stdin2 } from "process";
1588
- import { defineCommand as defineCommand8 } from "citty";
1589
- var addCmd = defineCommand8({
1590
- meta: {
1591
- name: "add",
1592
- description: "Register a group at ~/.bazilion/groups/<slug>/ (use --link to point at an existing tree)"
1593
- },
1594
- args: {
1595
- id: { type: "positional", required: true, description: "Group slug" },
1596
- name: { type: "string", description: "Display name (defaults to slug)" },
1597
- link: {
1598
- type: "string",
1599
- description: "Absolute path of an existing directory; the group slot becomes a symlink to it"
1600
- }
1601
- },
1602
- async run({ args }) {
1603
- const client = createClient2();
1604
- const body = {
1605
- id: args.id,
1606
- ...args.name ? { name: args.name } : {},
1607
- ...args.link ? { link: args.link } : {}
1608
- };
1609
- const g = await client.post("/api/groups", body);
1610
- console.log(`registered group ${g.id} at ${g.path}`);
1611
- }
1612
- });
1613
- var listCmd3 = defineCommand8({
1614
- meta: { name: "list", description: "List groups" },
1615
- async run() {
1616
- const client = createClient2();
1617
- const list = await client.get("/api/groups");
1618
- if (list.length === 0) {
1619
- console.log("(no groups)");
1620
- return;
1621
- }
1622
- const rows = list.map((g) => [g.id, g.path]);
1623
- for (const line of columnize(rows)) console.log(line);
1624
- }
1625
- });
1626
- var rmCmd2 = defineCommand8({
1627
- meta: { name: "rm", description: "Remove a group registration" },
1628
- args: {
1629
- id: { type: "positional", required: true }
1630
- },
1631
- async run({ args }) {
1632
- const client = createClient2();
1633
- await client.del(`/api/groups/${args.id}`);
1634
- console.log(`removed group ${args.id}`);
1635
- }
1636
- });
1637
- async function readStdin() {
1638
- const chunks = [];
1639
- for await (const chunk of stdin2) chunks.push(chunk);
1640
- return Buffer.concat(chunks).toString("utf8");
1641
- }
1642
- var userMdShowCmd = defineCommand8({
1643
- meta: { name: "show", description: "Print the group's USER.md" },
1644
- args: { id: { type: "positional", required: true } },
1645
- async run({ args }) {
1646
- const client = createClient2();
1647
- const g = await client.get(`/api/groups/${args.id}`);
1648
- process.stdout.write(g.userMd);
1649
- if (g.userMd && !g.userMd.endsWith("\n")) process.stdout.write("\n");
1650
- }
1651
- });
1652
- var userMdSetCmd = defineCommand8({
1653
- meta: {
1654
- name: "set",
1655
- description: "Replace the group's USER.md (from --file, --from-stdin, or inline text)"
1656
- },
1657
- args: {
1658
- id: { type: "positional", required: true },
1659
- file: { type: "string", description: "Read content from a file path" },
1660
- "from-stdin": { type: "boolean", description: "Read content from stdin" },
1661
- text: { type: "string", description: "Inline content" }
1662
- },
1663
- async run({ args }) {
1664
- let content;
1665
- if (args["from-stdin"]) content = await readStdin();
1666
- else if (args.file) content = readFileSync3(args.file, "utf8");
1667
- else if (args.text !== void 0) content = args.text;
1668
- else {
1669
- console.error("group user-md set: provide --file, --from-stdin, or --text");
1670
- process.exit(2);
1671
- }
1672
- const client = createClient2();
1673
- const body = { userMd: content };
1674
- await client.put(`/api/groups/${args.id}/user-md`, body);
1675
- console.log(`updated USER.md for group ${args.id} (${content.length} bytes)`);
1676
- }
1677
- });
1678
- var userMdClearCmd = defineCommand8({
1679
- meta: { name: "clear", description: "Clear the group's USER.md to empty" },
1680
- args: { id: { type: "positional", required: true } },
1681
- async run({ args }) {
1682
- const client = createClient2();
1683
- const body = { userMd: "" };
1684
- await client.put(`/api/groups/${args.id}/user-md`, body);
1685
- console.log(`cleared USER.md for group ${args.id}`);
1686
- }
1687
- });
1688
- var userMdCmd = defineCommand8({
1689
- meta: { name: "user-md", description: "View or edit a group's USER.md" },
1690
- subCommands: {
1691
- show: userMdShowCmd,
1692
- set: userMdSetCmd,
1693
- clear: userMdClearCmd
1694
- }
1695
- });
1696
- var topicFormatShowCmd = defineCommand8({
1697
- meta: { name: "show", description: "Print the group's Telegram topic-name template" },
1698
- args: { id: { type: "positional", required: true } },
1699
- async run({ args }) {
1700
- const client = createClient2();
1701
- const g = await client.get(`/api/groups/${args.id}`);
1702
- console.log(g.telegramTopicNameFormat ?? "(default naming)");
1703
- }
1704
- });
1705
- var topicFormatSetCmd = defineCommand8({
1706
- meta: {
1707
- name: "set",
1708
- description: "Set the topic-name template. Tokens: {agent.name} {group.name} {group.slug} (must include {agent.name})"
1709
- },
1710
- args: {
1711
- id: { type: "positional", required: true },
1712
- format: {
1713
- type: "positional",
1714
- required: true,
1715
- description: 'e.g. "{group.name} / {agent.name}"'
1716
- }
1717
- },
1718
- async run({ args }) {
1719
- const client = createClient2();
1720
- const body = { format: args.format };
1721
- const g = await client.put(`/api/groups/${args.id}/topic-format`, body);
1722
- console.log(`set topic-name template for group ${args.id}: ${g.telegramTopicNameFormat}`);
1723
- }
1724
- });
1725
- var topicFormatClearCmd = defineCommand8({
1726
- meta: { name: "clear", description: "Clear the template (revert to built-in naming)" },
1727
- args: { id: { type: "positional", required: true } },
1728
- async run({ args }) {
1729
- const client = createClient2();
1730
- const body = { format: null };
1731
- await client.put(`/api/groups/${args.id}/topic-format`, body);
1732
- console.log(`cleared topic-name template for group ${args.id}`);
1733
- }
1734
- });
1735
- var topicFormatCmd = defineCommand8({
1736
- meta: {
1737
- name: "topic-format",
1738
- description: "View or edit a group's Telegram forum-topic name template"
1739
- },
1740
- subCommands: {
1741
- show: topicFormatShowCmd,
1742
- set: topicFormatSetCmd,
1743
- clear: topicFormatClearCmd
1744
- }
1745
- });
1746
- var groupCommand = defineCommand8({
1747
- meta: { name: "group", description: "Manage groups (collaboration contexts)" },
1748
- subCommands: {
1749
- add: addCmd,
1750
- list: listCmd3,
1751
- rm: rmCmd2,
1752
- "user-md": userMdCmd,
1753
- "topic-format": topicFormatCmd
1754
- }
1755
- });
1756
-
1757
1720
  // src/commands/inbox.ts
1758
1721
  import { defineCommand as defineCommand9 } from "citty";
1759
1722
  function decodeText(payload) {
@@ -1767,11 +1730,11 @@ function decodeText(payload) {
1767
1730
  function messageRow(m) {
1768
1731
  const when = new Date(m.createdAt).toISOString();
1769
1732
  const state = m.readAt ? "read" : "NEW";
1770
- const text = decodeText(m.payload);
1771
- const preview = text.length > 60 ? `${text.slice(0, 60)}\u2026` : text;
1733
+ const text2 = decodeText(m.payload);
1734
+ const preview = text2.length > 60 ? `${text2.slice(0, 60)}\u2026` : text2;
1772
1735
  return [m.id, state, when, `from:${m.fromAgentId.slice(0, 8)}`, `"${preview}"`];
1773
1736
  }
1774
- var listCmd4 = defineCommand9({
1737
+ var listCmd3 = defineCommand9({
1775
1738
  meta: { name: "list", description: "List messages in an agent inbox" },
1776
1739
  args: {
1777
1740
  agent: { type: "positional", required: true, description: "Recipient agent id" },
@@ -1824,14 +1787,14 @@ var readCmd = defineCommand9({
1824
1787
  var inboxCommand = defineCommand9({
1825
1788
  meta: { name: "inbox", description: "Inspect agent inboxes" },
1826
1789
  subCommands: {
1827
- list: listCmd4,
1790
+ list: listCmd3,
1828
1791
  show: showCmd2,
1829
1792
  read: readCmd
1830
1793
  }
1831
1794
  });
1832
1795
 
1833
1796
  // src/commands/login.ts
1834
- import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
1797
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
1835
1798
  import { defineCommand as defineCommand10 } from "citty";
1836
1799
  function normalizeServer(raw) {
1837
1800
  let url;
@@ -1870,7 +1833,7 @@ var loginCommand = defineCommand10({
1870
1833
  `${paths.authFile} not found. Start the daemon with "bazilion serve" first \u2014 login stores the remote there.`
1871
1834
  );
1872
1835
  }
1873
- const auth = JSON.parse(readFileSync4(paths.authFile, "utf8"));
1836
+ const auth = JSON.parse(readFileSync3(paths.authFile, "utf8"));
1874
1837
  if (args.clear) {
1875
1838
  if (!auth.remote) {
1876
1839
  console.log("no remote stored \u2014 nothing to clear");
@@ -1912,7 +1875,7 @@ function serverRow(s) {
1912
1875
  where
1913
1876
  ];
1914
1877
  }
1915
- var addCmd2 = defineCommand11({
1878
+ var addCmd = defineCommand11({
1916
1879
  meta: { name: "add", description: "Register an MCP server" },
1917
1880
  args: {
1918
1881
  name: { type: "positional", required: true, description: "Unique name ([a-zA-Z0-9_])" },
@@ -1939,7 +1902,7 @@ var addCmd2 = defineCommand11({
1939
1902
  console.log(`${server.id} ${server.name} ${server.transport}`);
1940
1903
  }
1941
1904
  });
1942
- var listCmd5 = defineCommand11({
1905
+ var listCmd4 = defineCommand11({
1943
1906
  meta: { name: "list", description: "List MCP servers" },
1944
1907
  async run() {
1945
1908
  const client = createClient2();
@@ -1960,7 +1923,7 @@ var showCmd3 = defineCommand11({
1960
1923
  console.log(JSON.stringify(server, null, 2));
1961
1924
  }
1962
1925
  });
1963
- var rmCmd3 = defineCommand11({
1926
+ var rmCmd2 = defineCommand11({
1964
1927
  meta: { name: "rm", description: "Delete an MCP server" },
1965
1928
  args: { id: { type: "positional", required: true } },
1966
1929
  async run({ args }) {
@@ -2008,10 +1971,10 @@ var testCmd = defineCommand11({
2008
1971
  var mcpCommand = defineCommand11({
2009
1972
  meta: { name: "mcp", description: "Manage MCP servers" },
2010
1973
  subCommands: {
2011
- add: addCmd2,
2012
- list: listCmd5,
1974
+ add: addCmd,
1975
+ list: listCmd4,
2013
1976
  show: showCmd3,
2014
- rm: rmCmd3,
1977
+ rm: rmCmd2,
2015
1978
  enable: enableCmd,
2016
1979
  disable: disableCmd,
2017
1980
  test: testCmd
@@ -2024,39 +1987,39 @@ function encodeKey(key) {
2024
1987
  return key.split("/").map(encodeURIComponent).join("/");
2025
1988
  }
2026
1989
  var writeCmd = defineCommand12({
2027
- meta: { name: "write", description: "Write an entry into a group's shared memory" },
1990
+ meta: { name: "write", description: "Write an entry into a team's shared memory" },
2028
1991
  args: {
2029
- group: { type: "positional", required: true, description: "Group slug" },
1992
+ team: { type: "positional", required: true, description: "Team slug" },
2030
1993
  key: { type: "positional", required: true, description: "Memory key (path under memory/)" },
2031
1994
  content: { type: "positional", required: true, description: "Content to write" }
2032
1995
  },
2033
1996
  async run({ args }) {
2034
1997
  const client = createClient2();
2035
1998
  const entry2 = await client.put(
2036
- `/api/groups/${args.group}/memory/${encodeKey(args.key)}`,
1999
+ `/api/teams/${args.team}/memory/${encodeKey(args.key)}`,
2037
2000
  { content: args.content }
2038
2001
  );
2039
2002
  console.log(`wrote ${entry2.key} (${entry2.content.length} bytes)`);
2040
2003
  }
2041
2004
  });
2042
2005
  var readCmd2 = defineCommand12({
2043
- meta: { name: "read", description: "Read an entry from a group's shared memory" },
2006
+ meta: { name: "read", description: "Read an entry from a team's shared memory" },
2044
2007
  args: {
2045
- group: { type: "positional", required: true, description: "Group slug" },
2008
+ team: { type: "positional", required: true, description: "Team slug" },
2046
2009
  key: { type: "positional", required: true }
2047
2010
  },
2048
2011
  async run({ args }) {
2049
2012
  const client = createClient2();
2050
2013
  const entry2 = await client.get(
2051
- `/api/groups/${args.group}/memory/${encodeKey(args.key)}`
2014
+ `/api/teams/${args.team}/memory/${encodeKey(args.key)}`
2052
2015
  );
2053
2016
  console.log(entry2.content);
2054
2017
  }
2055
2018
  });
2056
2019
  var searchCmd = defineCommand12({
2057
- meta: { name: "search", description: "Search a group's shared memory" },
2020
+ meta: { name: "search", description: "Search a team's shared memory" },
2058
2021
  args: {
2059
- group: { type: "positional", required: true, description: "Group slug" },
2022
+ team: { type: "positional", required: true, description: "Team slug" },
2060
2023
  query: { type: "positional", required: true },
2061
2024
  limit: { type: "string", description: "Max results (default 10)" }
2062
2025
  },
@@ -2064,7 +2027,7 @@ var searchCmd = defineCommand12({
2064
2027
  const client = createClient2();
2065
2028
  const limit = args.limit ? Number.parseInt(args.limit, 10) : 10;
2066
2029
  const params = new URLSearchParams({ q: args.query, limit: String(limit) });
2067
- const hits = await client.get(`/api/groups/${args.group}/memory/search?${params}`);
2030
+ const hits = await client.get(`/api/teams/${args.team}/memory/search?${params}`);
2068
2031
  if (hits.length === 0) {
2069
2032
  console.log("(no matches)");
2070
2033
  return;
@@ -2074,14 +2037,14 @@ var searchCmd = defineCommand12({
2074
2037
  }
2075
2038
  }
2076
2039
  });
2077
- var listCmd6 = defineCommand12({
2078
- meta: { name: "list", description: "List all entries in a group's shared memory" },
2040
+ var listCmd5 = defineCommand12({
2041
+ meta: { name: "list", description: "List all entries in a team's shared memory" },
2079
2042
  args: {
2080
- group: { type: "positional", required: true, description: "Group slug" }
2043
+ team: { type: "positional", required: true, description: "Team slug" }
2081
2044
  },
2082
2045
  async run({ args }) {
2083
2046
  const client = createClient2();
2084
- const all = await client.get(`/api/groups/${args.group}/memory`);
2047
+ const all = await client.get(`/api/teams/${args.team}/memory`);
2085
2048
  if (all.length === 0) {
2086
2049
  console.log("(no memory entries)");
2087
2050
  return;
@@ -2091,36 +2054,36 @@ var listCmd6 = defineCommand12({
2091
2054
  }
2092
2055
  }
2093
2056
  });
2094
- var rmCmd4 = defineCommand12({
2095
- meta: { name: "rm", description: "Remove an entry from a group's shared memory" },
2057
+ var rmCmd3 = defineCommand12({
2058
+ meta: { name: "rm", description: "Remove an entry from a team's shared memory" },
2096
2059
  args: {
2097
- group: { type: "positional", required: true, description: "Group slug" },
2060
+ team: { type: "positional", required: true, description: "Team slug" },
2098
2061
  key: { type: "positional", required: true }
2099
2062
  },
2100
2063
  async run({ args }) {
2101
2064
  const client = createClient2();
2102
- await client.del(`/api/groups/${args.group}/memory/${encodeKey(args.key)}`);
2065
+ await client.del(`/api/teams/${args.team}/memory/${encodeKey(args.key)}`);
2103
2066
  console.log(`removed ${args.key}`);
2104
2067
  }
2105
2068
  });
2106
2069
  var memoryCommand = defineCommand12({
2107
2070
  meta: {
2108
2071
  name: "memory",
2109
- description: "Manage a group's shared memory (BM25-indexed markdown notes)"
2072
+ description: "Manage a team's shared memory (BM25-indexed markdown notes)"
2110
2073
  },
2111
2074
  subCommands: {
2112
2075
  write: writeCmd,
2113
2076
  read: readCmd2,
2114
2077
  search: searchCmd,
2115
- list: listCmd6,
2116
- rm: rmCmd4
2078
+ list: listCmd5,
2079
+ rm: rmCmd3
2117
2080
  }
2118
2081
  });
2119
2082
 
2120
2083
  // src/commands/profile.ts
2121
2084
  import { spawn as spawn3 } from "child_process";
2122
2085
  import { randomBytes } from "crypto";
2123
- import { readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
2086
+ import { readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
2124
2087
  import { tmpdir } from "os";
2125
2088
  import { join as join3 } from "path";
2126
2089
 
@@ -2196,7 +2159,7 @@ var createCmd2 = defineCommand13({
2196
2159
  },
2197
2160
  async run({ args }) {
2198
2161
  const skillsMode = parseSkillsMode(args["skills-mode"]);
2199
- const readTemplate = (path) => path ? readFileSync5(path, "utf8") : void 0;
2162
+ const readTemplate = (path) => path ? readFileSync4(path, "utf8") : void 0;
2200
2163
  const body = {
2201
2164
  id: args.id,
2202
2165
  name: args.name,
@@ -2215,16 +2178,16 @@ var createCmd2 = defineCommand13({
2215
2178
  console.log(`created profile ${profile.id} at ${profile.dir}`);
2216
2179
  }
2217
2180
  });
2218
- var listCmd7 = defineCommand13({
2181
+ var listCmd6 = defineCommand13({
2219
2182
  meta: { name: "list", description: "List profiles" },
2220
2183
  async run() {
2221
2184
  const client = createClient2();
2222
- const list = await client.get("/api/profiles");
2223
- if (list.length === 0) {
2185
+ const list3 = await client.get("/api/profiles");
2186
+ if (list3.length === 0) {
2224
2187
  console.log("(no profiles)");
2225
2188
  return;
2226
2189
  }
2227
- const rows = list.map((p) => [p.id, p.defaultModel, p.name]);
2190
+ const rows = list3.map((p) => [p.id, p.defaultModel, p.name]);
2228
2191
  for (const line of columnize(rows)) console.log(line);
2229
2192
  }
2230
2193
  });
@@ -2283,7 +2246,7 @@ var editCmd2 = defineCommand13({
2283
2246
  child.on("close", (c) => resolve3(c ?? 0));
2284
2247
  });
2285
2248
  if (code !== 0) throw new Error(`editor exited with code ${code}`);
2286
- const updated = readFileSync5(tmpPath, "utf8");
2249
+ const updated = readFileSync4(tmpPath, "utf8");
2287
2250
  if (updated === content) {
2288
2251
  console.log("(no changes)");
2289
2252
  return;
@@ -2348,7 +2311,7 @@ var profileCommand = defineCommand13({
2348
2311
  meta: { name: "profile", description: "Manage profiles" },
2349
2312
  subCommands: {
2350
2313
  create: createCmd2,
2351
- list: listCmd7,
2314
+ list: listCmd6,
2352
2315
  show: showCmd4,
2353
2316
  edit: editCmd2,
2354
2317
  update: updateCmd,
@@ -2356,295 +2319,71 @@ var profileCommand = defineCommand13({
2356
2319
  }
2357
2320
  });
2358
2321
 
2359
- // src/commands/profile-group.ts
2360
- import { spawn as spawn4 } from "child_process";
2361
- import { randomBytes as randomBytes2 } from "crypto";
2362
- import { readFileSync as readFileSync6, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
2363
- import { tmpdir as tmpdir2 } from "os";
2364
- import { join as join4 } from "path";
2322
+ // src/commands/provider.ts
2365
2323
  import { defineCommand as defineCommand14 } from "citty";
2366
- var createCmd3 = defineCommand14({
2367
- meta: { name: "create", description: "Create a new profile group (team template)" },
2324
+ var listCmd7 = defineCommand14({
2325
+ meta: {
2326
+ name: "list",
2327
+ description: "List all providers with enabled/disabled state and curated model counts"
2328
+ },
2368
2329
  args: {
2369
- id: { type: "positional", required: true, description: "Profile group slug" },
2370
- name: { type: "string", description: "Display name (defaults to slug)" },
2371
- "user-md-file": {
2372
- type: "string",
2373
- description: "Path to a starter USER.md; seeded into a freshly-created target group"
2374
- }
2330
+ enabled: { type: "boolean", description: "Show only enabled providers" }
2375
2331
  },
2376
2332
  async run({ args }) {
2377
- const body = { id: args.id };
2378
- if (args.name) body.name = args.name;
2379
- if (args["user-md-file"]) body.userMd = readFileSync6(args["user-md-file"], "utf8");
2380
- const client = createClient2();
2381
- const created = await client.post("/api/profile-groups", body);
2382
- console.log(`created profile group ${created.id}`);
2383
- }
2384
- });
2385
- var listCmd8 = defineCommand14({
2386
- meta: { name: "list", description: "List profile groups" },
2387
- async run() {
2388
2333
  const client = createClient2();
2389
- const list = await client.get("/api/profile-groups");
2390
- if (list.length === 0) {
2391
- console.log("(no profile groups)");
2334
+ const { providers } = await client.get("/api/config/providers");
2335
+ const filtered = args.enabled ? providers.filter((p) => p.enabled) : providers;
2336
+ if (filtered.length === 0) {
2337
+ console.log("(no providers to show)");
2392
2338
  return;
2393
2339
  }
2394
- const rows = list.map((g) => [g.id, String(g.memberCount), g.name]);
2340
+ const rows = filtered.map((p) => [
2341
+ p.id,
2342
+ p.enabled ? "enabled" : "disabled",
2343
+ `${p.curated.length} curated`,
2344
+ `${p.catalog.length} catalog`,
2345
+ p.enabled ? "" : `(set ${p.envHint})`
2346
+ ]);
2395
2347
  for (const line of columnize(rows)) console.log(line);
2396
2348
  }
2397
2349
  });
2398
- var showCmd5 = defineCommand14({
2399
- meta: { name: "show", description: "Show profile group details + members" },
2350
+ var modelsCmd = defineCommand14({
2351
+ meta: {
2352
+ name: "models",
2353
+ description: "Show curated + catalog + live models for one provider"
2354
+ },
2400
2355
  args: {
2401
- id: { type: "positional", required: true },
2402
- json: { type: "boolean", description: "Emit full JSON (members + basics)" }
2356
+ name: { type: "positional", required: true, description: "Provider name" }
2403
2357
  },
2404
2358
  async run({ args }) {
2405
2359
  const client = createClient2();
2406
- const detail = await client.get(`/api/profile-groups/${args.id}`);
2407
- if (args.json) {
2408
- console.log(JSON.stringify(detail, null, 2));
2409
- return;
2360
+ const { providers } = await client.get("/api/config/providers");
2361
+ const p = providers.find((x) => x.id === args.name);
2362
+ if (!p) {
2363
+ console.error(`unknown provider: ${args.name}`);
2364
+ process.exit(1);
2410
2365
  }
2411
- console.log(`# ${detail.group.id}`);
2412
- console.log(`name: ${detail.group.name}`);
2413
- console.log(
2414
- `user-md: ${detail.group.userMd ? `${detail.group.userMd.length} chars` : "(none)"}`
2415
- );
2416
- console.log("");
2417
- if (detail.members.length === 0) {
2418
- console.log("(no members)");
2419
- return;
2366
+ console.log(`# ${p.id} (${p.enabled ? "enabled" : "disabled"})`);
2367
+ if (!p.enabled) console.log(` (set ${p.envHint} to enable)`);
2368
+ console.log("\n## curated");
2369
+ if (p.curated.length === 0) console.log(" (none \u2014 use `provider models-set` to pin some)");
2370
+ else for (const m of p.curated) console.log(` ${m}`);
2371
+ console.log("\n## catalog (from pi-ai)");
2372
+ if (p.catalog.length === 0) console.log(" (empty)");
2373
+ else for (const m of p.catalog) console.log(` ${m}`);
2374
+ if (p.live) {
2375
+ console.log("\n## live (from upstream /v1/models)");
2376
+ if (p.live.error) console.log(` (error: ${p.live.error})`);
2377
+ else if (p.live.models.length === 0) console.log(" (empty)");
2378
+ else for (const m of p.live.models) console.log(` ${m}`);
2420
2379
  }
2421
- console.log("members:");
2422
- const rows = [
2423
- ["#", "profile", "agent-name", "model-override", "reasoning"],
2424
- ...detail.members.map((m) => [
2425
- String(m.position),
2426
- m.profileId,
2427
- m.agentName,
2428
- m.modelOverride ?? "-",
2429
- m.reasoningLevel ?? "-"
2430
- ])
2431
- ];
2432
- for (const line of columnize(rows)) console.log(` ${line}`);
2433
2380
  }
2434
2381
  });
2435
- var updateCmd2 = defineCommand14({
2436
- meta: { name: "update", description: "Update profile group basics (name, user-md)" },
2437
- args: {
2438
- id: { type: "positional", required: true },
2439
- name: { type: "string", description: "New display name" },
2440
- "user-md-file": {
2441
- type: "string",
2442
- description: "Path to new USER.md content (pass empty string to clear)"
2443
- }
2444
- },
2445
- async run({ args }) {
2446
- const body = {};
2447
- if (args.name !== void 0) body.name = args.name;
2448
- if (args["user-md-file"] !== void 0) {
2449
- body.userMd = args["user-md-file"] === "" ? null : readFileSync6(args["user-md-file"], "utf8");
2450
- }
2451
- if (Object.keys(body).length === 0) {
2452
- throw new Error("nothing to update \u2014 pass at least one of --name/--user-md-file");
2453
- }
2454
- const client = createClient2();
2455
- const updated = await client.patch(`/api/profile-groups/${args.id}`, body);
2456
- console.log(`updated profile group ${updated.id}`);
2457
- }
2458
- });
2459
- var editCmd3 = defineCommand14({
2460
- meta: { name: "edit", description: "Edit the member array in $EDITOR (JSON)" },
2461
- args: {
2462
- id: { type: "positional", required: true }
2463
- },
2464
- async run({ args }) {
2465
- const client = createClient2();
2466
- const detail = await client.get(`/api/profile-groups/${args.id}`);
2467
- const editable = detail.members.map((m) => ({
2468
- profileId: m.profileId,
2469
- agentName: m.agentName,
2470
- modelOverride: m.modelOverride,
2471
- reasoningLevel: m.reasoningLevel
2472
- }));
2473
- const before = `${JSON.stringify(editable, null, 2)}
2474
- `;
2475
- const tmpPath = join4(
2476
- tmpdir2(),
2477
- `bazilion-profile-group-${args.id}-${randomBytes2(4).toString("hex")}.json`
2478
- );
2479
- writeFileSync4(tmpPath, before);
2480
- try {
2481
- const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
2482
- const code = await new Promise((resolve3, reject) => {
2483
- const child = spawn4(editor, [tmpPath], { stdio: "inherit" });
2484
- child.on("error", reject);
2485
- child.on("close", (c) => resolve3(c ?? 0));
2486
- });
2487
- if (code !== 0) throw new Error(`editor exited with code ${code}`);
2488
- const after = readFileSync6(tmpPath, "utf8");
2489
- if (after === before) {
2490
- console.log("(no changes)");
2491
- return;
2492
- }
2493
- let parsed;
2494
- try {
2495
- parsed = JSON.parse(after);
2496
- } catch (err) {
2497
- throw new Error(`invalid JSON: ${err.message}`);
2498
- }
2499
- if (!Array.isArray(parsed)) {
2500
- throw new Error("expected a JSON array of members");
2501
- }
2502
- const body = {
2503
- members: parsed.map((s, i) => {
2504
- const row = s;
2505
- if (!row || typeof row.profileId !== "string" || typeof row.agentName !== "string") {
2506
- throw new Error(`member ${i}: profileId and agentName are required strings`);
2507
- }
2508
- return {
2509
- profileId: row.profileId,
2510
- agentName: row.agentName,
2511
- modelOverride: row.modelOverride ?? null,
2512
- reasoningLevel: row.reasoningLevel === null || row.reasoningLevel === void 0 ? null : row.reasoningLevel
2513
- };
2514
- })
2515
- };
2516
- await client.put(`/api/profile-groups/${args.id}/members`, body);
2517
- console.log(`saved ${body.members.length} member(s)`);
2518
- } finally {
2519
- try {
2520
- rmSync3(tmpPath, { force: true });
2521
- } catch {
2522
- }
2523
- }
2524
- }
2525
- });
2526
- var deleteCmd3 = defineCommand14({
2527
- meta: { name: "delete", description: "Delete a profile group (does not affect spawned agents)" },
2528
- args: {
2529
- id: { type: "positional", required: true }
2530
- },
2531
- async run({ args }) {
2532
- const client = createClient2();
2533
- await client.del(`/api/profile-groups/${args.id}`);
2534
- console.log(`deleted profile group ${args.id}`);
2535
- }
2536
- });
2537
- var spawnCmd2 = defineCommand14({
2538
- meta: { name: "spawn", description: "Spawn the whole team into a group (transactional)" },
2539
- args: {
2540
- id: { type: "positional", required: true },
2541
- group: {
2542
- type: "string",
2543
- description: "Target group slug (overrides the template default)"
2544
- },
2545
- "user-md-file": {
2546
- type: "string",
2547
- description: "Path to USER.md content to seed (only takes effect on a fresh target group)"
2548
- }
2549
- },
2550
- async run({ args }) {
2551
- const body = {};
2552
- if (args.group) body.groupSlug = args.group;
2553
- if (args["user-md-file"]) body.userMd = readFileSync6(args["user-md-file"], "utf8");
2554
- const client = createClient2();
2555
- const result = await client.post(
2556
- `/api/profile-groups/${args.id}/spawn`,
2557
- body
2558
- );
2559
- console.log(`spawned ${result.agents.length} agent(s) into group ${result.groupSlug}`);
2560
- const rows = result.agents.map((a) => [a.id, a.name]);
2561
- for (const line of columnize(rows)) console.log(` ${line}`);
2562
- if (result.orphanAgentIds && result.orphanAgentIds.length > 0) {
2563
- console.error("");
2564
- console.error(`warning: ${result.orphanAgentIds.length} orphan agent dir(s) left on disk:`);
2565
- for (const id of result.orphanAgentIds) console.error(` ${id}`);
2566
- process.exitCode = 1;
2567
- }
2568
- }
2569
- });
2570
- var profileGroupCommand = defineCommand14({
2571
- meta: { name: "profile-group", description: "Manage profile groups" },
2572
- subCommands: {
2573
- create: createCmd3,
2574
- list: listCmd8,
2575
- show: showCmd5,
2576
- update: updateCmd2,
2577
- edit: editCmd3,
2578
- delete: deleteCmd3,
2579
- spawn: spawnCmd2
2580
- }
2581
- });
2582
-
2583
- // src/commands/provider.ts
2584
- import { defineCommand as defineCommand15 } from "citty";
2585
- var listCmd9 = defineCommand15({
2586
- meta: {
2587
- name: "list",
2588
- description: "List all providers with enabled/disabled state and curated model counts"
2589
- },
2590
- args: {
2591
- enabled: { type: "boolean", description: "Show only enabled providers" }
2592
- },
2593
- async run({ args }) {
2594
- const client = createClient2();
2595
- const { providers } = await client.get("/api/config/providers");
2596
- const filtered = args.enabled ? providers.filter((p) => p.enabled) : providers;
2597
- if (filtered.length === 0) {
2598
- console.log("(no providers to show)");
2599
- return;
2600
- }
2601
- const rows = filtered.map((p) => [
2602
- p.id,
2603
- p.enabled ? "enabled" : "disabled",
2604
- `${p.curated.length} curated`,
2605
- `${p.catalog.length} catalog`,
2606
- p.enabled ? "" : `(set ${p.envHint})`
2607
- ]);
2608
- for (const line of columnize(rows)) console.log(line);
2609
- }
2610
- });
2611
- var modelsCmd = defineCommand15({
2612
- meta: {
2613
- name: "models",
2614
- description: "Show curated + catalog + live models for one provider"
2615
- },
2616
- args: {
2617
- name: { type: "positional", required: true, description: "Provider name" }
2618
- },
2619
- async run({ args }) {
2620
- const client = createClient2();
2621
- const { providers } = await client.get("/api/config/providers");
2622
- const p = providers.find((x) => x.id === args.name);
2623
- if (!p) {
2624
- console.error(`unknown provider: ${args.name}`);
2625
- process.exit(1);
2626
- }
2627
- console.log(`# ${p.id} (${p.enabled ? "enabled" : "disabled"})`);
2628
- if (!p.enabled) console.log(` (set ${p.envHint} to enable)`);
2629
- console.log("\n## curated");
2630
- if (p.curated.length === 0) console.log(" (none \u2014 use `provider models-set` to pin some)");
2631
- else for (const m of p.curated) console.log(` ${m}`);
2632
- console.log("\n## catalog (from pi-ai)");
2633
- if (p.catalog.length === 0) console.log(" (empty)");
2634
- else for (const m of p.catalog) console.log(` ${m}`);
2635
- if (p.live) {
2636
- console.log("\n## live (from upstream /v1/models)");
2637
- if (p.live.error) console.log(` (error: ${p.live.error})`);
2638
- else if (p.live.models.length === 0) console.log(" (empty)");
2639
- else for (const m of p.live.models) console.log(` ${m}`);
2640
- }
2641
- }
2642
- });
2643
- var modelsSetCmd = defineCommand15({
2644
- meta: {
2645
- name: "models-set",
2646
- description: "Replace the curated model list for a provider (comma-separated)"
2647
- },
2382
+ var modelsSetCmd = defineCommand14({
2383
+ meta: {
2384
+ name: "models-set",
2385
+ description: "Replace the curated model list for a provider (comma-separated)"
2386
+ },
2648
2387
  args: {
2649
2388
  name: { type: "positional", required: true, description: "Provider name" },
2650
2389
  models: {
@@ -2665,7 +2404,7 @@ var modelsSetCmd = defineCommand15({
2665
2404
  for (const m of saved.models) console.log(` ${m}`);
2666
2405
  }
2667
2406
  });
2668
- var enableCmd2 = defineCommand15({
2407
+ var enableCmd2 = defineCommand14({
2669
2408
  meta: { name: "enable", description: "Toggle a provider on so agents can use it" },
2670
2409
  args: {
2671
2410
  name: { type: "positional", required: true, description: "Provider id (e.g. anthropic)" }
@@ -2679,7 +2418,7 @@ var enableCmd2 = defineCommand15({
2679
2418
  console.log(`${res.name}: enabled`);
2680
2419
  }
2681
2420
  });
2682
- var disableCmd2 = defineCommand15({
2421
+ var disableCmd2 = defineCommand14({
2683
2422
  meta: {
2684
2423
  name: "disable",
2685
2424
  description: "Toggle a provider off \u2014 agents will refuse its model strings"
@@ -2696,7 +2435,7 @@ var disableCmd2 = defineCommand15({
2696
2435
  console.log(`${res.name}: disabled`);
2697
2436
  }
2698
2437
  });
2699
- var testCmd2 = defineCommand15({
2438
+ var testCmd2 = defineCommand14({
2700
2439
  meta: { name: "test", description: "Send a single chat to a model and print the reply" },
2701
2440
  args: {
2702
2441
  model: {
@@ -2717,10 +2456,10 @@ var testCmd2 = defineCommand15({
2717
2456
  }
2718
2457
  }
2719
2458
  });
2720
- var providerCommand = defineCommand15({
2459
+ var providerCommand = defineCommand14({
2721
2460
  meta: { name: "provider", description: "Manage and test LLM providers" },
2722
2461
  subCommands: {
2723
- list: listCmd9,
2462
+ list: listCmd7,
2724
2463
  enable: enableCmd2,
2725
2464
  disable: disableCmd2,
2726
2465
  models: modelsCmd,
@@ -2730,8 +2469,8 @@ var providerCommand = defineCommand15({
2730
2469
  });
2731
2470
 
2732
2471
  // src/commands/send.ts
2733
- import { defineCommand as defineCommand16 } from "citty";
2734
- var sendCommand = defineCommand16({
2472
+ import { defineCommand as defineCommand15 } from "citty";
2473
+ var sendCommand = defineCommand15({
2735
2474
  meta: {
2736
2475
  name: "send",
2737
2476
  description: "Send a message from one agent to another"
@@ -2747,20 +2486,29 @@ var sendCommand = defineCommand16({
2747
2486
  from: args.from,
2748
2487
  payload: { text: args.message }
2749
2488
  };
2750
- const msg = await client.post(`/api/agents/${args.to}/messages`, body);
2751
- console.log(`sent message ${msg.id}`);
2489
+ const result = await client.post(
2490
+ `/api/agents/${args.to}/messages`,
2491
+ body
2492
+ );
2493
+ if ("approvalId" in result) {
2494
+ console.log(
2495
+ `pending approval ${result.approvalId} (expires ${new Date(result.expiresAt).toISOString()})`
2496
+ );
2497
+ return;
2498
+ }
2499
+ console.log(`sent message ${result.id}`);
2752
2500
  }
2753
2501
  });
2754
2502
 
2755
2503
  // src/commands/serve.ts
2756
- import { spawn as spawn5 } from "child_process";
2504
+ import { spawn as spawn4 } from "child_process";
2757
2505
  import { existsSync as existsSync5 } from "fs";
2758
- import { join as join5 } from "path";
2759
- import { defineCommand as defineCommand17 } from "citty";
2760
- var bundledDaemonEntry2 = join5(import.meta.dirname, "daemon.js");
2761
- var sourceDaemonEntry2 = join5(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
2506
+ import { join as join4 } from "path";
2507
+ import { defineCommand as defineCommand16 } from "citty";
2508
+ var bundledDaemonEntry2 = join4(import.meta.dirname, "daemon.js");
2509
+ var sourceDaemonEntry2 = join4(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
2762
2510
  var daemonEntry2 = existsSync5(bundledDaemonEntry2) ? bundledDaemonEntry2 : sourceDaemonEntry2;
2763
- var serveCommand = defineCommand17({
2511
+ var serveCommand = defineCommand16({
2764
2512
  meta: {
2765
2513
  name: "serve",
2766
2514
  description: "Start the bazilion daemon (HTTP API)"
@@ -2793,7 +2541,7 @@ var serveCommand = defineCommand17({
2793
2541
  console.log(`starting bazilion daemon at http://${host}:${port}`);
2794
2542
  console.log("(web UI runs separately: cd apps/web && pnpm dev)");
2795
2543
  const nodeArgs2 = daemonEntry2.endsWith(".ts") ? ["--import", "tsx/esm", daemonEntry2] : [daemonEntry2];
2796
- const proc = spawn5("node", nodeArgs2, {
2544
+ const proc = spawn4("node", nodeArgs2, {
2797
2545
  env,
2798
2546
  stdio: "inherit"
2799
2547
  });
@@ -2827,10 +2575,16 @@ var serveCommand = defineCommand17({
2827
2575
  });
2828
2576
 
2829
2577
  // src/commands/skill.ts
2830
- import { existsSync as existsSync6, readFileSync as readFileSync7, statSync } from "fs";
2578
+ import { existsSync as existsSync6, readFileSync as readFileSync5, statSync } from "fs";
2831
2579
  import { basename as basename2, resolve as resolve2 } from "path";
2832
- import { defineCommand as defineCommand18 } from "citty";
2833
- var listCmd10 = defineCommand18({
2580
+ import { defineCommand as defineCommand17 } from "citty";
2581
+ function printFindings(findings, prefix = " ") {
2582
+ for (const f of findings) {
2583
+ const line = f.line ? ` line ${f.line}` : "";
2584
+ console.log(`${prefix}${f.severity}: ${f.code}${line} - ${f.message}`);
2585
+ }
2586
+ }
2587
+ var listCmd8 = defineCommand17({
2834
2588
  meta: { name: "list", description: "List installed skills (or those attached to an agent)" },
2835
2589
  args: {
2836
2590
  agent: { type: "string", description: "Filter to skills attached to this agent" }
@@ -2860,9 +2614,18 @@ var listCmd10 = defineCommand18({
2860
2614
  s.parseError ? `(parse error: ${s.parseError})` : s.description
2861
2615
  ]);
2862
2616
  for (const line of columnize(rows)) console.log(line);
2617
+ const flagged = skills.filter((s) => s.scanFindings && s.scanFindings.length > 0);
2618
+ if (flagged.length > 0) {
2619
+ console.log("");
2620
+ console.log("scan findings:");
2621
+ for (const s of flagged) {
2622
+ console.log(`${s.name}:`);
2623
+ printFindings(s.scanFindings ?? []);
2624
+ }
2625
+ }
2863
2626
  }
2864
2627
  });
2865
- var importCmd = defineCommand18({
2628
+ var importCmd = defineCommand17({
2866
2629
  meta: {
2867
2630
  name: "import",
2868
2631
  description: "Import skills from openclaw, a directory, or a local .zip archive"
@@ -2880,19 +2643,36 @@ var importCmd = defineCommand18({
2880
2643
  const absFrom = resolve2(args.from);
2881
2644
  const isLocalZip = args.from.toLowerCase().endsWith(".zip") && existsSync6(absFrom) && statSync(absFrom).isFile();
2882
2645
  let result;
2883
- if (isLocalZip) {
2884
- const bytes = readFileSync7(absFrom);
2885
- const file = new File([bytes], basename2(absFrom), { type: "application/zip" });
2886
- const fd = new FormData();
2887
- fd.set("file", file);
2888
- if (args.force) fd.set("force", "true");
2889
- result = await client.postMultipart("/api/skills/import", fd);
2890
- } else {
2891
- const body = {
2892
- source: args.from,
2893
- force: args.force
2894
- };
2895
- result = await client.post("/api/skills/import", body);
2646
+ try {
2647
+ if (isLocalZip) {
2648
+ const bytes = readFileSync5(absFrom);
2649
+ const file = new File([bytes], basename2(absFrom), { type: "application/zip" });
2650
+ const fd = new FormData();
2651
+ fd.set("file", file);
2652
+ if (args.force) fd.set("force", "true");
2653
+ result = await client.postMultipart("/api/skills/import", fd);
2654
+ } else {
2655
+ const body = {
2656
+ source: args.from,
2657
+ force: args.force
2658
+ };
2659
+ result = await client.post("/api/skills/import", body);
2660
+ }
2661
+ } catch (err) {
2662
+ if (err instanceof ApiClientError && err.body.code === "skill_scan_blocked") {
2663
+ console.error(`error: ${err.body.error}`);
2664
+ if (err.body.findings && err.body.findings.length > 0) {
2665
+ console.error("scan findings:");
2666
+ for (const f of err.body.findings) {
2667
+ const line = f.line ? ` line ${f.line}` : "";
2668
+ console.error(` ${f.severity}: ${f.code}${line} - ${f.message}`);
2669
+ }
2670
+ }
2671
+ console.error(" hint: inspect the skill, then rerun with --force to confirm");
2672
+ process.exitCode = 1;
2673
+ return;
2674
+ }
2675
+ throw err;
2896
2676
  }
2897
2677
  if (result.imported.length === 0 && result.skipped.length === 0) {
2898
2678
  console.log("(nothing to import)");
@@ -2904,9 +2684,17 @@ var importCmd = defineCommand18({
2904
2684
  for (const s of result.skipped) {
2905
2685
  console.log(`skipped ${s.name}: ${s.reason}`);
2906
2686
  }
2687
+ if (result.findings && Object.keys(result.findings).length > 0) {
2688
+ console.log("");
2689
+ console.log("confirmed scan findings:");
2690
+ for (const [name, findings] of Object.entries(result.findings)) {
2691
+ console.log(`${name}:`);
2692
+ printFindings(findings);
2693
+ }
2694
+ }
2907
2695
  }
2908
2696
  });
2909
- var rmCmd5 = defineCommand18({
2697
+ var rmCmd4 = defineCommand17({
2910
2698
  meta: { name: "rm", description: "Remove an installed skill" },
2911
2699
  args: {
2912
2700
  name: { type: "positional", required: true }
@@ -2917,18 +2705,844 @@ var rmCmd5 = defineCommand18({
2917
2705
  console.log(`removed skill ${args.name}`);
2918
2706
  }
2919
2707
  });
2920
- var skillCommand = defineCommand18({
2708
+ var skillCommand = defineCommand17({
2921
2709
  meta: { name: "skill", description: "Manage the skill library" },
2922
2710
  subCommands: {
2923
- list: listCmd10,
2711
+ list: listCmd8,
2924
2712
  import: importCmd,
2925
- rm: rmCmd5
2713
+ rm: rmCmd4
2926
2714
  }
2927
2715
  });
2928
2716
 
2929
- // src/commands/telegram.ts
2717
+ // src/commands/team.ts
2718
+ import { readFileSync as readFileSync7 } from "fs";
2719
+ import { stdin as stdin2 } from "process";
2930
2720
  import { defineCommand as defineCommand19 } from "citty";
2931
- var setCmd2 = defineCommand19({
2721
+
2722
+ // src/commands/team-policy.ts
2723
+ import { readFileSync as readFileSync6 } from "fs";
2724
+ import { defineCommand as defineCommand18 } from "citty";
2725
+
2726
+ // src/team-interchange.ts
2727
+ var TEAM_POLICY_INTERCHANGE_VERSION = 1;
2728
+ var TEAM_DOCUMENT_KIND = "bazilion.team-template";
2729
+ var TEAM_POLICY_DOCUMENT_KIND = "bazilion.team-policy";
2730
+ var reasoning = /* @__PURE__ */ new Set(["off", "minimal", "low", "medium", "high", "xhigh"]);
2731
+ var templateKinds = /* @__PURE__ */ new Set(["user", "outside_team", "slot"]);
2732
+ var liveKinds = /* @__PURE__ */ new Set(["user", "outside_team", "agent"]);
2733
+ function object(value, label) {
2734
+ if (!value || typeof value !== "object" || Array.isArray(value))
2735
+ throw new Error(`${label} must be an object`);
2736
+ return value;
2737
+ }
2738
+ function text(value, label) {
2739
+ if (typeof value !== "string" || !value.trim()) throw new Error(`${label} is required`);
2740
+ return value.trim();
2741
+ }
2742
+ function nullableText(value, label) {
2743
+ if (value === null || value === void 0) return null;
2744
+ if (typeof value !== "string") throw new Error(`${label} must be a string or null`);
2745
+ return value;
2746
+ }
2747
+ function endpointKey(kind, key) {
2748
+ return `${kind}:${key ?? "-"}`;
2749
+ }
2750
+ function exportTeamDocument(detail) {
2751
+ const keyById = new Map(detail.slots.map((slot, index) => [slot.slotId, `slot-${index + 1}`]));
2752
+ return {
2753
+ version: TEAM_POLICY_INTERCHANGE_VERSION,
2754
+ kind: TEAM_DOCUMENT_KIND,
2755
+ template: {
2756
+ id: detail.template.id,
2757
+ name: detail.template.name,
2758
+ userMd: detail.template.userMd
2759
+ },
2760
+ slots: detail.slots.map((slot) => ({
2761
+ key: keyById.get(slot.slotId),
2762
+ profileId: slot.profileId,
2763
+ agentName: slot.agentName,
2764
+ modelOverride: slot.modelOverride,
2765
+ reasoningLevel: slot.reasoningLevel,
2766
+ layoutPosition: slot.layoutPosition,
2767
+ display: slot.display
2768
+ })),
2769
+ edges: detail.edges.map((edge) => ({
2770
+ sourceKind: edge.sourceKind,
2771
+ sourceKey: edge.sourceKind === "slot" ? keyById.get(edge.sourceId ?? "") ?? null : null,
2772
+ targetKind: edge.targetKind,
2773
+ targetKey: edge.targetKind === "slot" ? keyById.get(edge.targetId ?? "") ?? null : null,
2774
+ posture: edge.posture
2775
+ }))
2776
+ };
2777
+ }
2778
+ function parseTeamDocument(value) {
2779
+ const root = object(value, "document");
2780
+ if (root.version !== TEAM_POLICY_INTERCHANGE_VERSION)
2781
+ throw new Error(`unsupported Team Policy document version: ${String(root.version)}`);
2782
+ if (root.kind !== TEAM_DOCUMENT_KIND)
2783
+ throw new Error(`invalid document kind: expected ${TEAM_DOCUMENT_KIND}`);
2784
+ const meta = object(root.template, "template");
2785
+ const rawSlots = Array.isArray(root.slots) ? root.slots : null;
2786
+ const rawEdges = Array.isArray(root.edges) ? root.edges : null;
2787
+ if (!rawSlots || !rawEdges) throw new Error("slots and edges must be arrays");
2788
+ const keys = /* @__PURE__ */ new Set();
2789
+ const slots = rawSlots.map((raw, index) => {
2790
+ const slot = object(raw, `slot ${index}`);
2791
+ const key = text(slot.key, `slot ${index} key`);
2792
+ if (keys.has(key)) throw new Error(`duplicate slot key: ${key}`);
2793
+ keys.add(key);
2794
+ const level = slot.reasoningLevel;
2795
+ if (level !== null && level !== void 0 && !reasoning.has(level))
2796
+ throw new Error(`slot ${index} has invalid reasoningLevel`);
2797
+ const position = slot.layoutPosition;
2798
+ if (position !== null && position !== void 0 && (!position || typeof position !== "object" || Array.isArray(position) || !Number.isFinite(position.x) || !Number.isFinite(position.y)))
2799
+ throw new Error(`slot ${index} has invalid layoutPosition`);
2800
+ const display = slot.display;
2801
+ if (display !== null && display !== void 0 && (!display || typeof display !== "object" || Array.isArray(display)))
2802
+ throw new Error(`slot ${index} has invalid display`);
2803
+ return {
2804
+ key,
2805
+ profileId: text(slot.profileId, `slot ${index} profileId`),
2806
+ agentName: text(slot.agentName, `slot ${index} agentName`),
2807
+ modelOverride: nullableText(slot.modelOverride, `slot ${index} modelOverride`),
2808
+ reasoningLevel: level ?? null,
2809
+ layoutPosition: position ?? null,
2810
+ display: display ?? null
2811
+ };
2812
+ });
2813
+ const seen = /* @__PURE__ */ new Set();
2814
+ const edges = rawEdges.map((raw, index) => {
2815
+ const edge = object(raw, `edge ${index}`);
2816
+ if (!templateKinds.has(String(edge.sourceKind)) || !templateKinds.has(String(edge.targetKind)))
2817
+ throw new Error(`edge ${index} has invalid endpoint kind`);
2818
+ const sourceKind = edge.sourceKind;
2819
+ const targetKind = edge.targetKind;
2820
+ const sourceKey = nullableText(edge.sourceKey, `edge ${index} sourceKey`);
2821
+ const targetKey = nullableText(edge.targetKey, `edge ${index} targetKey`);
2822
+ const posture = edge.posture === void 0 || edge.posture === "allow" ? "allow" : edge.posture === "approval_required" ? "approval_required" : null;
2823
+ if (!posture) throw new Error(`edge ${index} has invalid posture`);
2824
+ if (sourceKind === "slot" !== Boolean(sourceKey))
2825
+ throw new Error(`edge ${index} source slot key is missing or invalid`);
2826
+ if (targetKind === "slot" !== Boolean(targetKey))
2827
+ throw new Error(`edge ${index} target slot key is missing or invalid`);
2828
+ if (sourceKey && !keys.has(sourceKey))
2829
+ throw new Error(`edge ${index} references missing slot ${sourceKey}`);
2830
+ if (targetKey && !keys.has(targetKey))
2831
+ throw new Error(`edge ${index} references missing slot ${targetKey}`);
2832
+ const signature = `${endpointKey(sourceKind, sourceKey)}->${endpointKey(targetKind, targetKey)}`;
2833
+ if (endpointKey(sourceKind, sourceKey) === endpointKey(targetKind, targetKey))
2834
+ throw new Error(`edge ${index} is a self edge`);
2835
+ if (seen.has(signature)) throw new Error(`duplicate edge: ${signature}`);
2836
+ seen.add(signature);
2837
+ return { sourceKind, sourceKey, targetKind, targetKey, posture };
2838
+ });
2839
+ return {
2840
+ version: 1,
2841
+ kind: TEAM_DOCUMENT_KIND,
2842
+ template: {
2843
+ id: text(meta.id, "template id"),
2844
+ name: text(meta.name, "template name"),
2845
+ userMd: nullableText(meta.userMd, "template userMd")
2846
+ },
2847
+ slots,
2848
+ edges
2849
+ };
2850
+ }
2851
+ function teamImportBody(document, existing) {
2852
+ const currentByKey = existing ? new Map(existing.slots.map((slot, index) => [`slot-${index + 1}`, slot.slotId])) : /* @__PURE__ */ new Map();
2853
+ const slots = document.slots.map((slot) => ({
2854
+ ...currentByKey.has(slot.key) ? { slotId: currentByKey.get(slot.key) } : { clientKey: slot.key },
2855
+ profileId: slot.profileId,
2856
+ agentName: slot.agentName,
2857
+ modelOverride: slot.modelOverride,
2858
+ reasoningLevel: slot.reasoningLevel,
2859
+ layoutPosition: slot.layoutPosition,
2860
+ display: slot.display
2861
+ }));
2862
+ const idByKey = new Map(
2863
+ slots.map((slot, index) => [
2864
+ document.slots[index]?.key,
2865
+ slot.slotId ?? slot.clientKey ?? null
2866
+ ])
2867
+ );
2868
+ const edges = document.edges.map((edge) => ({
2869
+ sourceKind: edge.sourceKind,
2870
+ sourceId: edge.sourceKind === "slot" ? idByKey.get(edge.sourceKey ?? "") : null,
2871
+ targetKind: edge.targetKind,
2872
+ targetId: edge.targetKind === "slot" ? idByKey.get(edge.targetKey ?? "") : null,
2873
+ posture: edge.posture
2874
+ }));
2875
+ return { slots, edges };
2876
+ }
2877
+ function parseTeamPolicyDocument(value) {
2878
+ const root = object(value, "document");
2879
+ if (root.version !== 1)
2880
+ throw new Error(`unsupported Team Policy document version: ${String(root.version)}`);
2881
+ if (root.kind !== TEAM_POLICY_DOCUMENT_KIND)
2882
+ throw new Error(`invalid document kind: expected ${TEAM_POLICY_DOCUMENT_KIND}`);
2883
+ if (!Number.isInteger(root.expectedRevision) || Number(root.expectedRevision) < 1)
2884
+ throw new Error("expectedRevision must be a positive integer");
2885
+ if (!Array.isArray(root.edges)) throw new Error("edges must be an array");
2886
+ const seen = /* @__PURE__ */ new Set();
2887
+ const edges = root.edges.map((raw, index) => {
2888
+ const edge = object(raw, `edge ${index}`);
2889
+ if (!liveKinds.has(String(edge.sourceKind)) || !liveKinds.has(String(edge.targetKind)))
2890
+ throw new Error(`edge ${index} has invalid endpoint kind`);
2891
+ const sourceKind = edge.sourceKind;
2892
+ const targetKind = edge.targetKind;
2893
+ const sourceId = nullableText(edge.sourceId, `edge ${index} sourceId`);
2894
+ const targetId = nullableText(edge.targetId, `edge ${index} targetId`);
2895
+ if (sourceKind === "agent" !== Boolean(sourceId) || targetKind === "agent" !== Boolean(targetId))
2896
+ throw new Error(`edge ${index} Agent id is missing or invalid`);
2897
+ const signature = `${endpointKey(sourceKind, sourceId)}->${endpointKey(targetKind, targetId)}`;
2898
+ if (endpointKey(sourceKind, sourceId) === endpointKey(targetKind, targetId))
2899
+ throw new Error(`edge ${index} is a self edge`);
2900
+ if (seen.has(signature)) throw new Error(`duplicate edge: ${signature}`);
2901
+ seen.add(signature);
2902
+ return { sourceKind, sourceId, targetKind, targetId };
2903
+ });
2904
+ return {
2905
+ version: 1,
2906
+ kind: TEAM_POLICY_DOCUMENT_KIND,
2907
+ teamId: text(root.teamId, "teamId"),
2908
+ expectedRevision: Number(root.expectedRevision),
2909
+ edges
2910
+ };
2911
+ }
2912
+ function exportTeamPolicy(teamId, revision, edges) {
2913
+ return {
2914
+ version: 1,
2915
+ kind: TEAM_POLICY_DOCUMENT_KIND,
2916
+ teamId,
2917
+ expectedRevision: revision,
2918
+ edges: edges.map(({ sourceKind, sourceId, targetKind, targetId, posture }) => ({
2919
+ sourceKind,
2920
+ sourceId,
2921
+ targetKind,
2922
+ targetId,
2923
+ posture
2924
+ }))
2925
+ };
2926
+ }
2927
+ function edgeDiff(before, after) {
2928
+ const signature = (edge) => `${endpointKey(edge.sourceKind, edge.sourceId ?? null)} -> ${endpointKey(edge.targetKind, edge.targetId ?? null)} [${edge.posture ?? "allow"}]`;
2929
+ const left = new Set(before.map(signature));
2930
+ const right = new Set(after.map(signature));
2931
+ return {
2932
+ added: [...right].filter((value) => !left.has(value)).sort(),
2933
+ removed: [...left].filter((value) => !right.has(value)).sort()
2934
+ };
2935
+ }
2936
+
2937
+ // src/commands/team-policy.ts
2938
+ function readJson(path) {
2939
+ try {
2940
+ return JSON.parse(readFileSync6(path, "utf8"));
2941
+ } catch (error) {
2942
+ throw new Error(`invalid JSON: ${error.message}`);
2943
+ }
2944
+ }
2945
+ function endpoint2(value, teamId) {
2946
+ if (value === "user") return { kind: "user", teamId };
2947
+ if (value.startsWith("agent:") && value.length > 6) return { kind: "agent", id: value.slice(6) };
2948
+ if (value.startsWith("outside:") && value.length > 8)
2949
+ return { kind: "outside_team", teamId: value.slice(8) };
2950
+ throw new Error("endpoint must be user, agent:<id>, or outside:<team-id>");
2951
+ }
2952
+ function printPolicy(detail) {
2953
+ console.log(`# Team ${detail.teamPolicy.teamId} policy`);
2954
+ console.log(`revision: ${detail.teamPolicy.revision}`);
2955
+ console.log(
2956
+ `baseline: ${detail.baseline ? `${detail.baseline.templateId}@${detail.baseline.templateRevision}` : "(none)"}`
2957
+ );
2958
+ console.log(`members: ${detail.members.length}`);
2959
+ console.log(`edges: ${detail.edges.length}`);
2960
+ if (detail.edges.length) {
2961
+ console.log("");
2962
+ for (const line of columnize([
2963
+ ["source", "target"],
2964
+ ...detail.edges.map((edge) => [
2965
+ `${edge.sourceKind}:${edge.sourceId ?? "-"}`,
2966
+ `${edge.targetKind}:${edge.targetId ?? "-"}`
2967
+ ])
2968
+ ]))
2969
+ console.log(line);
2970
+ }
2971
+ }
2972
+ var show2 = defineCommand18({
2973
+ meta: { name: "show", description: "Show the one effective live policy for a Team" },
2974
+ args: {
2975
+ team: { type: "positional", required: true },
2976
+ json: { type: "boolean", description: "Emit the canonical aggregate as JSON" }
2977
+ },
2978
+ async run({ args }) {
2979
+ const detail = await createClient2().get(
2980
+ `/api/teams/${encodeURIComponent(args.team)}/policy`
2981
+ );
2982
+ if (args.json) console.log(JSON.stringify(detail, null, 2));
2983
+ else printPolicy(detail);
2984
+ }
2985
+ });
2986
+ var exportCommand = defineCommand18({
2987
+ meta: { name: "export", description: "Export a revisioned Team policy document" },
2988
+ args: { team: { type: "positional", required: true } },
2989
+ async run({ args }) {
2990
+ const detail = await createClient2().get(
2991
+ `/api/teams/${encodeURIComponent(args.team)}/policy`
2992
+ );
2993
+ console.log(
2994
+ JSON.stringify(
2995
+ exportTeamPolicy(args.team, detail.teamPolicy.revision, detail.edges),
2996
+ null,
2997
+ 2
2998
+ )
2999
+ );
3000
+ }
3001
+ });
3002
+ function printEdgeDiff(current, edges) {
3003
+ const diff2 = edgeDiff(current.edges, edges);
3004
+ console.log(`Team: ${current.teamPolicy.teamId}`);
3005
+ console.log(`Revision: ${current.teamPolicy.revision}`);
3006
+ console.log(`Edges: +${diff2.added.length} -${diff2.removed.length}`);
3007
+ for (const value of diff2.added) console.log(` + ${value}`);
3008
+ for (const value of diff2.removed) console.log(` - ${value}`);
3009
+ }
3010
+ var importCommand = defineCommand18({
3011
+ meta: {
3012
+ name: "import",
3013
+ description: "Validate, diff, and explicitly replace a Team policy"
3014
+ },
3015
+ args: {
3016
+ team: { type: "positional", required: true },
3017
+ file: { type: "positional", required: true },
3018
+ "dry-run": { type: "boolean", description: "Validate and print the diff only" },
3019
+ apply: { type: "boolean", description: "Apply non-interactively after printing the diff" },
3020
+ "expected-revision": {
3021
+ type: "string",
3022
+ description: "Expected current Team revision (defaults to document revision)"
3023
+ },
3024
+ force: {
3025
+ type: "boolean",
3026
+ description: "Refetch current revision; requires --apply and still uses optimistic locking"
3027
+ },
3028
+ "confirm-current-revision": {
3029
+ type: "string",
3030
+ description: "Second force confirmation: the freshly displayed current revision"
3031
+ }
3032
+ },
3033
+ async run({ args }) {
3034
+ if (args.force && !args.apply)
3035
+ throw new Error("--force requires --apply (interactive force is intentionally unsupported)");
3036
+ const document = parseTeamPolicyDocument(readJson(args.file));
3037
+ if (document.teamId !== args.team)
3038
+ throw new Error(`document belongs to Team ${document.teamId}, not ${args.team}`);
3039
+ const client = createClient2();
3040
+ const current = await client.get(
3041
+ `/api/teams/${encodeURIComponent(args.team)}/policy`
3042
+ );
3043
+ printEdgeDiff(current, document.edges);
3044
+ if (args["dry-run"]) return console.log("valid: no changes applied");
3045
+ if (!args.apply) throw new Error("refusing mutation: review the diff, then pass --apply");
3046
+ const supplied = args["expected-revision"] ? Number.parseInt(args["expected-revision"], 10) : document.expectedRevision;
3047
+ const expectedRevision = args.force ? current.teamPolicy.revision : supplied;
3048
+ if (args.force && Number.parseInt(args["confirm-current-revision"] ?? "", 10) !== current.teamPolicy.revision)
3049
+ throw new Error(
3050
+ `--force requires --confirm-current-revision ${current.teamPolicy.revision} after reviewing the fresh diff`
3051
+ );
3052
+ if (!Number.isInteger(expectedRevision) || expectedRevision < 1)
3053
+ throw new Error("expected revision must be a positive integer");
3054
+ const body = {
3055
+ expectedRevision,
3056
+ edges: document.edges
3057
+ };
3058
+ const updated = await client.put(
3059
+ `/api/teams/${encodeURIComponent(args.team)}/policy`,
3060
+ body
3061
+ );
3062
+ console.log(`updated Team ${args.team} policy to revision ${updated.teamPolicy.revision}`);
3063
+ }
3064
+ });
3065
+ var diff = defineCommand18({
3066
+ meta: { name: "diff", description: "Compare live policy with its retained baseline source" },
3067
+ args: {
3068
+ team: { type: "positional", required: true },
3069
+ json: { type: "boolean", description: "Emit canonical diff JSON" }
3070
+ },
3071
+ async run({ args }) {
3072
+ const result = await createClient2().get(
3073
+ `/api/teams/${encodeURIComponent(args.team)}/policy/diff`
3074
+ );
3075
+ if (args.json) return console.log(JSON.stringify(result, null, 2));
3076
+ console.log(`# Team ${args.team} source diff`);
3077
+ console.log(
3078
+ `status: ${result.baseline ? result.sourceDiverged ? "source diverged" : "source current" : "no baseline"}`
3079
+ );
3080
+ console.log(`revision: ${result.liveRevision}`);
3081
+ console.log(
3082
+ `edges: +${result.comparison.addedSinceBaseline.length} -${result.comparison.removedSinceBaseline.length}`
3083
+ );
3084
+ console.log(
3085
+ `slots: +${result.comparison.currentSourceAddedSlotIds.length} -${result.comparison.currentSourceRemovedSlotIds.length}`
3086
+ );
3087
+ }
3088
+ });
3089
+ var evaluate = defineCommand18({
3090
+ meta: {
3091
+ name: "evaluate",
3092
+ description: "Evaluate a communication path without sending or recording a block"
3093
+ },
3094
+ args: {
3095
+ team: { type: "positional", required: true, description: "Owning Team for context" },
3096
+ source: { type: "string", required: true, description: "user | agent:<id> | outside:<team>" },
3097
+ target: { type: "string", required: true, description: "user | agent:<id> | outside:<team>" },
3098
+ origin: { type: "string", default: "cli-diagnostic" },
3099
+ json: { type: "boolean", description: "Emit decision JSON" }
3100
+ },
3101
+ async run({ args }) {
3102
+ const result = await createClient2().post(
3103
+ "/api/communication/evaluate",
3104
+ {
3105
+ source: endpoint2(args.source, args.team),
3106
+ target: endpoint2(args.target, args.team),
3107
+ origin: args.origin,
3108
+ attemptKind: "cli_evaluate",
3109
+ attemptId: `diagnostic:${args.team}`
3110
+ }
3111
+ );
3112
+ if (args.json) return console.log(JSON.stringify(result, null, 2));
3113
+ console.log(`${result.decision.toUpperCase()} ${result.channel}: ${result.reasonCode}`);
3114
+ console.log(result.reason);
3115
+ console.log(
3116
+ `policy revisions: ${result.policyRefs.map((ref) => `${ref.teamId}@${ref.revision}`).join(", ") || "-"}`
3117
+ );
3118
+ }
3119
+ });
3120
+ var blocks = defineCommand18({
3121
+ meta: { name: "blocks", description: "List paginated durable communication denials" },
3122
+ args: {
3123
+ team: { type: "positional", required: true },
3124
+ limit: { type: "string", default: "50" },
3125
+ cursor: { type: "string" },
3126
+ source: { type: "string" },
3127
+ target: { type: "string" },
3128
+ channel: { type: "string" },
3129
+ origin: { type: "string" },
3130
+ reason: { type: "string", description: "Reason code" },
3131
+ from: { type: "string", description: "Epoch milliseconds or ISO timestamp" },
3132
+ to: { type: "string", description: "Epoch milliseconds or ISO timestamp" },
3133
+ json: { type: "boolean", description: "Emit page JSON including nextCursor" }
3134
+ },
3135
+ async run({ args }) {
3136
+ const query = new URLSearchParams({ limit: args.limit });
3137
+ for (const [key, value] of [
3138
+ ["cursor", args.cursor],
3139
+ ["source", args.source],
3140
+ ["target", args.target],
3141
+ ["channel", args.channel],
3142
+ ["origin", args.origin],
3143
+ ["reasonCode", args.reason],
3144
+ ["from", args.from],
3145
+ ["to", args.to]
3146
+ ])
3147
+ if (value) query.set(key, value);
3148
+ const page = await createClient2().get(
3149
+ `/api/teams/${encodeURIComponent(args.team)}/policy/blocks?${query}`
3150
+ );
3151
+ if (args.json) return console.log(JSON.stringify(page, null, 2));
3152
+ if (!page.blocks.length) console.log("(no blocks)");
3153
+ else
3154
+ for (const line of columnize([
3155
+ ["time", "source", "target", "channel", "origin", "reason"],
3156
+ ...page.blocks.map((block) => [
3157
+ new Date(block.created_at).toISOString(),
3158
+ `${block.source_kind}:${block.source_id ?? "-"}`,
3159
+ `${block.target_kind}:${block.target_id ?? "-"}`,
3160
+ block.channel,
3161
+ block.origin,
3162
+ block.reason_code
3163
+ ])
3164
+ ]))
3165
+ console.log(line);
3166
+ if (page.nextCursor) console.log(`next cursor: ${page.nextCursor}`);
3167
+ }
3168
+ });
3169
+ var teamPolicyCommand = defineCommand18({
3170
+ meta: { name: "policy", description: "Inspect and manage the Team-owned live policy" },
3171
+ subCommands: {
3172
+ show: show2,
3173
+ export: exportCommand,
3174
+ import: importCommand,
3175
+ diff,
3176
+ evaluate,
3177
+ blocks
3178
+ }
3179
+ });
3180
+
3181
+ // src/commands/team.ts
3182
+ var addCmd2 = defineCommand19({
3183
+ meta: {
3184
+ name: "add",
3185
+ description: "Register a team at ~/.bazilion/teams/<slug>/ (use --link to point at an existing tree)"
3186
+ },
3187
+ args: {
3188
+ id: { type: "positional", required: true, description: "Team slug" },
3189
+ name: { type: "string", description: "Display name (defaults to slug)" },
3190
+ link: {
3191
+ type: "string",
3192
+ description: "Absolute path of an existing directory; the team slot becomes a symlink to it"
3193
+ }
3194
+ },
3195
+ async run({ args }) {
3196
+ const client = createClient2();
3197
+ const body = {
3198
+ id: args.id,
3199
+ ...args.name ? { name: args.name } : {},
3200
+ ...args.link ? { link: args.link } : {}
3201
+ };
3202
+ const g = await client.post("/api/teams", body);
3203
+ console.log(`registered team ${g.id} at ${g.path}`);
3204
+ }
3205
+ });
3206
+ var listCmd9 = defineCommand19({
3207
+ meta: { name: "list", description: "List teams" },
3208
+ async run() {
3209
+ const client = createClient2();
3210
+ const list3 = await client.get("/api/teams");
3211
+ if (list3.length === 0) {
3212
+ console.log("(no teams)");
3213
+ return;
3214
+ }
3215
+ const rows = list3.map((g) => [g.id, g.path]);
3216
+ for (const line of columnize(rows)) console.log(line);
3217
+ }
3218
+ });
3219
+ var rmCmd5 = defineCommand19({
3220
+ meta: { name: "rm", description: "Remove a team registration" },
3221
+ args: {
3222
+ id: { type: "positional", required: true }
3223
+ },
3224
+ async run({ args }) {
3225
+ const client = createClient2();
3226
+ const policy = await client.get(
3227
+ `/api/teams/${encodeURIComponent(args.id)}/policy`
3228
+ );
3229
+ await client.del(
3230
+ `/api/teams/${encodeURIComponent(args.id)}?expectedTeamPolicyRevision=${policy.teamPolicy.revision}`
3231
+ );
3232
+ console.log(`removed team ${args.id}`);
3233
+ }
3234
+ });
3235
+ async function readStdin() {
3236
+ const chunks = [];
3237
+ for await (const chunk of stdin2) chunks.push(chunk);
3238
+ return Buffer.concat(chunks).toString("utf8");
3239
+ }
3240
+ var userMdShowCmd = defineCommand19({
3241
+ meta: { name: "show", description: "Print the team's USER.md" },
3242
+ args: { id: { type: "positional", required: true } },
3243
+ async run({ args }) {
3244
+ const client = createClient2();
3245
+ const g = await client.get(`/api/teams/${args.id}`);
3246
+ process.stdout.write(g.userMd);
3247
+ if (g.userMd && !g.userMd.endsWith("\n")) process.stdout.write("\n");
3248
+ }
3249
+ });
3250
+ var userMdSetCmd = defineCommand19({
3251
+ meta: {
3252
+ name: "set",
3253
+ description: "Replace the team's USER.md (from --file, --from-stdin, or inline text)"
3254
+ },
3255
+ args: {
3256
+ id: { type: "positional", required: true },
3257
+ file: { type: "string", description: "Read content from a file path" },
3258
+ "from-stdin": { type: "boolean", description: "Read content from stdin" },
3259
+ text: { type: "string", description: "Inline content" }
3260
+ },
3261
+ async run({ args }) {
3262
+ let content;
3263
+ if (args["from-stdin"]) content = await readStdin();
3264
+ else if (args.file) content = readFileSync7(args.file, "utf8");
3265
+ else if (args.text !== void 0) content = args.text;
3266
+ else {
3267
+ console.error("team user-md set: provide --file, --from-stdin, or --text");
3268
+ process.exit(2);
3269
+ }
3270
+ const client = createClient2();
3271
+ const body = { userMd: content };
3272
+ await client.put(`/api/teams/${args.id}/user-md`, body);
3273
+ console.log(`updated USER.md for team ${args.id} (${content.length} bytes)`);
3274
+ }
3275
+ });
3276
+ var userMdClearCmd = defineCommand19({
3277
+ meta: { name: "clear", description: "Clear the team's USER.md to empty" },
3278
+ args: { id: { type: "positional", required: true } },
3279
+ async run({ args }) {
3280
+ const client = createClient2();
3281
+ const body = { userMd: "" };
3282
+ await client.put(`/api/teams/${args.id}/user-md`, body);
3283
+ console.log(`cleared USER.md for team ${args.id}`);
3284
+ }
3285
+ });
3286
+ var userMdCmd = defineCommand19({
3287
+ meta: { name: "user-md", description: "View or edit a team's USER.md" },
3288
+ subCommands: {
3289
+ show: userMdShowCmd,
3290
+ set: userMdSetCmd,
3291
+ clear: userMdClearCmd
3292
+ }
3293
+ });
3294
+ var topicFormatShowCmd = defineCommand19({
3295
+ meta: { name: "show", description: "Print the team's Telegram topic-name template" },
3296
+ args: { id: { type: "positional", required: true } },
3297
+ async run({ args }) {
3298
+ const client = createClient2();
3299
+ const g = await client.get(`/api/teams/${args.id}`);
3300
+ console.log(g.telegramTopicNameFormat ?? "(default naming)");
3301
+ }
3302
+ });
3303
+ var topicFormatSetCmd = defineCommand19({
3304
+ meta: {
3305
+ name: "set",
3306
+ description: "Set the topic-name template. Tokens: {agent.name} {team.name} {team.slug} (must include {agent.name})"
3307
+ },
3308
+ args: {
3309
+ id: { type: "positional", required: true },
3310
+ format: {
3311
+ type: "positional",
3312
+ required: true,
3313
+ description: 'e.g. "{team.name} / {agent.name}"'
3314
+ }
3315
+ },
3316
+ async run({ args }) {
3317
+ const client = createClient2();
3318
+ const body = { format: args.format };
3319
+ const g = await client.put(`/api/teams/${args.id}/topic-format`, body);
3320
+ console.log(`set topic-name template for team ${args.id}: ${g.telegramTopicNameFormat}`);
3321
+ }
3322
+ });
3323
+ var topicFormatClearCmd = defineCommand19({
3324
+ meta: { name: "clear", description: "Clear the template (revert to built-in naming)" },
3325
+ args: { id: { type: "positional", required: true } },
3326
+ async run({ args }) {
3327
+ const client = createClient2();
3328
+ const body = { format: null };
3329
+ await client.put(`/api/teams/${args.id}/topic-format`, body);
3330
+ console.log(`cleared topic-name template for team ${args.id}`);
3331
+ }
3332
+ });
3333
+ var topicFormatCmd = defineCommand19({
3334
+ meta: {
3335
+ name: "topic-format",
3336
+ description: "View or edit a team's Telegram forum-topic name template"
3337
+ },
3338
+ subCommands: {
3339
+ show: topicFormatShowCmd,
3340
+ set: topicFormatSetCmd,
3341
+ clear: topicFormatClearCmd
3342
+ }
3343
+ });
3344
+ var teamCommand = defineCommand19({
3345
+ meta: { name: "team", description: "Manage teams (collaboration contexts)" },
3346
+ subCommands: {
3347
+ add: addCmd2,
3348
+ list: listCmd9,
3349
+ rm: rmCmd5,
3350
+ "user-md": userMdCmd,
3351
+ "topic-format": topicFormatCmd,
3352
+ policy: teamPolicyCommand
3353
+ }
3354
+ });
3355
+
3356
+ // src/commands/team-template.ts
3357
+ import { readFileSync as readFileSync8 } from "fs";
3358
+ import { defineCommand as defineCommand20 } from "citty";
3359
+ function jsonFile(path) {
3360
+ try {
3361
+ return JSON.parse(readFileSync8(path, "utf8"));
3362
+ } catch (error) {
3363
+ throw new Error(`invalid JSON: ${error.message}`);
3364
+ }
3365
+ }
3366
+ function printTeam(detail) {
3367
+ console.log(`# ${detail.template.id} \u2014 ${detail.template.name}`);
3368
+ console.log(`revision: ${detail.template.currentRevision}`);
3369
+ console.log(`slots: ${detail.slots.length}`);
3370
+ console.log(`edges: ${detail.edges.length}`);
3371
+ if (detail.slots.length) {
3372
+ console.log("");
3373
+ for (const line of columnize([
3374
+ ["slot", "profile", "Agent name", "model", "reasoning"],
3375
+ ...detail.slots.map((slot, index) => [
3376
+ String(index + 1),
3377
+ slot.profileId,
3378
+ slot.agentName,
3379
+ slot.modelOverride ?? "-",
3380
+ slot.reasoningLevel ?? "-"
3381
+ ])
3382
+ ]))
3383
+ console.log(line);
3384
+ }
3385
+ }
3386
+ var list2 = defineCommand20({
3387
+ meta: { name: "list", description: "List canonical Team templates" },
3388
+ args: { json: { type: "boolean", description: "Emit stable JSON" } },
3389
+ async run({ args }) {
3390
+ const rows = await createClient2().get("/api/team-templates");
3391
+ if (args.json) return console.log(JSON.stringify(rows, null, 2));
3392
+ if (!rows.length) return console.log("(no Team templates)");
3393
+ for (const line of columnize([
3394
+ ["id", "revision", "slots", "name"],
3395
+ ...rows.map((row) => [row.id, String(row.currentRevision), String(row.slotCount), row.name])
3396
+ ]))
3397
+ console.log(line);
3398
+ }
3399
+ });
3400
+ var show3 = defineCommand20({
3401
+ meta: { name: "show", description: "Show a canonical Team template" },
3402
+ args: {
3403
+ id: { type: "positional", required: true },
3404
+ json: { type: "boolean", description: "Emit the canonical API aggregate" }
3405
+ },
3406
+ async run({ args }) {
3407
+ const detail = await createClient2().get(
3408
+ `/api/team-templates/${encodeURIComponent(args.id)}`
3409
+ );
3410
+ if (args.json) console.log(JSON.stringify(detail, null, 2));
3411
+ else printTeam(detail);
3412
+ }
3413
+ });
3414
+ var exportCommand2 = defineCommand20({
3415
+ meta: {
3416
+ name: "export",
3417
+ description: "Export a portable versioned Team-template document to stdout"
3418
+ },
3419
+ args: { id: { type: "positional", required: true } },
3420
+ async run({ args }) {
3421
+ const detail = await createClient2().get(
3422
+ `/api/team-templates/${encodeURIComponent(args.id)}`
3423
+ );
3424
+ console.log(JSON.stringify(exportTeamDocument(detail), null, 2));
3425
+ }
3426
+ });
3427
+ function printImportDiff(current, document) {
3428
+ const before = current ? exportTeamDocument(current) : null;
3429
+ console.log(`Team: ${current ? current.template.id : "(new)"} -> ${document.template.id}`);
3430
+ console.log(`Roster: ${current?.slots.length ?? 0} -> ${document.slots.length}`);
3431
+ const previousSlots = new Map(before?.slots.map((slot) => [slot.key, slot]) ?? []);
3432
+ const nextSlots = new Map(document.slots.map((slot) => [slot.key, slot]));
3433
+ for (const [key, slot] of nextSlots) {
3434
+ const previous = previousSlots.get(key);
3435
+ if (!previous) console.log(` + ${key}: ${slot.profileId} / ${slot.agentName}`);
3436
+ else if (JSON.stringify(previous) !== JSON.stringify(slot))
3437
+ console.log(
3438
+ ` ~ ${key}: ${previous.profileId} / ${previous.agentName} -> ${slot.profileId} / ${slot.agentName}`
3439
+ );
3440
+ }
3441
+ for (const [key, slot] of previousSlots)
3442
+ if (!nextSlots.has(key)) console.log(` - ${key}: ${slot.profileId} / ${slot.agentName}`);
3443
+ const toEdge = (edge) => ({
3444
+ sourceKind: edge.sourceKind,
3445
+ sourceId: edge.sourceKey,
3446
+ targetKind: edge.targetKind,
3447
+ targetId: edge.targetKey
3448
+ });
3449
+ const diff2 = edgeDiff(before?.edges.map(toEdge) ?? [], document.edges.map(toEdge));
3450
+ console.log(`Edges: +${diff2.added.length} -${diff2.removed.length}`);
3451
+ for (const value of diff2.added) console.log(` + ${value}`);
3452
+ for (const value of diff2.removed) console.log(` - ${value}`);
3453
+ }
3454
+ var importCommand2 = defineCommand20({
3455
+ meta: {
3456
+ name: "import",
3457
+ description: "Validate, diff, and explicitly apply a portable Team-template document"
3458
+ },
3459
+ args: {
3460
+ file: { type: "positional", required: true, description: "JSON document path" },
3461
+ "dry-run": { type: "boolean", description: "Validate and print the resolved diff only" },
3462
+ apply: { type: "boolean", description: "Apply non-interactively after printing the diff" },
3463
+ "expected-revision": {
3464
+ type: "string",
3465
+ description: "Required current revision when replacing an existing Team"
3466
+ },
3467
+ force: {
3468
+ type: "boolean",
3469
+ description: "Refetch current revision; requires --apply and still uses optimistic locking"
3470
+ },
3471
+ "confirm-current-revision": {
3472
+ type: "string",
3473
+ description: "Second force confirmation: the freshly displayed current revision"
3474
+ }
3475
+ },
3476
+ async run({ args }) {
3477
+ if (args.force && !args.apply)
3478
+ throw new Error("--force requires --apply (interactive force is intentionally unsupported)");
3479
+ const document = parseTeamDocument(jsonFile(args.file));
3480
+ const client = createClient2();
3481
+ let current = null;
3482
+ try {
3483
+ current = await client.get(
3484
+ `/api/team-templates/${encodeURIComponent(document.template.id)}`
3485
+ );
3486
+ } catch (error) {
3487
+ if (!(error instanceof ApiClientError) || error.status !== 404) throw error;
3488
+ }
3489
+ printImportDiff(current, document);
3490
+ if (args["dry-run"]) {
3491
+ console.log("valid: no changes applied");
3492
+ return;
3493
+ }
3494
+ if (!args.apply) throw new Error("refusing mutation: review the diff, then pass --apply");
3495
+ if (!current) {
3496
+ const body2 = teamImportBody(document);
3497
+ const created = await client.post("/api/team-templates/import", {
3498
+ id: document.template.id,
3499
+ name: document.template.name,
3500
+ userMd: document.template.userMd,
3501
+ slots: document.slots.map((slot, index) => ({
3502
+ ...body2.slots[index],
3503
+ clientKey: slot.key
3504
+ })),
3505
+ edges: body2.edges
3506
+ });
3507
+ console.log(
3508
+ `created Team ${created.template.id} at revision ${created.template.currentRevision}`
3509
+ );
3510
+ return;
3511
+ }
3512
+ if (document.template.name !== current.template.name || document.template.userMd !== current.template.userMd)
3513
+ throw new Error(
3514
+ "replacement document metadata differs; update Team name/USER.md separately before import"
3515
+ );
3516
+ const supplied = Number.parseInt(args["expected-revision"] ?? "", 10);
3517
+ const expectedRevision = args.force ? current.template.currentRevision : supplied;
3518
+ if (args.force && Number.parseInt(args["confirm-current-revision"] ?? "", 10) !== current.template.currentRevision)
3519
+ throw new Error(
3520
+ `--force requires --confirm-current-revision ${current.template.currentRevision} after reviewing the fresh diff`
3521
+ );
3522
+ if (!Number.isInteger(expectedRevision) || expectedRevision < 1)
3523
+ throw new Error("--expected-revision is required when replacing an existing Team");
3524
+ const definition = teamImportBody(document, current);
3525
+ const body = { expectedRevision, ...definition };
3526
+ const updated = await client.put(
3527
+ `/api/team-templates/${encodeURIComponent(document.template.id)}/definition`,
3528
+ body
3529
+ );
3530
+ console.log(
3531
+ `updated Team ${updated.template.id} to revision ${updated.template.currentRevision}`
3532
+ );
3533
+ }
3534
+ });
3535
+ var teamTemplateCommand = defineCommand20({
3536
+ meta: {
3537
+ name: "team-template",
3538
+ description: "Inspect and exchange canonical Team templates"
3539
+ },
3540
+ subCommands: { list: list2, show: show3, export: exportCommand2, import: importCommand2 }
3541
+ });
3542
+
3543
+ // src/commands/telegram.ts
3544
+ import { defineCommand as defineCommand21 } from "citty";
3545
+ var setCmd2 = defineCommand21({
2932
3546
  meta: {
2933
3547
  name: "set",
2934
3548
  description: "Save bot token + supergroup chat ID (paired write)"
@@ -2946,7 +3560,7 @@ var setCmd2 = defineCommand19({
2946
3560
  console.log(`saved \xB7 token ${state.botTokenPreview} \xB7 chat ${state.chatId}`);
2947
3561
  }
2948
3562
  });
2949
- var clearCmd = defineCommand19({
3563
+ var clearCmd = defineCommand21({
2950
3564
  meta: {
2951
3565
  name: "clear",
2952
3566
  description: "Remove stored bot token + chat ID"
@@ -2957,7 +3571,7 @@ var clearCmd = defineCommand19({
2957
3571
  console.log("cleared");
2958
3572
  }
2959
3573
  });
2960
- var showCmd6 = defineCommand19({
3574
+ var showCmd5 = defineCommand21({
2961
3575
  meta: {
2962
3576
  name: "show",
2963
3577
  description: "Show what credentials are stored (token is masked)"
@@ -2978,7 +3592,7 @@ var showCmd6 = defineCommand19({
2978
3592
  }
2979
3593
  }
2980
3594
  });
2981
- var reconnectCmd = defineCommand19({
3595
+ var reconnectCmd = defineCommand21({
2982
3596
  meta: {
2983
3597
  name: "reconnect",
2984
3598
  description: "Apply a pending supergroup chat-id migration + re-activate the bot"
@@ -2989,7 +3603,7 @@ var reconnectCmd = defineCommand19({
2989
3603
  console.log(`reconnected \xB7 chat ${state.chatId}`);
2990
3604
  }
2991
3605
  });
2992
- var configCmd = defineCommand19({
3606
+ var configCmd = defineCommand21({
2993
3607
  meta: {
2994
3608
  name: "config",
2995
3609
  description: "Manage Telegram credentials (bot token + chat ID)"
@@ -2997,10 +3611,10 @@ var configCmd = defineCommand19({
2997
3611
  subCommands: {
2998
3612
  set: setCmd2,
2999
3613
  clear: clearCmd,
3000
- show: showCmd6
3614
+ show: showCmd5
3001
3615
  }
3002
3616
  });
3003
- var healthCmd = defineCommand19({
3617
+ var healthCmd = defineCommand21({
3004
3618
  meta: {
3005
3619
  name: "health",
3006
3620
  description: "Run the four-step preflight against the Telegram Bot API"
@@ -3034,7 +3648,7 @@ var healthCmd = defineCommand19({
3034
3648
  if (!allOk) process.exitCode = 1;
3035
3649
  }
3036
3650
  });
3037
- var botStatusCmd = defineCommand19({
3651
+ var botStatusCmd = defineCommand21({
3038
3652
  meta: {
3039
3653
  name: "status",
3040
3654
  description: "Show polling state of the live bot"
@@ -3059,7 +3673,7 @@ var botStatusCmd = defineCommand19({
3059
3673
  if (!p.running) process.exitCode = 1;
3060
3674
  }
3061
3675
  });
3062
- var botRestartCmd = defineCommand19({
3676
+ var botRestartCmd = defineCommand21({
3063
3677
  meta: {
3064
3678
  name: "restart",
3065
3679
  description: "Force-restart the bot (tears down + brings up from current creds)"
@@ -3070,7 +3684,7 @@ var botRestartCmd = defineCommand19({
3070
3684
  console.log("restart requested");
3071
3685
  }
3072
3686
  });
3073
- var botCmd = defineCommand19({
3687
+ var botCmd = defineCommand21({
3074
3688
  meta: {
3075
3689
  name: "bot",
3076
3690
  description: "Inspect / control the live polling bot"
@@ -3080,7 +3694,7 @@ var botCmd = defineCommand19({
3080
3694
  restart: botRestartCmd
3081
3695
  }
3082
3696
  });
3083
- var bindCmd = defineCommand19({
3697
+ var bindCmd = defineCommand21({
3084
3698
  meta: {
3085
3699
  name: "bind",
3086
3700
  description: "Create a Telegram topic for an agent (manual fallback for /talk)"
@@ -3098,7 +3712,7 @@ var bindCmd = defineCommand19({
3098
3712
  console.log(` ${result.deepLink}`);
3099
3713
  }
3100
3714
  });
3101
- var unbindCmd = defineCommand19({
3715
+ var unbindCmd = defineCommand21({
3102
3716
  meta: {
3103
3717
  name: "unbind",
3104
3718
  description: "Clear an agent's Telegram topic binding (topic stays in Telegram as orphan)"
@@ -3112,7 +3726,7 @@ var unbindCmd = defineCommand19({
3112
3726
  console.log(`unbound agent ${args.agent}`);
3113
3727
  }
3114
3728
  });
3115
- var listBindingsCmd = defineCommand19({
3729
+ var listBindingsCmd = defineCommand21({
3116
3730
  meta: {
3117
3731
  name: "list",
3118
3732
  description: "List agents and their Telegram topic bindings"
@@ -3129,18 +3743,18 @@ var listBindingsCmd = defineCommand19({
3129
3743
  if (bound.length > 0) {
3130
3744
  console.log("bound:");
3131
3745
  for (const a of bound) {
3132
- console.log(` #${a.telegramTopicId} ${a.name} (group: ${a.groupId})`);
3746
+ console.log(` #${a.telegramTopicId} ${a.name} (team: ${a.teamId})`);
3133
3747
  }
3134
3748
  }
3135
3749
  if (unbound.length > 0) {
3136
3750
  console.log("unbound:");
3137
3751
  for (const a of unbound) {
3138
- console.log(` \u2014 ${a.name} (group: ${a.groupId})`);
3752
+ console.log(` \u2014 ${a.name} (team: ${a.teamId})`);
3139
3753
  }
3140
3754
  }
3141
3755
  }
3142
3756
  });
3143
- var allowCmd = defineCommand19({
3757
+ var allowCmd = defineCommand21({
3144
3758
  meta: { name: "allow", description: "Add a Telegram user id to the allowlist" },
3145
3759
  args: {
3146
3760
  userId: { type: "positional", required: true, description: "Numeric Telegram user id" },
@@ -3157,7 +3771,7 @@ var allowCmd = defineCommand19({
3157
3771
  console.log(`allowed ${u.userId} (${u.role})`);
3158
3772
  }
3159
3773
  });
3160
- var denyCmd = defineCommand19({
3774
+ var denyCmd = defineCommand21({
3161
3775
  meta: { name: "deny", description: "Remove a Telegram user id from the allowlist" },
3162
3776
  args: { userId: { type: "positional", required: true } },
3163
3777
  async run({ args }) {
@@ -3166,7 +3780,7 @@ var denyCmd = defineCommand19({
3166
3780
  console.log(`removed ${args.userId}`);
3167
3781
  }
3168
3782
  });
3169
- var allowedCmd = defineCommand19({
3783
+ var allowedCmd = defineCommand21({
3170
3784
  meta: { name: "allowed", description: "List allowlisted Telegram users" },
3171
3785
  async run() {
3172
3786
  const client = createClient2();
@@ -3181,7 +3795,7 @@ var allowedCmd = defineCommand19({
3181
3795
  }
3182
3796
  }
3183
3797
  });
3184
- var telegramCommand = defineCommand19({
3798
+ var telegramCommand = defineCommand21({
3185
3799
  meta: {
3186
3800
  name: "telegram",
3187
3801
  description: "Telegram integration: credentials, health, bot lifecycle, bindings, access"
@@ -3202,7 +3816,7 @@ var telegramCommand = defineCommand19({
3202
3816
 
3203
3817
  // src/commands/token.ts
3204
3818
  import { networkInterfaces } from "os";
3205
- import { defineCommand as defineCommand20 } from "citty";
3819
+ import { defineCommand as defineCommand22 } from "citty";
3206
3820
  import qrcode from "qrcode-terminal";
3207
3821
  function tokenRow(t) {
3208
3822
  const last = t.lastUsedAt ? new Date(t.lastUsedAt).toISOString() : "(never)";
@@ -3236,7 +3850,7 @@ function resolveQrServer(override) {
3236
3850
  if (detected.warning) console.warn(`\u26A0 ${detected.warning}`);
3237
3851
  return detected.origin;
3238
3852
  }
3239
- var createCmd4 = defineCommand20({
3853
+ var createCmd3 = defineCommand22({
3240
3854
  meta: { name: "create", description: "Mint a new web token (shown once)" },
3241
3855
  args: {
3242
3856
  label: { type: "positional", required: true, description: "Human-readable label" },
@@ -3267,7 +3881,7 @@ var createCmd4 = defineCommand20({
3267
3881
  qrcode.generate(pairUrl, { small: true }, (qr) => console.log(qr));
3268
3882
  }
3269
3883
  });
3270
- var listCmd11 = defineCommand20({
3884
+ var listCmd10 = defineCommand22({
3271
3885
  meta: { name: "list", description: "List web tokens" },
3272
3886
  args: {
3273
3887
  all: { type: "boolean", description: "Include revoked tokens" }
@@ -3283,7 +3897,7 @@ var listCmd11 = defineCommand20({
3283
3897
  for (const line of columnize(tokens.map(tokenRow))) console.log(line);
3284
3898
  }
3285
3899
  });
3286
- var showLocalCmd = defineCommand20({
3900
+ var showLocalCmd = defineCommand22({
3287
3901
  meta: {
3288
3902
  name: "show-local",
3289
3903
  description: "Print the bootstrap web token stored in ~/.bazilion/auth.json"
@@ -3293,7 +3907,7 @@ var showLocalCmd = defineCommand20({
3293
3907
  console.log(readAuthFile(paths.authFile).token);
3294
3908
  }
3295
3909
  });
3296
- var revokeCmd = defineCommand20({
3910
+ var revokeCmd = defineCommand22({
3297
3911
  meta: { name: "revoke", description: "Revoke a web token" },
3298
3912
  args: {
3299
3913
  id: { type: "positional", required: true }
@@ -3304,19 +3918,19 @@ var revokeCmd = defineCommand20({
3304
3918
  console.log(`revoked token ${args.id}`);
3305
3919
  }
3306
3920
  });
3307
- var tokenCommand = defineCommand20({
3921
+ var tokenCommand = defineCommand22({
3308
3922
  meta: { name: "token", description: "Manage web tokens for API/CLI clients" },
3309
3923
  subCommands: {
3310
- create: createCmd4,
3311
- list: listCmd11,
3924
+ create: createCmd3,
3925
+ list: listCmd10,
3312
3926
  revoke: revokeCmd,
3313
3927
  "show-local": showLocalCmd
3314
3928
  }
3315
3929
  });
3316
3930
 
3317
3931
  // src/commands/trigger.ts
3318
- import { defineCommand as defineCommand21 } from "citty";
3319
- var addCmd3 = defineCommand21({
3932
+ import { defineCommand as defineCommand23 } from "citty";
3933
+ var addCmd3 = defineCommand23({
3320
3934
  meta: { name: "add", description: "Add a heartbeat / cron trigger to an agent" },
3321
3935
  args: {
3322
3936
  agent: { type: "positional", required: true },
@@ -3364,7 +3978,7 @@ function triggerRow(t) {
3364
3978
  const msgPreview = t.message.length > 60 ? `${t.message.slice(0, 60)}\u2026` : t.message;
3365
3979
  return [t.id, state, spec, `last: ${last}`, `"${msgPreview}"`];
3366
3980
  }
3367
- var listCmd12 = defineCommand21({
3981
+ var listCmd11 = defineCommand23({
3368
3982
  meta: { name: "list", description: "List triggers for an agent" },
3369
3983
  args: {
3370
3984
  agent: { type: "positional", required: true }
@@ -3381,7 +3995,7 @@ var listCmd12 = defineCommand21({
3381
3995
  for (const line of columnize(triggers.map(triggerRow))) console.log(line);
3382
3996
  }
3383
3997
  });
3384
- var rmCmd6 = defineCommand21({
3998
+ var rmCmd6 = defineCommand23({
3385
3999
  meta: { name: "rm", description: "Delete a trigger" },
3386
4000
  args: {
3387
4001
  id: { type: "positional", required: true }
@@ -3392,7 +4006,7 @@ var rmCmd6 = defineCommand21({
3392
4006
  console.log(`removed trigger ${args.id}`);
3393
4007
  }
3394
4008
  });
3395
- var enableCmd3 = defineCommand21({
4009
+ var enableCmd3 = defineCommand23({
3396
4010
  meta: { name: "enable", description: "Enable a trigger" },
3397
4011
  args: {
3398
4012
  id: { type: "positional", required: true }
@@ -3404,7 +4018,7 @@ var enableCmd3 = defineCommand21({
3404
4018
  console.log(`enabled trigger ${args.id}`);
3405
4019
  }
3406
4020
  });
3407
- var disableCmd3 = defineCommand21({
4021
+ var disableCmd3 = defineCommand23({
3408
4022
  meta: { name: "disable", description: "Disable a trigger" },
3409
4023
  args: {
3410
4024
  id: { type: "positional", required: true }
@@ -3416,11 +4030,11 @@ var disableCmd3 = defineCommand21({
3416
4030
  console.log(`disabled trigger ${args.id}`);
3417
4031
  }
3418
4032
  });
3419
- var triggerCommand = defineCommand21({
4033
+ var triggerCommand = defineCommand23({
3420
4034
  meta: { name: "trigger", description: "Manage agent heartbeats / cron triggers" },
3421
4035
  subCommands: {
3422
4036
  add: addCmd3,
3423
- list: listCmd12,
4037
+ list: listCmd11,
3424
4038
  rm: rmCmd6,
3425
4039
  enable: enableCmd3,
3426
4040
  disable: disableCmd3
@@ -3428,9 +4042,9 @@ var triggerCommand = defineCommand21({
3428
4042
  });
3429
4043
 
3430
4044
  // src/commands/uninstall.ts
3431
- import { existsSync as existsSync7, readdirSync as readdirSync2, rmSync as rmSync4 } from "fs";
3432
- import { join as join6 } from "path";
3433
- import { defineCommand as defineCommand22 } from "citty";
4045
+ import { existsSync as existsSync7, readdirSync as readdirSync2, rmSync as rmSync3 } from "fs";
4046
+ import { join as join5 } from "path";
4047
+ import { defineCommand as defineCommand24 } from "citty";
3434
4048
  function makeLineReader() {
3435
4049
  let buffer = "";
3436
4050
  let ended = false;
@@ -3475,10 +4089,10 @@ async function askYes(readLine, prompt) {
3475
4089
  }
3476
4090
  function removePath(p) {
3477
4091
  if (!existsSync7(p)) return false;
3478
- rmSync4(p, { recursive: true, force: true });
4092
+ rmSync3(p, { recursive: true, force: true });
3479
4093
  return true;
3480
4094
  }
3481
- var uninstallCommand = defineCommand22({
4095
+ var uninstallCommand = defineCommand24({
3482
4096
  meta: {
3483
4097
  name: "uninstall",
3484
4098
  description: "Wipe bazilion state from ~/.bazilion (or BAZILION_HOME)"
@@ -3496,26 +4110,19 @@ var uninstallCommand = defineCommand22({
3496
4110
  },
3497
4111
  async run({ args }) {
3498
4112
  const paths = resolveCliPaths(args.home);
3499
- const dbFile = join6(paths.home, "bazilion.db");
3500
- const profilesDir = join6(paths.home, "profiles");
3501
- const agentsDir = join6(paths.home, "agents");
3502
- const groupsDir = join6(paths.home, "groups");
3503
- const skillsDir = join6(paths.home, "skills");
3504
- const logsDir = join6(paths.home, "logs");
4113
+ const dbFile = join5(paths.home, "bazilion.db");
4114
+ const profilesDir = join5(paths.home, "profiles");
4115
+ const agentsDir = join5(paths.home, "agents");
4116
+ const teamsDir = join5(paths.home, "teams");
4117
+ const skillsDir = join5(paths.home, "skills");
4118
+ const logsDir = join5(paths.home, "logs");
3505
4119
  if (!existsSync7(paths.home)) {
3506
4120
  console.log(`nothing to remove: ${paths.home} does not exist`);
3507
4121
  return;
3508
4122
  }
3509
4123
  console.log(`about to uninstall bazilion at ${paths.home}`);
3510
4124
  console.log("");
3511
- const dataTargets = [
3512
- dbFile,
3513
- `${dbFile}-wal`,
3514
- `${dbFile}-shm`,
3515
- profilesDir,
3516
- agentsDir,
3517
- groupsDir
3518
- ];
4125
+ const dataTargets = [dbFile, `${dbFile}-wal`, `${dbFile}-shm`, profilesDir, agentsDir, teamsDir];
3519
4126
  const needsPrompt = !args.yes;
3520
4127
  const readLine = needsPrompt ? makeLineReader() : null;
3521
4128
  const wipeData = args.yes || await askYes(
@@ -3541,7 +4148,7 @@ var uninstallCommand = defineCommand22({
3541
4148
  if (removePath(p)) console.log(`removed ${p}`);
3542
4149
  }
3543
4150
  if (readdirSync2(paths.home).length === 0) {
3544
- rmSync4(paths.home, { recursive: true, force: true });
4151
+ rmSync3(paths.home, { recursive: true, force: true });
3545
4152
  console.log(`removed ${paths.home}`);
3546
4153
  } else {
3547
4154
  console.log(`${paths.home} still has unmanaged files; left in place`);
@@ -3556,7 +4163,7 @@ var uninstallCommand = defineCommand22({
3556
4163
 
3557
4164
  // src/index.ts
3558
4165
  var VERSION = package_default.version;
3559
- var main = defineCommand23({
4166
+ var main = defineCommand25({
3560
4167
  meta: {
3561
4168
  name: "bazilion",
3562
4169
  version: VERSION,
@@ -3565,9 +4172,10 @@ var main = defineCommand23({
3565
4172
  subCommands: {
3566
4173
  login: loginCommand,
3567
4174
  profile: profileCommand,
3568
- "profile-group": profileGroupCommand,
3569
- group: groupCommand,
4175
+ team: teamCommand,
4176
+ "team-template": teamTemplateCommand,
3570
4177
  agent: agentCommand,
4178
+ approval: approvalCommand,
3571
4179
  skill: skillCommand,
3572
4180
  memory: memoryCommand,
3573
4181
  mcp: mcpCommand,
@@ -3622,12 +4230,22 @@ function printError(err) {
3622
4230
  console.error(" hint: host not found. Check BAZILION_SERVER / ~/.bazilion/auth.json.");
3623
4231
  }
3624
4232
  }
4233
+ function exitCodeForError(err) {
4234
+ if (err instanceof ApiClientError) {
4235
+ if (err.status === 401 || err.status === 403) return 4;
4236
+ if (err.status === 409) return 3;
4237
+ if (err.status === 400 || err.status === 422) return 2;
4238
+ return 1;
4239
+ }
4240
+ const message = err instanceof Error ? err.message : String(err);
4241
+ return /invalid|unsupported|must be|require|refusing mutation|document belongs/.test(message) ? 2 : 1;
4242
+ }
3625
4243
  function printTopLevelHelp() {
3626
4244
  console.log(`Multi-agent runtime (bazilion v${VERSION})`);
3627
4245
  console.log("");
3628
4246
  console.log("USAGE bazilion <command> [args]");
3629
4247
  console.log("");
3630
- const groups = [
4248
+ const teams = [
3631
4249
  {
3632
4250
  title: "setup",
3633
4251
  items: [
@@ -3641,8 +4259,8 @@ function printTopLevelHelp() {
3641
4259
  title: "catalog",
3642
4260
  items: [
3643
4261
  ["profile", "Manage profiles (templates agents are spawned from)"],
3644
- ["profile-group", "Manage profile groups (preconfigured team templates)"],
3645
- ["group", "Manage groups (collaboration context \u2014 filesystem root + USER.md + roster)"],
4262
+ ["team-template", "Inspect and exchange reusable Team Templates"],
4263
+ ["team", "Manage teams (collaboration context \u2014 filesystem root + USER.md + roster)"],
3646
4264
  ["skill", "Manage the skill library"],
3647
4265
  ["provider", "Manage and test LLM providers"],
3648
4266
  ["config", "Manage service config (credentials + URLs/IDs)"],
@@ -3652,8 +4270,9 @@ function printTopLevelHelp() {
3652
4270
  {
3653
4271
  title: "agents",
3654
4272
  items: [
4273
+ ["approval", "Review and decide communication approval attempts"],
3655
4274
  ["agent", "Spawn, list, chat, archive agents"],
3656
- ["memory", "Read/write a group's shared memory"],
4275
+ ["memory", "Read/write a team's shared memory"],
3657
4276
  ["send", "Send a message from one agent to another"],
3658
4277
  ["inbox", "Inspect agent inboxes"],
3659
4278
  ["trigger", "Manage agent heartbeats / cron triggers"]
@@ -3679,8 +4298,8 @@ function printTopLevelHelp() {
3679
4298
  items: [["completion", "Print shell completion script (bash | zsh | fish)"]]
3680
4299
  }
3681
4300
  ];
3682
- const nameWidth = 12;
3683
- for (const g of groups) {
4301
+ const nameWidth = 15;
4302
+ for (const g of teams) {
3684
4303
  console.log(` ${g.title}`);
3685
4304
  for (const [name, desc] of g.items) {
3686
4305
  console.log(` ${name.padEnd(nameWidth)}${desc}`);
@@ -3709,7 +4328,7 @@ async function entry() {
3709
4328
  await runCommand(main, { rawArgs });
3710
4329
  } catch (err) {
3711
4330
  printError(err);
3712
- process.exit(1);
4331
+ process.exit(exitCodeForError(err));
3713
4332
  }
3714
4333
  }
3715
4334
  entry();