beecork 2.5.0 → 2.5.1

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 (2) hide show
  1. package/dist/index.js +65 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -135,9 +135,10 @@ var config = {
135
135
  };
136
136
 
137
137
  // src/update.ts
138
- import { readFile, writeFile, mkdir } from "node:fs/promises";
138
+ import { readFile, writeFile, mkdir, realpath } from "node:fs/promises";
139
139
  import { homedir as homedir2 } from "node:os";
140
- import { join, dirname } from "node:path";
140
+ import { join, dirname, basename, delimiter } from "node:path";
141
+ import { fileURLToPath } from "node:url";
141
142
  import { spawn } from "node:child_process";
142
143
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
143
144
  var cacheFile = () => join(homedir2(), ".beecork", "update-check.json");
@@ -149,6 +150,48 @@ async function currentVersion() {
149
150
  return "0.0.0";
150
151
  }
151
152
  }
153
+ function runningPkgRoot() {
154
+ return fileURLToPath(new URL("..", import.meta.url));
155
+ }
156
+ function prefixFromPkgRoot(pkgRoot) {
157
+ const nm = dirname(pkgRoot);
158
+ if (basename(nm) !== "node_modules") return null;
159
+ const up = dirname(nm);
160
+ return basename(up) === "lib" ? dirname(up) : up;
161
+ }
162
+ function installPrefix() {
163
+ return prefixFromPkgRoot(runningPkgRoot());
164
+ }
165
+ async function findShadowingInstalls() {
166
+ let running;
167
+ try {
168
+ running = await realpath(runningPkgRoot());
169
+ } catch {
170
+ running = runningPkgRoot();
171
+ }
172
+ const names = process.platform === "win32" ? ["beecork.cmd", "beecork"] : ["beecork"];
173
+ const seenRoots = /* @__PURE__ */ new Set([running]);
174
+ const others = [];
175
+ for (const dir of (process.env.PATH ?? "").split(delimiter).filter(Boolean)) {
176
+ for (const name of names) {
177
+ try {
178
+ const bin = join(dir, name);
179
+ const root = dirname(dirname(await realpath(bin)));
180
+ if (seenRoots.has(root)) continue;
181
+ seenRoots.add(root);
182
+ const pkg = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
183
+ if (String(pkg.name) === "beecork") others.push({ bin, version: String(pkg.version ?? "?").replace(/[^\w.+-]/g, "") });
184
+ } catch {
185
+ }
186
+ }
187
+ }
188
+ return others;
189
+ }
190
+ async function shadowWarning() {
191
+ const others = await findShadowingInstalls();
192
+ if (!others.length) return null;
193
+ return "\u26A0 Another beecork is on your PATH and may shadow the version you just installed:\n" + others.map((o) => ` ${o.bin} (v${o.version})`).join("\n") + "\n Remove the stale one(s) so `beecork` always runs the newest install (may need sudo):\n" + others.map((o) => ` rm ${o.bin}`).join("\n");
194
+ }
152
195
  function isNewer(a, b) {
153
196
  const pa = a.split(".").map((n) => parseInt(n, 10) || 0);
154
197
  const pb = b.split(".").map((n) => parseInt(n, 10) || 0);
@@ -195,7 +238,9 @@ async function checkForUpdate(current) {
195
238
  function selfUpdate(timeoutMs = 12e4) {
196
239
  return new Promise((resolve2) => {
197
240
  const npm = process.platform === "win32" ? "npm.cmd" : "npm";
198
- const child = spawn(npm, ["install", "-g", "beecork@latest"], { stdio: ["ignore", "pipe", "pipe"] });
241
+ const prefix = installPrefix();
242
+ const args = ["install", "-g", "beecork@latest", ...prefix ? ["--prefix", prefix] : []];
243
+ const child = spawn(npm, args, { stdio: ["ignore", "pipe", "pipe"] });
199
244
  let out3 = "", done = false;
200
245
  const finish = (r) => {
201
246
  if (done) return;
@@ -494,8 +539,9 @@ function markLines(width) {
494
539
  }
495
540
  return lines.filter((l) => l.length > 0);
496
541
  }
497
- function printBanner(model, sources) {
542
+ function printBanner(model, version, sources) {
498
543
  const safeModel = stripControl(model);
544
+ const safeVersion = stripControl(version);
499
545
  const word = [
500
546
  " _ _ ",
501
547
  " | |__ ___ ___ ___ ___ _ __| | __",
@@ -527,7 +573,7 @@ function printBanner(model, sources) {
527
573
  const mem = sources.filter((s) => s.endsWith("memory.md"));
528
574
  const cwd = tildify(process.cwd());
529
575
  const rows2 = [
530
- ["", "\u{1F41D} a tiny CLI coding agent"],
576
+ ["", `\u{1F41D} a tiny CLI coding agent \xB7 v${safeVersion}`],
531
577
  ["dir", cwd],
532
578
  ["model", safeModel],
533
579
  ["cork.md", cork.length ? cork.join(", ") : "none"],
@@ -1307,7 +1353,7 @@ async function runExplorer(task, focus, signal) {
1307
1353
 
1308
1354
  // src/safety.ts
1309
1355
  import { homedir as homedir3 } from "node:os";
1310
- import { basename } from "node:path";
1356
+ import { basename as basename2 } from "node:path";
1311
1357
  function pathGuard(args) {
1312
1358
  const { abs, inRoot } = resolveInRoot(String(args.path ?? "."));
1313
1359
  return inRoot ? {} : { needsApproval: true, reason: `path is outside the project root: ${abs}`, cacheKey: `path:${abs}` };
@@ -1315,7 +1361,7 @@ function pathGuard(args) {
1315
1361
  var SECRET_FILE = /(^|\/)(\.env(\.[\w.-]+)?|[\w.-]*\.(env|pem|key|secret|pfx|p12|jks|keystore)|id_(rsa|ed25519|ecdsa|dsa)|credentials|\.git-credentials|\.pgpass|\.npmrc|\.netrc)$/i;
1316
1362
  function isSecretPath(userPath) {
1317
1363
  const { abs } = resolveInRoot(userPath);
1318
- return SECRET_FILE.test(abs) || SECRET_FILE.test(basename(abs));
1364
+ return SECRET_FILE.test(abs) || SECRET_FILE.test(basename2(abs));
1319
1365
  }
1320
1366
  function secretGuard(args) {
1321
1367
  const p = pathGuard(args);
@@ -3664,8 +3710,11 @@ async function handleCommand(input, messages) {
3664
3710
  } else if (cmd === "/update") {
3665
3711
  console.log(color.dim("updating beecork\u2026 (npm install -g beecork@latest)"));
3666
3712
  const { ok, output } = await selfUpdate();
3667
- if (ok) console.log(color.green("\u2713 updated \u2014 restart beecork to use the new version.") + "\n");
3668
- else {
3713
+ if (ok) {
3714
+ console.log(color.green("\u2713 updated \u2014 restart beecork to use the new version.") + "\n");
3715
+ const w = await shadowWarning();
3716
+ if (w) console.log(color.yellow(w) + "\n");
3717
+ } else {
3669
3718
  console.log(color.red("update failed: ") + output.split("\n").filter(Boolean).slice(-1)[0]);
3670
3719
  console.log(color.dim(" run manually: npm install -g beecork (may need sudo / your version manager)") + "\n");
3671
3720
  }
@@ -3835,8 +3884,11 @@ async function main() {
3835
3884
  if (process.argv[2] === "update") {
3836
3885
  console.log("Updating beecork\u2026");
3837
3886
  const { ok, output } = await selfUpdate();
3838
- if (ok) console.log(color.green("\u2713 beecork updated. Run `beecork` to use the new version."));
3839
- else {
3887
+ if (ok) {
3888
+ console.log(color.green("\u2713 beecork updated. Run `beecork` to use the new version."));
3889
+ const w = await shadowWarning();
3890
+ if (w) console.log("\n" + color.yellow(w));
3891
+ } else {
3840
3892
  console.error(color.red("Update failed:") + "\n" + output);
3841
3893
  console.error(color.dim("\nTry manually: npm install -g beecork (you may need sudo, or your Node version manager)."));
3842
3894
  process.exitCode = 1;
@@ -3917,12 +3969,12 @@ ${instr.trusted}`;
3917
3969
  }
3918
3970
  const rl = tty ? null : createInterface({ input: process.stdin, output: process.stdout, completer });
3919
3971
  if (chromeEnabled()) process.stdout.write(ansi.clearScreen + ansi.clearScrollback + ansi.home);
3920
- printBanner(state.model, instr.sources.map(tildify));
3972
+ const version = await currentVersion();
3973
+ printBanner(state.model, version, instr.sources.map(tildify));
3921
3974
  if (config.dangerouslySkipPermissions) {
3922
3975
  console.log(color.red("\u26A0 --dangerously-skip-permissions is ON: the approval gate is OFF. Out-of-root paths and risky") + "\n" + color.red(" shell commands will RUN unprompted. Use only in a disposable sandbox. (read-only mode + catastrophic-") + "\n" + color.red(" command refusal still apply.)") + "\n");
3923
3976
  }
3924
3977
  if (tty) {
3925
- const version = await currentVersion();
3926
3978
  const newer = await checkForUpdate(version);
3927
3979
  if (newer) console.log(color.dim(`\u25B8 beecork ${stripControl(newer)} is available (you have ${version}) \u2014 update: npm install -g beecork`) + "\n");
3928
3980
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "beecork",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "beecork — a from-scratch CLI coding agent: multi-model (OpenRouter), BYOK, path-confined tools, built part by part.",
5
5
  "type": "module",
6
6
  "bin": {