@botbuddy/cli 1.64.32 → 1.64.34

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.64.32",
3
- "source_commit": "170ead0f849e941e0076215bba062cb9f7424327",
4
- "source_sha256": "589ea191f9c830eef71bd941dcd32ea4ba14972537805f12d07bf91231fae7ef",
2
+ "release_version": "1.64.34",
3
+ "source_commit": "512513a6c1887db44c8a1743abb0f10ff844c1b0",
4
+ "source_sha256": "f6675485098c6bc62cab5119a356db6c12f4247e153f241584f0a349c09d9454",
5
5
  "target": "darwin-arm64",
6
- "sha256": "bf4295c5e7d4e6da1019d5c553bc8ab978d36fbbd26acb8c53831c8233c91e0c"
6
+ "sha256": "5fba031a897c73f93e078e0aca1c4e8338926dc3501e512b3a9f0d706f39708c"
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "release_version": "1.64.32",
3
- "source_commit": "170ead0f849e941e0076215bba062cb9f7424327",
4
- "source_sha256": "589ea191f9c830eef71bd941dcd32ea4ba14972537805f12d07bf91231fae7ef",
2
+ "release_version": "1.64.34",
3
+ "source_commit": "512513a6c1887db44c8a1743abb0f10ff844c1b0",
4
+ "source_sha256": "f6675485098c6bc62cab5119a356db6c12f4247e153f241584f0a349c09d9454",
5
5
  "target": "linux-x64",
6
- "sha256": "52d1d1da89ea20d675dbe07a598a2553a52102bcbfe549171005724310e594d7"
6
+ "sha256": "7d722a654dd8da0794024fc6c0dba71034d631e1de87f434e5fbd8399f0d08af"
7
7
  }
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "schema_version": 1,
3
- "release_version": "1.64.32",
4
- "source_commit": "170ead0f849e941e0076215bba062cb9f7424327",
5
- "source_sha256": "589ea191f9c830eef71bd941dcd32ea4ba14972537805f12d07bf91231fae7ef",
3
+ "release_version": "1.64.34",
4
+ "source_commit": "512513a6c1887db44c8a1743abb0f10ff844c1b0",
5
+ "source_sha256": "f6675485098c6bc62cab5119a356db6c12f4247e153f241584f0a349c09d9454",
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": "bf4295c5e7d4e6da1019d5c553bc8ab978d36fbbd26acb8c53831c8233c91e0c",
11
+ "sha256": "5fba031a897c73f93e078e0aca1c4e8338926dc3501e512b3a9f0d706f39708c",
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": "52d1d1da89ea20d675dbe07a598a2553a52102bcbfe549171005724310e594d7",
18
+ "sha256": "7d722a654dd8da0794024fc6c0dba71034d631e1de87f434e5fbd8399f0d08af",
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.64.32",
3
+ "version": "1.64.34",
4
4
  "description": "BotBuddy \u2014 Swarm coordination CLI for multi-agent workflows",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api.mjs CHANGED
@@ -415,6 +415,8 @@ export function containerHostRegisterEndpoint(serverUrl = SERVER_URL) {
415
415
  */
416
416
  export function registerContainerHost(body, options = {}) { return postContainerHostControl(body, options, "register", "container_host_register"); }
417
417
  export function daemonHandoverRequest(body, options = {}) { return postContainerHostControl(body, options, "handover", "daemon_handover"); }
418
+ // BOT-3127: the owner-only automatic-update describe read (same auth as handover).
419
+ export function daemonAutomaticUpdateRequest(body, options = {}) { return postContainerHostControl(body, options, "automatic-update", "daemon_handover"); }
418
420
  async function postContainerHostControl(body, {
419
421
  fetchImpl = fetch,
420
422
  auth: pinnedAuth = null,
@@ -1,4 +1,4 @@
1
- import { callToolJson, resolveCallAuth } from "../api.mjs";
1
+ import { callToolJson, daemonAutomaticUpdateRequest, resolveCallAuth } from "../api.mjs";
2
2
  import {
3
3
  assertSshHost,
4
4
  installedBinaryPath,
@@ -11,13 +11,20 @@ const fail = (code) => {
11
11
  };
12
12
  // One explicit administrator installation grants only the fixed native
13
13
  // coordinator/schedule. Persisted operator opt-in remains a separate drawer act.
14
+ // BOT-3127: user-scoped. The spec names no tenant; the host's owner asks the
15
+ // server for the host's inert rollout label and the root binding pins that.
14
16
  export async function installAutomaticDaemonUpdater(spec, {
15
17
  validateRelease = validateDaemonRelease,
16
18
  resolveAuth = resolveCallAuth,
17
19
  identity = callToolJson,
20
+ describe = daemonAutomaticUpdateRequest,
18
21
  stage = stageRemoteDaemonRelease,
19
22
  native = nativeHandoverCommand,
20
23
  } = {}) {
24
+ if (spec && typeof spec === "object" && Object.hasOwn(spec, "tenant")) {
25
+ // Automatic updates belong to the host's owner, not a project.
26
+ fail("daemon_automatic_install_tenant_not_used");
27
+ }
21
28
  if (
22
29
  !spec || typeof spec !== "object" || Array.isArray(spec) ||
23
30
  Object.keys(spec).some((key) =>
@@ -28,13 +35,11 @@ export async function installAutomaticDaemonUpdater(spec, {
28
35
  "serviceUser",
29
36
  "releaseRoot",
30
37
  "expectedHostKey",
31
- "tenant",
32
38
  ].includes(key)
33
39
  ) || !["linux", "darwin"].includes(spec.platform) ||
34
40
  typeof spec.serviceUser !== "string" || spec.serviceUser === "root" ||
35
41
  !/^[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
42
+ !/^bbh-[0-9a-f]{24}$/.test(spec.expectedHostKey)
38
43
  ) fail("daemon_automatic_install_spec_invalid");
39
44
  assertSshHost(spec.sshHost);
40
45
  const release = await validateRelease({ releaseRoot: spec.releaseRoot }, {
@@ -48,14 +53,30 @@ export async function installAutomaticDaemonUpdater(spec, {
48
53
  if (resolved?.error || !resolved?.auth) {
49
54
  fail("daemon_automatic_install_auth_required");
50
55
  }
51
- const who = await identity("whoami", {}, {
52
- auth: resolved.auth,
53
- tenant: spec.tenant,
54
- });
56
+ const who = await identity("whoami", {}, { auth: resolved.auth });
55
57
  if (
56
58
  !who?.ok || who.isError || typeof who.data?.owner_email !== "string" ||
57
- !who.data.owner_email.includes("@") || who.data.tenant_id !== spec.tenant
59
+ !who.data.owner_email.includes("@")
58
60
  ) fail("daemon_automatic_install_owner_unavailable");
61
+ const described = await describe({
62
+ action: "describe",
63
+ host_key: spec.expectedHostKey,
64
+ }, { auth: resolved.auth });
65
+ const owner = described?.data?.owner_email, label = described?.data?.tenant_id;
66
+ if (
67
+ !described?.ok || described.data?.success !== true ||
68
+ described.data.host_key !== spec.expectedHostKey ||
69
+ typeof owner !== "string" || owner.toLowerCase() !== who.data.owner_email.toLowerCase() ||
70
+ typeof label !== "string" || !label
71
+ ) {
72
+ // A 4xx answer carries its code in `error` (e.g. daemon_host_scope).
73
+ const code = described?.data?.code ?? described?.error;
74
+ fail(
75
+ typeof code === "string" && /^(?:[A-Z_]{1,64}|[a-z_]{1,64})$/.test(code)
76
+ ? `daemon_automatic_install_owner_refused: ${code}`
77
+ : "daemon_automatic_install_owner_refused",
78
+ );
79
+ }
59
80
  const staged = await stage({
60
81
  platform: spec.platform,
61
82
  host: spec.sshHost,
@@ -70,8 +91,8 @@ export async function installAutomaticDaemonUpdater(spec, {
70
91
  mode: "automatic-install",
71
92
  input: {
72
93
  host_key: spec.expectedHostKey,
73
- owner_email: who.data.owner_email,
74
- tenant_id: who.data.tenant_id,
94
+ owner_email: owner,
95
+ tenant_id: label,
75
96
  },
76
97
  });
77
98
  if (result?.installed !== true || result.protocol !== 2) {
package/src/stack.mjs CHANGED
@@ -5618,6 +5618,9 @@ export async function cmdRun(opts, childArgv, {
5618
5618
  receipt.feedback_recovery = { status: "not_yet_checked", available_after: "command_exits", recover_command: "bb feedback recover", list_command: "bb call list_feedback" };
5619
5619
  }
5620
5620
  const code = emit(receipt, opts, result.exitCode);
5621
+ // BOT-3126: the requester line already says BotBuddy was not at fault; the
5622
+ // launcher's generic "If BotBuddy is blocking your work" reminder would undercut it.
5623
+ if (failureClass.category === "requester") markFeedback();
5621
5624
  try {
5622
5625
  const outcome = await report({ fields: stackRunOutcomeFields(result), exitCode: code, runId, opts, env, durationMs: now() - startedAt, channel: result?.[OUTCOME_CHANNEL] ?? null });
5623
5626
  const capture = outcome?.feedback_capture;