@botbuddy/cli 1.63.44 → 1.64.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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "release_version": "1.63.44",
3
- "source_commit": "6fb9ea556869f4b6bb5b1851941dc348009198ff",
4
- "source_sha256": "175730f9512d5a1fa81e4800f0be93420e5fd91f1968bba4cd264611b8ae0f82",
2
+ "release_version": "1.64.0",
3
+ "source_commit": "e6cc3786c39bf5326fe5b5dabccd80c1fba8b17d",
4
+ "source_sha256": "0f97518d4f2ad1ac4d1195fd80ce4fa875a587b3ab2f102fbb5e28d6d5d62172",
5
5
  "target": "darwin-arm64",
6
- "sha256": "1740585f4d9e5ce03d798353c1c473b6b818191f83d3a6e63b8e94f6e5d975bb"
6
+ "sha256": "675ce80ef07e7ef87f3a9111e911cd6241a775d5af4812dd9f53fb29846b9832"
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "release_version": "1.63.44",
3
- "source_commit": "6fb9ea556869f4b6bb5b1851941dc348009198ff",
4
- "source_sha256": "175730f9512d5a1fa81e4800f0be93420e5fd91f1968bba4cd264611b8ae0f82",
2
+ "release_version": "1.64.0",
3
+ "source_commit": "e6cc3786c39bf5326fe5b5dabccd80c1fba8b17d",
4
+ "source_sha256": "0f97518d4f2ad1ac4d1195fd80ce4fa875a587b3ab2f102fbb5e28d6d5d62172",
5
5
  "target": "linux-x64",
6
- "sha256": "93c1837e1aad2e8cb048399e57d2d4504db08d5edda38a92369558ceb4c4e8c4"
6
+ "sha256": "3223c862b52f1e81777e7c9403f6c854c5192f618c2c7ee46c56ad5b0a9ccfd9"
7
7
  }
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "schema_version": 1,
3
- "release_version": "1.63.44",
4
- "source_commit": "6fb9ea556869f4b6bb5b1851941dc348009198ff",
5
- "source_sha256": "175730f9512d5a1fa81e4800f0be93420e5fd91f1968bba4cd264611b8ae0f82",
3
+ "release_version": "1.64.0",
4
+ "source_commit": "e6cc3786c39bf5326fe5b5dabccd80c1fba8b17d",
5
+ "source_sha256": "0f97518d4f2ad1ac4d1195fd80ce4fa875a587b3ab2f102fbb5e28d6d5d62172",
6
6
  "targets": {
7
7
  "darwin-arm64": {
8
8
  "goos": "darwin",
9
9
  "goarch": "arm64",
10
10
  "binary": "daemon/bin/darwin-arm64/botbuddy-daemon",
11
- "sha256": "1740585f4d9e5ce03d798353c1c473b6b818191f83d3a6e63b8e94f6e5d975bb",
11
+ "sha256": "675ce80ef07e7ef87f3a9111e911cd6241a775d5af4812dd9f53fb29846b9832",
12
12
  "mode": "0755"
13
13
  },
14
14
  "linux-x64": {
15
15
  "goos": "linux",
16
16
  "goarch": "amd64",
17
17
  "binary": "daemon/bin/linux-x64/botbuddy-daemon",
18
- "sha256": "93c1837e1aad2e8cb048399e57d2d4504db08d5edda38a92369558ceb4c4e8c4",
18
+ "sha256": "3223c862b52f1e81777e7c9403f6c854c5192f618c2c7ee46c56ad5b0a9ccfd9",
19
19
  "mode": "0755"
20
20
  }
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbuddy/cli",
3
- "version": "1.63.44",
3
+ "version": "1.64.0",
4
4
  "description": "BotBuddy \u2014 Swarm coordination CLI for multi-agent workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,81 @@
1
+ import { callToolJson, resolveCallAuth } from "../api.mjs";
2
+ import {
3
+ assertSshHost,
4
+ installedBinaryPath,
5
+ stageRemoteDaemonRelease,
6
+ } from "./installer.mjs";
7
+ import { validateDaemonRelease } from "./release.mjs";
8
+ import { nativeHandoverCommand } from "./handover.mjs";
9
+ const fail = (code) => {
10
+ throw new Error(code);
11
+ };
12
+ // One explicit administrator installation grants only the fixed native
13
+ // coordinator/schedule. Persisted operator opt-in remains a separate drawer act.
14
+ export async function installAutomaticDaemonUpdater(spec, {
15
+ validateRelease = validateDaemonRelease,
16
+ resolveAuth = resolveCallAuth,
17
+ identity = callToolJson,
18
+ stage = stageRemoteDaemonRelease,
19
+ native = nativeHandoverCommand,
20
+ } = {}) {
21
+ if (
22
+ !spec || typeof spec !== "object" || Array.isArray(spec) ||
23
+ Object.keys(spec).some((key) =>
24
+ ![
25
+ "platform",
26
+ "arch",
27
+ "sshHost",
28
+ "serviceUser",
29
+ "releaseRoot",
30
+ "expectedHostKey",
31
+ "tenant",
32
+ ].includes(key)
33
+ ) || !["linux", "darwin"].includes(spec.platform) ||
34
+ typeof spec.serviceUser !== "string" || spec.serviceUser === "root" ||
35
+ !/^[a-z_][a-z0-9_-]*$/i.test(spec.serviceUser) ||
36
+ !/^bbh-[0-9a-f]{24}$/.test(spec.expectedHostKey) ||
37
+ typeof spec.tenant !== "string" || !spec.tenant
38
+ ) fail("daemon_automatic_install_spec_invalid");
39
+ assertSshHost(spec.sshHost);
40
+ const release = await validateRelease({ releaseRoot: spec.releaseRoot }, {
41
+ platform: spec.platform,
42
+ arch: spec.arch,
43
+ });
44
+ const resolved = await resolveAuth({
45
+ toolName: "daemon_handover",
46
+ preferSession: false,
47
+ });
48
+ if (resolved?.error || !resolved?.auth) {
49
+ fail("daemon_automatic_install_auth_required");
50
+ }
51
+ const who = await identity("whoami", {}, {
52
+ auth: resolved.auth,
53
+ tenant: spec.tenant,
54
+ });
55
+ if (
56
+ !who?.ok || who.isError || typeof who.data?.owner_email !== "string" ||
57
+ !who.data.owner_email.includes("@") || who.data.tenant_id !== spec.tenant
58
+ ) fail("daemon_automatic_install_owner_unavailable");
59
+ const staged = await stage({
60
+ platform: spec.platform,
61
+ host: spec.sshHost,
62
+ user: spec.serviceUser,
63
+ release,
64
+ });
65
+ const binary = installedBinaryPath(release);
66
+ if (staged?.binary !== binary) fail("daemon_automatic_install_stage_invalid");
67
+ const result = await native({
68
+ host: spec.sshHost,
69
+ binary,
70
+ mode: "automatic-install",
71
+ input: {
72
+ host_key: spec.expectedHostKey,
73
+ owner_email: who.data.owner_email,
74
+ tenant_id: who.data.tenant_id,
75
+ },
76
+ });
77
+ if (result?.installed !== true || result.protocol !== 2) {
78
+ fail("daemon_automatic_install_receipt_invalid");
79
+ }
80
+ return { installed: true, protocol: 2, host_key: spec.expectedHostKey };
81
+ }
@@ -5,6 +5,7 @@ import { tmpdir } from "node:os";
5
5
  import { join } from "node:path";
6
6
  import { promisify } from "node:util";
7
7
  import { registerContainerHost } from "../api.mjs";
8
+ import { installAutomaticDaemonUpdater } from "./automatic.mjs";
8
9
  import { upgradeDaemonHost } from "./handover.mjs";
9
10
  import { awaitHostApproval } from "./approval-wait.mjs";
10
11
  import { bootstrapFreshDaemon } from "./bootstrap.mjs";
@@ -49,6 +50,7 @@ export const daemonHelp = `Usage:
49
50
  bb daemon config-render '<json host policy>'
50
51
  bb daemon enroll '<json host-bound enrollment spec>'
51
52
  bb daemon bootstrap '<json fresh-host bootstrap spec>'
53
+ bb daemon updater-install '<json automatic updater installation spec>'
52
54
  bb daemon upgrade '<json controlled host upgrade spec>'
53
55
 
54
56
  The Go payload is verified from the extracted universal package before sudo.
@@ -293,6 +295,7 @@ export async function cmdDaemon(args, {
293
295
  verifyRemoteHelperIdentity = verifyRemoteHelperIdentityOnTarget,
294
296
  bootstrap = bootstrapFreshDaemon,
295
297
  upgrade = upgradeDaemonHost,
298
+ installAutomaticUpdater = installAutomaticDaemonUpdater,
296
299
  registerHost = registerContainerHost,
297
300
  createBootstrapIdentity = createRemoteBootstrapIdentity,
298
301
  inspectBootstrapIdentity = inspectRemoteBootstrapIdentity,
@@ -305,6 +308,11 @@ export async function cmdDaemon(args, {
305
308
  log(daemonHelp);
306
309
  return 0;
307
310
  }
311
+ if(args[0]==="updater-install"){
312
+ if(args.length!==2)fail("Usage: bb daemon updater-install '<json automatic updater installation spec>'");
313
+ let spec;try{spec=JSON.parse(args[1]);}catch{fail("daemon_automatic_install_spec_invalid");}
314
+ log(JSON.stringify(await installAutomaticUpdater(spec)));return 0;
315
+ }
308
316
  if(args[0]==="upgrade"){
309
317
  if(args.length!==2)fail("Usage: bb daemon upgrade '<json controlled host upgrade spec>'");
310
318
  let spec;try{spec=JSON.parse(args[1]);}catch{fail("daemon_handover_spec_invalid");}
@@ -27,9 +27,9 @@ export function nativeHandoverCommand(
27
27
  { spawnImpl = spawn } = {},
28
28
  ) {
29
29
  if (
30
- !immutableBinaryRE.test(binary) || !["inspect", "submit"].includes(mode)
30
+ !immutableBinaryRE.test(binary) || !["inspect", "submit", "automatic-install"].includes(mode)
31
31
  ) fail("daemon_handover_command_invalid");
32
- const flag = mode === "inspect"
32
+ const flag = mode === "automatic-install" ? "--native-automatic-update-install" : mode === "inspect"
33
33
  ? "--native-handover-inspect"
34
34
  : "--native-handover-submit";
35
35
  let command = "sudo", args = ["-n", binary, flag];