@botbuddy/cli 1.64.17 → 1.64.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/daemon/bin/darwin-arm64/botbuddy-daemon +0 -0
- package/daemon/bin/linux-x64/botbuddy-daemon +0 -0
- package/daemon-release/darwin-arm64.json +4 -4
- package/daemon-release/linux-x64.json +4 -4
- package/daemon-release/manifest.json +5 -5
- package/package.json +1 -1
- package/src/commands.mjs +1 -1
- package/src/feedback.mjs +13 -0
- package/src/staging-pool/cli.mjs +23 -2
- package/src/staging-pool/help.mjs +4 -2
- package/src/update-check.mjs +121 -7
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"release_version": "1.64.
|
|
3
|
-
"source_commit": "
|
|
4
|
-
"source_sha256": "
|
|
2
|
+
"release_version": "1.64.19",
|
|
3
|
+
"source_commit": "44604deb1f6fa2e2923d532bf4bbab095c3c429f",
|
|
4
|
+
"source_sha256": "5cd52ae09d485ea806fb37f86b1da9fa75dc6e37e7bb58952c25a6d695e1555b",
|
|
5
5
|
"target": "darwin-arm64",
|
|
6
|
-
"sha256": "
|
|
6
|
+
"sha256": "d180a0533460babac47b360dfce0250ba0ef90ce0f21e40e22df3ab632033f3d"
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"release_version": "1.64.
|
|
3
|
-
"source_commit": "
|
|
4
|
-
"source_sha256": "
|
|
2
|
+
"release_version": "1.64.19",
|
|
3
|
+
"source_commit": "44604deb1f6fa2e2923d532bf4bbab095c3c429f",
|
|
4
|
+
"source_sha256": "5cd52ae09d485ea806fb37f86b1da9fa75dc6e37e7bb58952c25a6d695e1555b",
|
|
5
5
|
"target": "linux-x64",
|
|
6
|
-
"sha256": "
|
|
6
|
+
"sha256": "137ff9f4318cd332d1320847f3837b5d8f23812e626a96fdf61d9d331d750b1d"
|
|
7
7
|
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": 1,
|
|
3
|
-
"release_version": "1.64.
|
|
4
|
-
"source_commit": "
|
|
5
|
-
"source_sha256": "
|
|
3
|
+
"release_version": "1.64.19",
|
|
4
|
+
"source_commit": "44604deb1f6fa2e2923d532bf4bbab095c3c429f",
|
|
5
|
+
"source_sha256": "5cd52ae09d485ea806fb37f86b1da9fa75dc6e37e7bb58952c25a6d695e1555b",
|
|
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": "
|
|
11
|
+
"sha256": "d180a0533460babac47b360dfce0250ba0ef90ce0f21e40e22df3ab632033f3d",
|
|
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": "
|
|
18
|
+
"sha256": "137ff9f4318cd332d1320847f3837b5d8f23812e626a96fdf61d9d331d750b1d",
|
|
19
19
|
"mode": "0755"
|
|
20
20
|
}
|
|
21
21
|
}
|
package/package.json
CHANGED
package/src/commands.mjs
CHANGED
|
@@ -147,7 +147,7 @@ export async function run(argv, {
|
|
|
147
147
|
case "wait": return runWait(args);
|
|
148
148
|
case "pw": return runPw(args);
|
|
149
149
|
// BOT-2084: the human-installed staging session pool broker.
|
|
150
|
-
case "staging-pool": return (await import("./staging-pool/cli.mjs")).runStagingPool(args);
|
|
150
|
+
case "staging-pool": return (await import("./staging-pool/cli.mjs")).runStagingPool(args, { cliVersion: VERSION });
|
|
151
151
|
case "mcp": return cmdMcp(args);
|
|
152
152
|
case "resources": return callTool("list_resources");
|
|
153
153
|
case "agents": return callTool("list_agents");
|
package/src/feedback.mjs
CHANGED
|
@@ -37,6 +37,19 @@ and its idempotency_key unchanged if delivery is uncertain; retry using the
|
|
|
37
37
|
same reporter and tenant. Tenant identity sharing follows the server's policy;
|
|
38
38
|
a report cannot override it.
|
|
39
39
|
|
|
40
|
+
To share separately reviewed anonymous details, prepare .botbuddy/anonymous-evidence.json
|
|
41
|
+
with feedback_id and an evidence object, then run:
|
|
42
|
+
bb call help --tool preview_feedback_anonymous_evidence
|
|
43
|
+
bb call preview_feedback_anonymous_evidence --json "$(cat .botbuddy/anonymous-evidence.json)"
|
|
44
|
+
Inspect every field: automatic checks cannot detect every person or organization.
|
|
45
|
+
Prepare .botbuddy/anonymous-approval.json with the exact evidence, preview_sha256,
|
|
46
|
+
expected_revision from the preview, and confirmed: true, then run:
|
|
47
|
+
bb call share_feedback_anonymous_evidence --json "$(cat .botbuddy/anonymous-approval.json)"
|
|
48
|
+
To withdraw, replace <feedback_id> with the original ID and run:
|
|
49
|
+
bb call withdraw_feedback_anonymous_evidence --feedback_id <feedback_id>
|
|
50
|
+
The separately approved details stay in BotBuddy and do not enable tenant identification.
|
|
51
|
+
For file templates and all commands, run: curl -fsS https://app.bot-buddy.ai/agent-feedback.json
|
|
52
|
+
|
|
40
53
|
An unavailable service does not mean a report was recorded. A failed send is
|
|
41
54
|
queued privately only when the original agent and tenant can be bound to the
|
|
42
55
|
cached session. Run bb feedback flush to replay those drafts after reconnecting.
|
package/src/staging-pool/cli.mjs
CHANGED
|
@@ -398,6 +398,26 @@ export function upgradeNotice(ctx) {
|
|
|
398
398
|
return { upgrade: { reason: "installed_before_registry", message: "This pool was installed from a repository checkout; re-install it from the BotBuddy control plane (keeps counts and interval).", next: installCommandFor(ctx.tenant) } };
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
+
// BOT-3016: the launchd job runs a pinned runtime copy, not this CLI. Status
|
|
402
|
+
// names both versions and, when they differ on a control-plane pool, the
|
|
403
|
+
// agent-safe refresh (bb update runs it too). cliVersion is null inside the
|
|
404
|
+
// bundled job copy, which has no package.json to read.
|
|
405
|
+
export function runtimeNotice(ctx, cliVersion) {
|
|
406
|
+
if (!ctx?.installed || ctx.installed.error) return {};
|
|
407
|
+
const runtimeVersion = ctx.installed.runtime?.version ?? null;
|
|
408
|
+
const versions = { runtimeVersion, ...(cliVersion ? { cliVersion } : {}) };
|
|
409
|
+
if (!cliVersion || runtimeVersion === cliVersion || ctx.installed.source !== "control-plane" || !ctx.tenant || !ctx.poolId) return versions;
|
|
410
|
+
const runs = runtimeVersion ? `runs v${runtimeVersion}` : "runs an untracked runtime copy";
|
|
411
|
+
return {
|
|
412
|
+
...versions,
|
|
413
|
+
runtimeBehind: {
|
|
414
|
+
reason: "runtime_behind",
|
|
415
|
+
message: `The pool job ${runs}, but this CLI is v${cliVersion}. bb update refreshes it; so does the next command.`,
|
|
416
|
+
next: `bb staging-pool refresh-runtime --tenant ${shellWord(String(ctx.tenant))} --pool ${shellWord(String(ctx.poolId))}`,
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
401
421
|
export async function runStagingPool(argv, deps = {}) {
|
|
402
422
|
const {
|
|
403
423
|
env = process.env,
|
|
@@ -415,6 +435,7 @@ export async function runStagingPool(argv, deps = {}) {
|
|
|
415
435
|
nodeBin = process.execPath,
|
|
416
436
|
sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
417
437
|
readSecretFile = readFileSync,
|
|
438
|
+
cliVersion = null,
|
|
418
439
|
} = deps;
|
|
419
440
|
|
|
420
441
|
const redactor = createRedactor();
|
|
@@ -599,10 +620,10 @@ export async function runStagingPool(argv, deps = {}) {
|
|
|
599
620
|
const entry = options.persona ? findPersona(ctx.poolBinding, options.persona) : null;
|
|
600
621
|
if (options.persona && !entry) assertPersonaAllowed(target, options.persona);
|
|
601
622
|
const health = await assessHealth({ ctx, pool, now, exec, uid, requestedPersona: entry?.email });
|
|
602
|
-
emit({ command: "status", check: true, ...health, ...upgradeNotice(ctx) });
|
|
623
|
+
emit({ command: "status", check: true, ...health, ...upgradeNotice(ctx), ...runtimeNotice(ctx, cliVersion) });
|
|
603
624
|
return health.ok ? 0 : 5;
|
|
604
625
|
}
|
|
605
|
-
emit({ ok: true, command: "status", ...(await pool.status()), ...upgradeNotice(ctx) });
|
|
626
|
+
emit({ ok: true, command: "status", ...(await pool.status()), ...upgradeNotice(ctx), ...runtimeNotice(ctx, cliVersion) });
|
|
606
627
|
return 0;
|
|
607
628
|
},
|
|
608
629
|
|
|
@@ -96,14 +96,16 @@ ANYONE (agents too) — existing runtime maintenance, never sign-in
|
|
|
96
96
|
and this published CLI package. Preserves credentials, sessions, counts,
|
|
97
97
|
interval and plist. The existing launchd job refills on its next tick.
|
|
98
98
|
No caller path or runtime content is accepted; no sign-in is performed.
|
|
99
|
+
bb update runs it for every installed pool after a confirmed upgrade.
|
|
99
100
|
|
|
100
101
|
HUMAN ONLY (Jono, from Terminal.app or iTerm) — refused inside a Claude or Codex session
|
|
101
102
|
These sign in with the persona password or change the standing sessions.
|
|
102
103
|
install --tenant <slug> [--pool <pool_id>] --botbuddy-bin <absolute path> [--interval <seconds>]
|
|
103
104
|
Reads the tenant's registered pool from the BotBuddy control plane, copies
|
|
104
105
|
the job to the pool home, writes its config and loads the launchd job. Run
|
|
105
|
-
it from any directory.
|
|
106
|
-
|
|
106
|
+
it from any directory. bb update refreshes the job's runtime, so re-run
|
|
107
|
+
install only when status or bb update names it; it keeps the counts and
|
|
108
|
+
interval. --pool is needed only when the tenant has several.
|
|
107
109
|
e.g. bb staging-pool install --tenant botbuddy --botbuddy-bin "$(command -v botbuddy)"
|
|
108
110
|
tick [--pool <pool_id>] [--home <pool home>]
|
|
109
111
|
One refresh and refill pass now (what the job runs).
|
package/src/update-check.mjs
CHANGED
|
@@ -11,14 +11,23 @@
|
|
|
11
11
|
// `cmdUpdate` deliberately does NOT update in-process (BOT-1499: a self-update
|
|
12
12
|
// that replaces its own running files can kill itself mid-install). It hands
|
|
13
13
|
// off to a detached, unref'd `npm install -g` and exits 0.
|
|
14
|
+
//
|
|
15
|
+
// BOT-3016: an installed staging session pool is a standing launchd job that
|
|
16
|
+
// runs a pinned copy of the CLI, so npm alone leaves it on old code. After a
|
|
17
|
+
// confirmed update, `cmdUpdate` refreshes each control-plane pool with the NEW
|
|
18
|
+
// package's agent-safe `staging-pool refresh-runtime` (BOT-2673), which derives
|
|
19
|
+
// its runtime from its own package path — hence a child of the new binary, not
|
|
20
|
+
// this process. A refusal is reported once and never fails the update.
|
|
14
21
|
|
|
15
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
22
|
+
import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
16
23
|
import { readFileSync } from "node:fs";
|
|
17
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
24
|
+
import { execFile, spawn, spawnSync } from "node:child_process";
|
|
18
25
|
import { homedir } from "node:os";
|
|
19
26
|
import { dirname, join } from "node:path";
|
|
27
|
+
import { promisify } from "node:util";
|
|
20
28
|
|
|
21
29
|
import { VERSION } from "./version.mjs";
|
|
30
|
+
import { installLine } from "./staging-pool/errors.mjs";
|
|
22
31
|
|
|
23
32
|
export const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
24
33
|
export const NPM_LATEST_URL = "https://registry.npmjs.org/@botbuddy/cli/latest";
|
|
@@ -118,11 +127,16 @@ export async function maybeWarnStale({
|
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
|
|
121
|
-
export function
|
|
130
|
+
export function readNpmGlobalRoot({ npmBin = "npm", shellOpt = {}, probeImpl = spawnSync } = {}) {
|
|
122
131
|
const root = probeImpl(npmBin, ["root", "-g"], { encoding: "utf8", ...shellOpt });
|
|
123
132
|
if (root?.error || root?.status !== 0) throw new Error(`npm global root lookup failed for ${npmBin}`);
|
|
124
133
|
const directory = String(root?.stdout ?? "").trim();
|
|
125
134
|
if (!directory) throw new Error("npm global root lookup returned no directory");
|
|
135
|
+
return directory;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function readInstalledVersion({ npmBin = "npm", shellOpt = {}, probeImpl = spawnSync, readPackage = readFileSync } = {}) {
|
|
139
|
+
const directory = readNpmGlobalRoot({ npmBin, shellOpt, probeImpl });
|
|
126
140
|
const packageJson = JSON.parse(readPackage(join(directory, "@botbuddy", "cli", "package.json"), "utf8"));
|
|
127
141
|
if (typeof packageJson?.version !== "string" || !parseSemver(packageJson.version)) throw new Error("installed @botbuddy/cli package has no valid version");
|
|
128
142
|
return packageJson.version;
|
|
@@ -130,7 +144,7 @@ export function readInstalledVersion({ npmBin = "npm", shellOpt = {}, probeImpl
|
|
|
130
144
|
|
|
131
145
|
// `botbuddy update` waits for npm because the terminal result, rather than the
|
|
132
146
|
// child-process launch, is the only trustworthy confirmation an update worked.
|
|
133
|
-
export function cmdUpdate({ version = VERSION, spawnImpl = spawn, probeImpl = spawnSync, readInstalledVersion: installedVersion = readInstalledVersion, log = (line) => console.log(line), platform = process.platform, stderr = process.stderr } = {}) {
|
|
147
|
+
export function cmdUpdate({ version = VERSION, spawnImpl = spawn, probeImpl = spawnSync, readInstalledVersion: installedVersion = readInstalledVersion, refreshPools = refreshPoolsFromNewPackage, log = (line) => console.log(line), platform = process.platform, stderr = process.stderr } = {}) {
|
|
134
148
|
// BOT-1566 (Codex P1/P2): on Windows npm is the `npm.cmd` shim, and Node
|
|
135
149
|
// cannot spawn a .cmd file shell-free (docs) — run it through a shell on
|
|
136
150
|
// win32 (args are all static constants, so no injection surface) and select
|
|
@@ -179,14 +193,114 @@ export function cmdUpdate({ version = VERSION, spawnImpl = spawn, probeImpl = sp
|
|
|
179
193
|
resolve(1);
|
|
180
194
|
return;
|
|
181
195
|
}
|
|
196
|
+
let installed;
|
|
182
197
|
try {
|
|
183
|
-
|
|
184
|
-
log(`✓ Updated to v${installed}`);
|
|
185
|
-
resolve(0);
|
|
198
|
+
installed = installedVersion({ npmBin, shellOpt });
|
|
186
199
|
} catch (error) {
|
|
187
200
|
try { stderr.write(`botbuddy update: npm completed but could not verify the installed version (${error?.message ?? error})\n`); } catch { /* ignore */ }
|
|
188
201
|
resolve(1);
|
|
202
|
+
return;
|
|
189
203
|
}
|
|
204
|
+
log(`✓ Updated to v${installed}`);
|
|
205
|
+
// BOT-3016: the update succeeded; a pool refresh problem is reported, never an exit code.
|
|
206
|
+
Promise.resolve()
|
|
207
|
+
.then(() => refreshPools({ installedVersion: installed, npmBin, shellOpt, probeImpl, log, stderr }))
|
|
208
|
+
.catch((error) => {
|
|
209
|
+
try { stderr.write(`botbuddy update: the installed staging pools were not refreshed (${error?.message ?? error}); run bb staging-pool status\n`); } catch { /* ignore */ }
|
|
210
|
+
})
|
|
211
|
+
.finally(() => resolve(0));
|
|
190
212
|
});
|
|
191
213
|
});
|
|
192
214
|
}
|
|
215
|
+
|
|
216
|
+
// ─── BOT-3016: refresh installed staging-pool runtimes after an update ───────
|
|
217
|
+
|
|
218
|
+
export const REFRESH_TIMEOUT_MS = 120_000;
|
|
219
|
+
const HUMAN_NEXT = "human, from Terminal.app or iTerm";
|
|
220
|
+
|
|
221
|
+
export function stagingPoolsRoot(home = homedir()) {
|
|
222
|
+
return join(home, ".botbuddy", "staging-session-pool");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function lastJsonLine(text) {
|
|
226
|
+
const lines = String(text ?? "").split("\n").filter((line) => line.startsWith("{"));
|
|
227
|
+
for (const line of lines.reverse()) {
|
|
228
|
+
try { return JSON.parse(line); } catch { /* keep looking */ }
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function refreshOne({ dirName, installedVersion, cliEntry, nodeBin, home, execFileImpl }) {
|
|
234
|
+
let config;
|
|
235
|
+
try {
|
|
236
|
+
config = JSON.parse(await readFile(join(stagingPoolsRoot(home), dirName, "config.json"), "utf8"));
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (error?.code === "ENOENT") return null; // not a pool home
|
|
239
|
+
return { poolId: dirName, status: "unreadable", code: "config_unreadable", message: `Its config.json could not be read (${error?.message ?? error}).`, next: "bb staging-pool status --check --pool " + dirName, actor: "agent or human" };
|
|
240
|
+
}
|
|
241
|
+
const poolId = typeof config?.poolId === "string" ? config.poolId : dirName;
|
|
242
|
+
const tenant = config?.tenant ?? config?.binding?.tenant ?? null;
|
|
243
|
+
if (config?.source !== "control-plane" || !tenant) {
|
|
244
|
+
return { poolId, status: "legacy", code: "installed_before_registry", message: "It was installed before the control-plane registry, so only a human re-install can update it.", next: tenant ? installLine(tenant, poolId) : `bb staging-pool status --pool ${poolId}`, actor: HUMAN_NEXT };
|
|
245
|
+
}
|
|
246
|
+
const runtimeVersion = config?.runtime?.version ?? null;
|
|
247
|
+
if (runtimeVersion === installedVersion) return { poolId, status: "current", runtimeVersion };
|
|
248
|
+
const retry = `bb staging-pool refresh-runtime --tenant ${tenant} --pool ${poolId}`;
|
|
249
|
+
try {
|
|
250
|
+
const { stdout } = await execFileImpl(nodeBin, [cliEntry, "staging-pool", "refresh-runtime", "--tenant", tenant, "--pool", poolId], { timeout: REFRESH_TIMEOUT_MS, maxBuffer: 1024 * 1024 });
|
|
251
|
+
const receipt = lastJsonLine(stdout);
|
|
252
|
+
if (receipt?.ok === true) return { poolId, status: "refreshed", runtimeVersion: receipt.runtimeVersion ?? installedVersion };
|
|
253
|
+
return { poolId, status: "refused", code: receipt?.code ?? "refresh_failed", message: receipt?.message ?? "The refresh printed no success receipt.", next: retry, actor: "agent or human" };
|
|
254
|
+
} catch (error) {
|
|
255
|
+
// A refusal is one JSON line on stderr (then text guidance); stdout stays empty.
|
|
256
|
+
const receipt = lastJsonLine(error?.stderr) ?? lastJsonLine(error?.stdout);
|
|
257
|
+
if (receipt?.code) {
|
|
258
|
+
const human = /^human/i.test(String(receipt.actor ?? "")) || /install/.test(String(receipt.next ?? ""));
|
|
259
|
+
const actor = typeof receipt.actor === "string" && receipt.actor ? (human ? `${receipt.actor}, from Terminal.app or iTerm` : receipt.actor) : (human ? HUMAN_NEXT : "agent or human");
|
|
260
|
+
return { poolId, status: "refused", code: receipt.code, message: [receipt.message, receipt.detail].filter(Boolean).join(" "), next: receipt.next ?? retry, actor };
|
|
261
|
+
}
|
|
262
|
+
return { poolId, status: "refused", code: "refresh_failed", message: `The refresh did not finish (${error?.message ?? error}).`, next: retry, actor: "agent or human" };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Refresh every control-plane staging pool installed under ~/.botbuddy whose
|
|
268
|
+
* recorded runtime differs from `installedVersion`, by running the new
|
|
269
|
+
* package's `staging-pool refresh-runtime`. Reports one line per pool and
|
|
270
|
+
* never throws for a pool's refusal. Returns [{ poolId, status, ... }].
|
|
271
|
+
*/
|
|
272
|
+
export async function refreshInstalledPools({
|
|
273
|
+
installedVersion,
|
|
274
|
+
cliEntry,
|
|
275
|
+
nodeBin = process.execPath,
|
|
276
|
+
home = homedir(),
|
|
277
|
+
execFileImpl = promisify(execFile),
|
|
278
|
+
log = (line) => console.log(line),
|
|
279
|
+
stderr = process.stderr,
|
|
280
|
+
} = {}) {
|
|
281
|
+
let entries;
|
|
282
|
+
try {
|
|
283
|
+
entries = await readdir(stagingPoolsRoot(home), { withFileTypes: true });
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (error?.code === "ENOENT") return [];
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
const results = [];
|
|
289
|
+
for (const entry of entries.filter((e) => e.isDirectory()).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
290
|
+
const result = await refreshOne({ dirName: entry.name, installedVersion, cliEntry, nodeBin, home, execFileImpl });
|
|
291
|
+
if (!result) continue;
|
|
292
|
+
results.push(result);
|
|
293
|
+
if (result.status === "refreshed") log(`✓ Staging pool ${result.poolId} now runs v${result.runtimeVersion}`);
|
|
294
|
+
else if (result.status === "current") log(`✓ Staging pool ${result.poolId} already runs v${result.runtimeVersion}`);
|
|
295
|
+
else {
|
|
296
|
+
try { stderr.write(`! Staging pool ${result.poolId} was not refreshed (${result.code}): ${result.message}\n Next (${result.actor}): ${result.next}\n`); } catch { /* ignore */ }
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return results;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// The default for `cmdUpdate`: locate the newly installed package and refresh with it.
|
|
303
|
+
export async function refreshPoolsFromNewPackage({ installedVersion, npmBin, shellOpt, probeImpl, log, stderr }) {
|
|
304
|
+
const root = readNpmGlobalRoot({ npmBin, shellOpt, probeImpl });
|
|
305
|
+
return refreshInstalledPools({ installedVersion, cliEntry: join(root, "@botbuddy", "cli", "bin", "botbuddy.mjs"), log, stderr });
|
|
306
|
+
}
|