@my-life-buddies/cli 0.21.1 → 0.23.0-dev.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.
package/dist/bin/buddy.js CHANGED
@@ -5,10 +5,11 @@ import { execFile as execFile3 } from "node:child_process";
5
5
  import { promisify as promisify3 } from "node:util";
6
6
  import { stdin, stderr, stdout } from "node:process";
7
7
  import { createRequire } from "node:module";
8
- import { dirname as dirname2 } from "node:path";
8
+ import { dirname as dirname3 } from "node:path";
9
9
  import { createInterface } from "node:readline/promises";
10
10
  import {
11
11
  PromptCancelledError,
12
+ resolvePlatformUrl as resolvePlatformUrl2,
12
13
  runBuddyCli
13
14
  } from "./core.js";
14
15
 
@@ -94,8 +95,8 @@ import {
94
95
  connectPreviewBridge
95
96
  } from "./preview.js";
96
97
  var PREVIEW_COMMAND_HELP = `\u7528\u6CD5:
97
- buddy-cli preview [--directory <\u9879\u76EE\u76EE\u5F55>] [--buddy-id <\u642D\u5B50 ID>] [--developer-web <\u540E\u53F0 URL>] [--app-server <App Server URL>] [--no-open]
98
- buddy-cli preview --local [--directory <\u9879\u76EE\u76EE\u5F55>] [--port <\u672C\u5730\u7AEF\u53E3>]
98
+ buddy-cli-sit preview [--directory <\u9879\u76EE\u76EE\u5F55>] [--buddy-id <\u642D\u5B50 ID>] [--developer-web <\u540E\u53F0 URL>] [--app-server <App Server URL>] [--no-open]
99
+ buddy-cli-sit preview --local [--directory <\u9879\u76EE\u76EE\u5F55>] [--port <\u672C\u5730\u7AEF\u53E3>]
99
100
 
100
101
  \u8BF4\u660E:
101
102
  \u9ED8\u8BA4\u6253\u5F00\u5F53\u524D\u642D\u5B50\u7684\u521B\u9020\u8005\u540E\u53F0\u300C\u5F00\u53D1\u8C03\u8BD5\u300D\uFF0C\u8FDE\u63A5\u672C\u5730\u5DE5\u7A0B\uFF1B\u5728\u540E\u53F0\u542F\u52A8/\u505C\u6B62 DEV\u3001\u8BD5\u804A\u3001\u67E5\u770B Widget\u3001\u65F6\u95F4\u7EBF\u4E0E\u534F\u8BAE\u65E5\u5FD7\u3001\u771F\u673A\u9884\u89C8\u3002
@@ -104,13 +105,14 @@ var PREVIEW_COMMAND_HELP = `\u7528\u6CD5:
104
105
  --no-open \u4EC5\u7528\u4E8E\u540E\u53F0\u9884\u89C8\uFF1B\u76F4\u63A5\u6267\u884C preview \u4ECD\u81EA\u52A8\u6253\u5F00\u540E\u53F0\u3002
105
106
  --local \u662F\u540E\u53F0\u4E0D\u53EF\u7528\u65F6\u7684\u72EC\u7ACB\u672C\u5730\u9884\u89C8\u5907\u7528\u5165\u53E3\uFF0C--port \u4EC5\u4E0E --local \u4E00\u8D77\u4F7F\u7528\u3002
106
107
  \u4FDD\u6301\u7EC8\u7AEF\u8FD0\u884C\uFF1BCtrl+C \u6216\u5173\u95ED\u7EC8\u7AEF\u4F1A\u505C\u6B62 DEV \u5E76\u65AD\u5F00\u8FDE\u63A5\uFF0C\u5237\u65B0\u540E\u53F0\u4E0D\u4F1A\u81EA\u52A8\u542F\u52A8 DEV\u3002
107
- \u540E\u53F0\u53EF\u5F3A\u5236\u65AD\u8FDE\uFF1B\u672C\u673A\u505C\u6B62\u672A\u786E\u8BA4\u65F6\uFF0C\u5728\u539F\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C buddy-cli dev stop\u3002\u8BE5\u547D\u4EE4\u4E0D\u91CD\u8FDE\u3001\u4E0D\u91CD\u542F\u3002
108
+ DEV \u5931\u8D25\u5148\u67E5\u770B\u5177\u4F53\u9519\u8BEF\u548C\u8FD0\u884C\u65E5\u5FD7\uFF1B\u5347\u7EA7 CLI \u540E\u9000\u51FA\u65E7 preview \u8FDB\u7A0B\u5E76\u91CD\u65B0\u8FDE\u63A5\uFF0C\u518D\u542F\u52A8 DEV\u3002
109
+ \u540E\u53F0\u53EF\u5F3A\u5236\u65AD\u8FDE\uFF1B\u672C\u673A\u505C\u6B62\u672A\u786E\u8BA4\u65F6\uFF0C\u5728\u539F\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C buddy-cli-sit dev stop\u3002\u8BE5\u547D\u4EE4\u4E0D\u91CD\u8FDE\u3001\u4E0D\u91CD\u542F\u3002
108
110
  \u672A\u914D\u7F6E\u5730\u5740\u65F6\u8FDE\u63A5 MLB \u6D4B\u8BD5\u73AF\u5883 ${DEFAULT_MLB_TEST_URL}\uFF08HTTPS\uFF09\u3002
109
- MLB_GATEWAY_URL \u7EDF\u4E00\u9009\u62E9\u5E73\u53F0\uFF0C--app-server \u53EF\u8986\u76D6\u672C\u6B21\u547D\u4EE4\uFF1B\u540E\u53F0\u9ED8\u8BA4\u4F7F\u7528\u540C\u4E00\u5730\u5740\u7684 /developer/\u3002
110
- CLI \u7EDF\u4E00\u542F\u52A8\u5E76\u7BA1\u7406\u5DE5\u7A0B\u4E2D\u7684\u5B98\u65B9 Runtime\uFF1B\u6BCF\u6B21\u542F\u52A8\u6216\u91CD\u8F7D\u5FC5\u987B\u901A\u8FC7 npm \u6700\u65B0\u7A33\u5B9A\u7248\u68C0\u67E5\u3002
111
+ SIT \u5305\u56FA\u5B9A\u8FDE\u63A5 SIT\uFF1B\u5730\u5740\u53C2\u6570\u53EA\u6821\u9A8C\u56FA\u5B9A\u76EE\u6807\uFF0C\u4E0D\u80FD\u5207\u6362\u5E73\u53F0\u3002Runtime \u7F51\u5173\u7531 CLI \u6CE8\u5165\u3002
112
+ CLI \u7EDF\u4E00\u542F\u52A8\u5E76\u7BA1\u7406\u5DE5\u7A0B\u4E2D\u7684\u5B98\u65B9 Runtime\uFF1B\u6BCF\u6B21\u542F\u52A8\u6216\u91CD\u8F7D\u68C0\u67E5\u5DE5\u7A0B\u9009\u5B9A Runtime \u7684\u51C6\u786E\u7248\u672C\u3001\u5B89\u88C5\u548C\u9501\u6587\u4EF6\u3002
111
113
  \u8EAB\u4EFD\u8BFB\u53D6 package.json.buddyId\uFF1B.env \u4FDD\u5B58 Token\uFF0C\u542F\u52A8\u524D\u5411 Server \u6821\u9A8C\u6240\u5C5E\u642D\u5B50\u3002
112
- \u8FDE\u63A5\u524D\u81EA\u68C0 .env \u7F51\u5173\uFF1B\u5DF2\u77E5\u65E7 ECS \u5730\u5740\u5728\u542F\u52A8 DEV \u65F6\u6821\u9A8C\u5F52\u5C5E\u5E76\u81EA\u52A8\u66F4\u65B0\uFF0C\u4E0D\u540C\u5E73\u53F0\u4ECD\u9700\u660E\u786E\u786E\u8BA4\u3002
113
- --refresh-token \u91CD\u65B0\u9886\u53D6\u5DF2\u6709\u5F00\u53D1 Token\uFF0C\u66F4\u65B0\u5DE5\u7A0B .env\uFF1B\u4E0D\u4F1A\u751F\u6210\u65B0\u5BC6\u94A5\u3002
114
+ \u8FDE\u63A5\u524D\u81EA\u68C0 .env \u7F51\u5173\uFF1B\u53D1\u73B0\u5176\u4ED6\u73AF\u5883\u5730\u5740\u65F6\u505C\u6B62\uFF1B\u8BF7\u4F7F\u7528\u5BF9\u5E94 CLI\uFF0C\u8FC1\u79FB\u65F6\u65B0\u5EFA\u8EAB\u4EFD\u4E14\u4E0D\u590D\u5236\u51ED\u636E\u3002
115
+ --refresh-token \u91CD\u65B0\u9886\u53D6\u5DF2\u6709\u5F00\u53D1 Token\uFF0C\u66F4\u65B0\u540C\u4E00\u73AF\u5883\u7684\u5DE5\u7A0B .env\uFF1B\u4E0D\u80FD\u5207\u6362\u5E73\u53F0\uFF0C\u4E0D\u4F1A\u751F\u6210\u65B0\u5BC6\u94A5\u3002
114
116
  Widget \u6D88\u606F\u5361\u7247\u4FDD\u7559\u6307\u5B9A\u8BB0\u5F55\u7684\u6253\u5F00\u76EE\u6807\uFF0C\u5C0F\u6302\u4EF6\u5217\u8868\u6253\u5F00\u9ED8\u8BA4\u89C6\u56FE\u3002
115
117
  \u6A21\u62DF\u5668\u4F7F\u7528\u5F53\u524D\u5F00\u53D1\u8005\u8D26\u53F7\u8BBF\u95EE <buddyId>-dev \u8C03\u8BD5\u5206\u8EAB\u3002`;
116
118
  function valueAfter(args, index, flag) {
@@ -253,7 +255,7 @@ var BuddyPlatformHost = class {
253
255
  baseUrl,
254
256
  token: async () => (await session.token({ signal: this.#signal })).accessToken
255
257
  }),
256
- runtimeUpdate: { ...this.#runtimeUpdate, env: this.#env, platformUrl: baseUrl },
258
+ runtimeUpdate: { ...this.#runtimeUpdate, env: this.#env },
257
259
  preparePush
258
260
  };
259
261
  }
@@ -282,13 +284,13 @@ var BuddyPlatformHost = class {
282
284
  return { exitCode: 0, route: "preview" };
283
285
  }
284
286
  const projectRoot = await requireBuddyAgentProjectRoot(resolve(process.cwd(), parsed.directory));
285
- const baseUrl = resolvePlatformUrl({ env: this.#env, override: parsed.appServer, development: true });
287
+ const baseUrl = resolvePlatformUrl({ env: this.#env, override: parsed.appServer });
286
288
  const manifest = await readBuddyProjectManifest(projectRoot);
287
289
  if (parsed.buddyId && parsed.buddyId !== manifest.buddyId) throw new Error(`\u5F53\u524D\u5DE5\u7A0B\u5C5E\u4E8E ${manifest.buddyId}\uFF0C\u8FDE\u63A5\u6307\u4EE4\u8981\u6C42 ${parsed.buddyId}\uFF1B\u8BF7\u5728\u6B63\u786E\u642D\u5B50\u7684\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C\u3002`);
288
290
  const webUrl = resolveDeveloperWebUrl(baseUrl, parsed.developerWeb ?? this.#env.BUDDY_DEVELOPER_WEB_URL);
289
291
  const signal = this.#signal ?? new AbortController().signal;
290
- await checkProjectGateway(projectRoot, baseUrl, { refreshToken: parsed.refreshToken, report: (message) => io.write(message) });
291
- await checkRuntimeUpdate(projectRoot, (message) => io.writeError(message), { ...this.#runtimeUpdate, signal, env: this.#env, platformUrl: baseUrl });
292
+ await checkProjectGateway(projectRoot, baseUrl, { report: (message) => io.write(message) });
293
+ await checkRuntimeUpdate(projectRoot, (message) => io.writeError(message), { ...this.#runtimeUpdate, signal, env: this.#env });
292
294
  const session = this.#session(baseUrl, webUrl);
293
295
  await session.token({ signal });
294
296
  const starter = this.#previewStarter(baseUrl, manifest.buddyId, session, parsed.refreshToken ?? false);
@@ -359,10 +361,10 @@ var BuddyPlatformHost = class {
359
361
  const handle = await starter.start({
360
362
  projectRoot,
361
363
  signal,
362
- runtimeUpdate: { ...this.#runtimeUpdate, env: this.#env, platformUrl: baseUrl },
364
+ runtimeUpdate: { ...this.#runtimeUpdate, env: this.#env },
363
365
  onError(error) {
364
366
  logs.flush();
365
- let message = error.message;
367
+ let message = error.publicMessage ?? error.message;
366
368
  for (const secret of secrets) if (secret) message = message.split(secret).join("[REDACTED]");
367
369
  reloadError = { code: error.code, message: message.replace(/[\u0000-\u001f\u007f]/gu, " ").slice(0, 512) };
368
370
  },
@@ -426,6 +428,7 @@ var BuddyPlatformHost = class {
426
428
  return resolvePlatformUrl({ env: this.#env });
427
429
  }
428
430
  #session(baseUrl, webUrl) {
431
+ resolvePlatformUrl({ env: this.#env, override: baseUrl.href });
429
432
  const developerWebUrl = resolveDeveloperWebUrl(baseUrl, webUrl ?? this.#env.BUDDY_DEVELOPER_WEB_URL);
430
433
  const key = baseUrl.origin;
431
434
  let session = this.#sessions.get(key);
@@ -450,7 +453,7 @@ var BuddyPlatformHost = class {
450
453
  // apps/cli/src/platform-support.ts
451
454
  var UnsupportedDeveloperPlatformError = class extends Error {
452
455
  constructor(platform) {
453
- super(`buddy-cli V1 \u76EE\u524D\u53EA\u652F\u6301 macOS\uFF0C\u5F53\u524D\u7CFB\u7EDF\u662F ${platform}`);
456
+ super(`buddy-cli-sit V1 \u76EE\u524D\u53EA\u652F\u6301 macOS\uFF0C\u5F53\u524D\u7CFB\u7EDF\u662F ${platform}`);
454
457
  this.platform = platform;
455
458
  this.name = "UnsupportedDeveloperPlatformError";
456
459
  }
@@ -462,9 +465,9 @@ function assertSupportedDeveloperPlatform(platform = process.platform) {
462
465
 
463
466
  // apps/cli/src/self-update.ts
464
467
  import { execFile } from "node:child_process";
465
- import { lstat, readFile, realpath } from "node:fs/promises";
468
+ import { readFile } from "node:fs/promises";
466
469
  import { homedir as homedir2 } from "node:os";
467
- import { isAbsolute, join as join2 } from "node:path";
470
+ import { join as join3 } from "node:path";
468
471
  import { promisify } from "node:util";
469
472
 
470
473
  // apps/cli/src/update-lock.ts
@@ -473,7 +476,7 @@ import { dirname, join } from "node:path";
473
476
  import { homedir } from "node:os";
474
477
  import { createHash as createHash2 } from "node:crypto";
475
478
  import { setTimeout as delay } from "node:timers/promises";
476
- var defaultUpdateCache = () => join(homedir(), ".cache", "buddy-cli", "updates");
479
+ var defaultUpdateCache = () => join(homedir(), ".cache", "buddy-cli-sit", "updates");
477
480
  var globalUpdateLock = (cache, prefix) => join(cache, "locks", createHash2("sha256").update(prefix).digest("hex"));
478
481
  async function withUpdateLock(path, signal, action) {
479
482
  await mkdir(dirname(path), { recursive: true, mode: 448 });
@@ -542,25 +545,43 @@ async function installCliWithNpm(args, settings, runNpm) {
542
545
  }
543
546
  }
544
547
 
548
+ // apps/cli/src/install-location.ts
549
+ import { lstat, realpath } from "node:fs/promises";
550
+ import { dirname as dirname2, join as join2, resolve as resolve2 } from "node:path";
551
+ async function globalInstallation(packageRoot, packageName) {
552
+ try {
553
+ if ((await lstat(packageRoot)).isSymbolicLink()) return void 0;
554
+ const root = await realpath(packageRoot);
555
+ let prefix = root;
556
+ for (const _part of ["lib", "node_modules", ...packageName.split("/")]) prefix = dirname2(prefix);
557
+ if (root !== resolve2(prefix, "lib", "node_modules", packageName)) return void 0;
558
+ if ((await lstat(join2(prefix, "lib", "node_modules", packageName))).isSymbolicLink()) return void 0;
559
+ return { root, prefix };
560
+ } catch {
561
+ return void 0;
562
+ }
563
+ }
564
+
545
565
  // apps/cli/src/self-update.ts
546
566
  var PACKAGE = "@my-life-buddies/cli";
547
567
  var REGISTRY = "https://registry.npmjs.org/";
548
- var MANUAL_UPDATE = `npm install --global ${PACKAGE}@latest --registry=${REGISTRY} --prefer-online`;
568
+ var MANUAL_UPDATE = `npm install --global --prefix "$HOME/.local/share/buddy-cli/sit" ${PACKAGE}@dev --registry=${REGISTRY} --prefer-online`;
549
569
  var execute = promisify(execFile);
550
570
  var HELP = `\u7528\u6CD5:
551
- buddy-cli --version [--json]
552
- buddy-cli update --check [--json]
553
- buddy-cli update [--json]
571
+ buddy-cli-sit --version [--json]
572
+ buddy-cli-sit update --check [--json]
573
+ buddy-cli-sit update [--json]
554
574
 
555
575
  --version \u67E5\u770B\u5F53\u524D\u8FD0\u884C\u7684 CLI \u7248\u672C\uFF08\u65E0\u9700\u8054\u7F51\uFF09
556
- --check \u68C0\u67E5\u516C\u5171 npm \u7684 latest \u7248\u672C\uFF0C\u4E0D\u5B89\u88C5
576
+ --check \u68C0\u67E5\u516C\u5171 npm \u7684 dev \u7248\u672C\uFF0C\u4E0D\u5B89\u88C5
557
577
  --json \u8F93\u51FA JSON\uFF0C\u4F9B Coding Agent \u6216\u811A\u672C\u8BFB\u53D6
558
578
 
559
579
  \u65E0\u9700\u767B\u5F55\u642D\u642D\u8D26\u53F7\uFF0C\u4E5F\u65E0\u9700\u8FDB\u5165\u642D\u5B50\u5DE5\u7A0B\u3002
560
580
  \u6B63\u5E38\u547D\u4EE4\uFF08\u542B guide\uFF09\u4F1A\u5148\u8054\u7F51\u81EA\u68C0\uFF0C\u81EA\u52A8\u66F4\u65B0\u540E\u7531\u65B0\u7248\u7EE7\u7EED\u6267\u884C\uFF1B\u7B49\u5F85\u5B8C\u6210\u5373\u53EF\u3002
561
581
  \u5B89\u88C5\u4E3B\u52A8\u5237\u65B0 npm \u7248\u672C\u7F13\u5B58\uFF0C\u627E\u4E0D\u5230\u7248\u672C\uFF08ETARGET\uFF09\u65F6\u6700\u591A\u91CD\u8BD5\u4E00\u6B21\uFF1B\u5931\u8D25\u8BF4\u660E\u5177\u4F53\u539F\u56E0\u3002
562
582
  --help\u3001\u5404\u547D\u4EE4 --help \u4E0E --version \u79BB\u7EBF\u53EF\u7528\uFF1B\u67E5\u8BE2\u6216\u66F4\u65B0\u5931\u8D25\u65F6\u505C\u6B62\u4E1A\u52A1\u64CD\u4F5C\u3002
563
- update \u7528\u4E8E\u5355\u72EC\u66F4\u65B0\u5F53\u524D npm \u5168\u5C40\u5B89\u88C5\u7684 CLI\uFF0C\u4E0D\u4FEE\u6539\u642D\u5B50\u5DE5\u7A0B\u7684 Runtime \u4F9D\u8D56\u3002
583
+ update \u66F4\u65B0\u5F53\u524D CLI \u6240\u5728\u7684 npm \u5B89\u88C5\u76EE\u5F55\uFF08\u542B --global --prefix \u81EA\u5B9A\u4E49\u76EE\u5F55\uFF09\uFF0C\u4E0D\u4FEE\u6539\u5176\u4ED6\u5B89\u88C5\u6216\u5DE5\u7A0B Runtime \u4F9D\u8D56\u3002
584
+ \u540C\u4E00\u5305 latest/dev \u9700\u5206\u76EE\u5F55\u5B89\u88C5\u624D\u80FD\u5171\u5B58\uFF1BSIT \u547D\u4EE4\u4E3A buddy-cli-sit\uFF0C\u6B63\u5F0F\u547D\u4EE4\u4E3A buddy-cli\u3002
564
585
  \u5DF2\u7ECF\u662F\u6700\u65B0\u7248\u6216\u5F53\u524D\u7248\u672C\u66F4\u9AD8\u65F6\u4E0D\u5B89\u88C5\u3001\u4E0D\u964D\u7EA7\u3002
565
586
  \u6E90\u7801\u3001npm link\u3001\u5C40\u90E8\u5B89\u88C5\u6216 npx \u7684\u6B63\u5E38\u547D\u4EE4\u4F7F\u7528\u7F13\u5B58\u7684\u65B0\u7248\u6267\u884C\uFF0C\u4E0D\u8986\u76D6\u6E90\u7801\u6216\u5DE5\u7A0B\u4F9D\u8D56\u3002
566
587
  \u4E0A\u8FF0\u5B89\u88C5\u65B9\u5F0F\u4E0D\u80FD\u7528 update \u5355\u72EC\u4FEE\u6539\u539F\u5B89\u88C5\uFF0C\u8BF7\u6CBF\u7528\u539F\u6765\u7684\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0\u3002
@@ -598,7 +619,7 @@ async function latestVersion(options) {
598
619
  const timeout = AbortSignal.timeout(1e4);
599
620
  const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
600
621
  try {
601
- const response = await (options.fetch ?? globalThis.fetch)(`${REGISTRY}${encodeURIComponent(PACKAGE)}/latest`, {
622
+ const response = await (options.fetch ?? globalThis.fetch)(`${REGISTRY}${encodeURIComponent(PACKAGE)}/dev`, {
602
623
  signal,
603
624
  headers: { Accept: "application/json" },
604
625
  redirect: "error"
@@ -607,6 +628,7 @@ async function latestVersion(options) {
607
628
  const metadata = await response.json();
608
629
  if (metadata?.name !== PACKAGE) throw new Error("npm \u8FD4\u56DE\u7684\u5305\u540D\u4E0D\u5339\u914D");
609
630
  parseVersion(metadata.version);
631
+ if (typeof metadata.version !== "string" || !/^\d+\.\d+\.\d+-dev\.\d+$/.test(metadata.version)) throw new Error("npm dev \u672A\u6307\u5411 x.y.z-dev.N \u7248\u672C\uFF1BSIT CLI \u4E0D\u4F1A\u8DE8\u6E20\u9053\u66F4\u65B0\uFF0C\u8BF7\u8054\u7CFB\u53D1\u5E03\u8005\u4FEE\u6B63 dev \u6807\u7B7E");
610
632
  return metadata.version;
611
633
  } catch (cause) {
612
634
  if (options.signal?.aborted) throw new Error("\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002");
@@ -615,22 +637,20 @@ async function latestVersion(options) {
615
637
  }
616
638
  }
617
639
  async function installUpdate(version, options) {
640
+ if (!/^\d+\.\d+\.\d+-dev\.\d+$/.test(version)) throw new Error("SIT CLI \u53EA\u80FD\u66F4\u65B0 x.y.z-dev.N \u7248\u672C\uFF0C\u4E0D\u4F1A\u8DE8\u6E20\u9053\u5B89\u88C5\u3002");
618
641
  const runNpm = options.runNpm ?? ((args, settings2) => execute("npm", args, { ...settings2, encoding: "utf8", maxBuffer: 4 * 1024 * 1024 }));
619
642
  const settings = { cwd: homedir2(), signal: options.signal, timeout: 1e4 };
620
- const { stdout: stdout2 } = await runNpm(["prefix", "--global"], settings);
621
- const prefix = stdout2.trim();
622
- if (!isAbsolute(prefix) || /[\r\n]/u.test(prefix)) throw new Error("\u65E0\u6CD5\u786E\u5B9A npm \u5168\u5C40\u5B89\u88C5\u76EE\u5F55\u3002");
623
- const installedRoot = join2(prefix, "lib", "node_modules", PACKAGE);
624
- let sameInstallation = false;
625
- try {
626
- sameInstallation = !(await lstat(installedRoot)).isSymbolicLink() && await realpath(installedRoot) === await realpath(options.packageRoot);
627
- } catch {
628
- }
629
- if (!sameInstallation) {
630
- throw new Error("\u5F53\u524D CLI \u4E0D\u662F\u8FD9\u4E2A npm \u73AF\u5883\u7684\u5168\u5C40\u5B89\u88C5\uFF0C\u4E0D\u80FD\u76F4\u63A5\u66F4\u65B0\u3002\u8BF7\u7528\u539F\u6765\u7684\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0\uFF1B\u82E5\u4F7F\u7528 nvm\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5B89\u88C5\u8BE5 CLI \u7684 Node.js \u73AF\u5883\u3002");
643
+ const installation = await globalInstallation(options.packageRoot, PACKAGE);
644
+ if (!installation) {
645
+ throw new Error("\u5F53\u524D CLI \u662F\u6E90\u7801\u3001\u94FE\u63A5\u6216\u9879\u76EE\u5185\u5B89\u88C5\uFF0C\u4E0D\u80FD\u76F4\u63A5\u6539\u5199\u539F\u5B89\u88C5\u3002\u6B63\u5E38\u547D\u4EE4\u4F1A\u4ECE SIT \u72EC\u7ACB\u7F13\u5B58\u8FD0\u884C\u65B0\u7248\uFF1B\u5355\u72EC\u66F4\u65B0\u8BF7\u6CBF\u7528\u539F\u6765\u7684\u5B89\u88C5\u65B9\u5F0F\u3002");
631
646
  }
647
+ const { root: installedRoot, prefix } = installation;
648
+ const manualUpdate = `npm install --global --prefix '${prefix.replace(/'/gu, "'\\''")}' ${PACKAGE}@dev --registry=${REGISTRY} --prefer-online`;
632
649
  await withUpdateLock(globalUpdateLock(options.cacheDirectory ?? defaultUpdateCache(), prefix), options.signal, async () => {
633
- const current = JSON.parse(await readFile(join2(installedRoot, "package.json"), "utf8"));
650
+ const current = JSON.parse(await readFile(join3(installedRoot, "package.json"), "utf8"));
651
+ if (current.name !== PACKAGE || !/^\d+\.\d+\.\d+-dev\.\d+$/.test(current.version)) {
652
+ throw new Error("\u5F53\u524D\u5B89\u88C5\u76EE\u5F55\u5DF2\u88AB\u5176\u4ED6\u6E20\u9053\u66FF\u6362\uFF0C\u5DF2\u505C\u6B62\u66F4\u65B0\u3002\u8BF7\u5C06 latest \u548C dev \u5B89\u88C5\u5230\u4E0D\u540C\u76EE\u5F55\uFF0C\u518D\u91CD\u65B0\u8FD0\u884C buddy-cli-sit\u3002");
653
+ }
634
654
  if (current.name === PACKAGE && current.version === version) return;
635
655
  if (current.name === PACKAGE && compareVersions(current.version, version) > 0) throw new Error("\u53E6\u4E00\u4E2A\u8FDB\u7A0B\u5DF2\u5B89\u88C5\u66F4\u65B0\u7684 CLI\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C\u547D\u4EE4\u3002");
636
656
  try {
@@ -647,13 +667,13 @@ async function installUpdate(version, options) {
647
667
  "--no-fund"
648
668
  ], { ...settings, timeout: 18e4 }, runNpm);
649
669
  } catch (cause) {
650
- if (options.signal?.aborted) throw new Error("\u66F4\u65B0\u5DF2\u53D6\u6D88\uFF0C\u8BF7\u8FD0\u884C buddy-cli --version \u68C0\u67E5\u5B89\u88C5\u72B6\u6001\u3002");
670
+ if (options.signal?.aborted) throw new Error("\u66F4\u65B0\u5DF2\u53D6\u6D88\uFF0C\u8BF7\u8FD0\u884C buddy-cli-sit --version \u68C0\u67E5\u5B89\u88C5\u72B6\u6001\u3002");
651
671
  throw new Error(`${cause instanceof Error ? cause.message : "npm \u5B89\u88C5\u672A\u5B8C\u6210\u3002"}
652
- \u4E5F\u53EF\u624B\u52A8\u5B89\u88C5\uFF1A${MANUAL_UPDATE}`);
672
+ \u4E5F\u53EF\u624B\u52A8\u5B89\u88C5\uFF1A${manualUpdate}`);
653
673
  }
654
- const installed = JSON.parse(await readFile(join2(installedRoot, "package.json"), "utf8"));
674
+ const installed = JSON.parse(await readFile(join3(installedRoot, "package.json"), "utf8"));
655
675
  if (installed.name !== PACKAGE || installed.version !== version) {
656
- throw new Error(`npm \u5DF2\u7ED3\u675F\uFF0C\u4F46\u672A\u786E\u8BA4\u5B89\u88C5\u5230 ${version}\u3002\u8BF7\u8FD0\u884C buddy-cli --version \u68C0\u67E5\uFF0C\u5FC5\u8981\u65F6\u91CD\u8BD5\uFF1A${MANUAL_UPDATE}`);
676
+ throw new Error(`npm \u5DF2\u7ED3\u675F\uFF0C\u4F46\u672A\u786E\u8BA4\u5B89\u88C5\u5230 ${version}\u3002\u8BF7\u8FD0\u884C buddy-cli-sit --version \u68C0\u67E5\uFF0C\u5FC5\u8981\u65F6\u91CD\u8BD5\uFF1A${manualUpdate}`);
657
677
  }
658
678
  });
659
679
  }
@@ -663,13 +683,13 @@ async function runSelfUpdateCommand(args, io, options) {
663
683
  const json = args.includes("--json");
664
684
  const fail = (message, exitCode) => {
665
685
  if (json) io.write(JSON.stringify({ package: PACKAGE, currentVersion: options.version, error: message }));
666
- else io.writeError(`buddy-cli: ${message}`);
686
+ else io.writeError(`buddy-cli-sit: ${message}`);
667
687
  return { exitCode };
668
688
  };
669
689
  const flags = args.slice(1);
670
690
  const allowed = versionOnly ? ["--json", "--help", "-h"] : ["--check", "--json", "--help", "-h"];
671
691
  if (flags.some((flag) => !allowed.includes(flag)) || new Set(flags).size !== flags.length) {
672
- return fail("\u53C2\u6570\u65E0\u6548\uFF0C\u8BF7\u8FD0\u884C buddy-cli update --help \u67E5\u770B\u7528\u6CD5\u3002", 2);
692
+ return fail("\u53C2\u6570\u65E0\u6548\uFF0C\u8BF7\u8FD0\u884C buddy-cli-sit update --help \u67E5\u770B\u7528\u6CD5\u3002", 2);
673
693
  }
674
694
  if (flags.includes("--help") || flags.includes("-h")) {
675
695
  if (json) io.write(JSON.stringify({ help: HELP }));
@@ -682,6 +702,8 @@ async function runSelfUpdateCommand(args, io, options) {
682
702
  io.write(json ? JSON.stringify({ package: PACKAGE, version: options.version }) : options.version);
683
703
  return { exitCode: 0 };
684
704
  }
705
+ const pin = process.env.BUDDY_CLI_PIN_VERSION;
706
+ if (pin !== void 0) throw new Error("\u5F53\u524D\u5DF2\u7528 BUDDY_CLI_PIN_VERSION \u9501\u5B9A CLI\uFF1B\u5982\u9700\u66F4\u65B0\uFF0C\u8BF7\u5148 unset BUDDY_CLI_PIN_VERSION\u3002");
685
707
  const latest = await latestVersion(options);
686
708
  const comparison = compareVersions(latest, options.version);
687
709
  const check = flags.includes("--check");
@@ -701,8 +723,8 @@ async function runSelfUpdateCommand(args, io, options) {
701
723
  ...updated ? { installedVersion: latest } : {}
702
724
  }));
703
725
  } else if (updated) io.write(`CLI \u5DF2\u66F4\u65B0\uFF1A${options.version} \u2192 ${latest}\u3002`);
704
- else if (comparison > 0) io.write(`\u53D1\u73B0\u65B0\u7248\u672C\uFF1A${options.version} \u2192 ${latest}\u3002\u8FD0\u884C buddy-cli update \u66F4\u65B0\u3002`);
705
- else if (comparison < 0) io.write(`\u5F53\u524D\u7248\u672C ${options.version} \u9AD8\u4E8E npm latest ${latest}\uFF0C\u65E0\u9700\u66F4\u65B0\u3002`);
726
+ else if (comparison > 0) io.write(`\u53D1\u73B0\u65B0\u7248\u672C\uFF1A${options.version} \u2192 ${latest}\u3002\u8FD0\u884C buddy-cli-sit update \u66F4\u65B0\u3002`);
727
+ else if (comparison < 0) io.write(`\u5F53\u524D\u7248\u672C ${options.version} \u9AD8\u4E8E npm dev ${latest}\uFF0C\u65E0\u9700\u66F4\u65B0\u3002`);
706
728
  else io.write(`\u5F53\u524D\u5DF2\u662F\u6700\u65B0\u7248\uFF1A${options.version}\u3002`);
707
729
  return { exitCode: 0 };
708
730
  } catch (cause) {
@@ -728,16 +750,16 @@ function bindTerminationSignals(controller) {
728
750
  // apps/cli/src/auto-update.ts
729
751
  import { execFile as execFile2, spawn } from "node:child_process";
730
752
  import { lstat as lstat2, mkdir as mkdir2, mkdtemp, readFile as readFile2, realpath as realpath2, rename, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
731
- import { constants, homedir as homedir3 } from "node:os";
732
- import { isAbsolute as isAbsolute2, join as join3 } from "node:path";
753
+ import { constants } from "node:os";
754
+ import { join as join4 } from "node:path";
733
755
  import { promisify as promisify2 } from "node:util";
734
756
  var PACKAGE2 = "@my-life-buddies/cli";
735
757
  var REGISTRY2 = "https://registry.npmjs.org/";
736
758
  var execute2 = promisify2(execFile2);
737
- var HANDOFF_ENV = "BUDDY_CLI_UPDATE_HANDOFF";
759
+ var HANDOFF_ENV = "BUDDY_CLI_SIT_UPDATE_HANDOFF";
738
760
  async function installedVersion(root) {
739
761
  try {
740
- const pkg = JSON.parse(await readFile2(join3(root, "package.json"), "utf8"));
762
+ const pkg = JSON.parse(await readFile2(join4(root, "package.json"), "utf8"));
741
763
  return pkg.name === PACKAGE2 && typeof pkg.version === "string" ? pkg.version : void 0;
742
764
  } catch {
743
765
  return void 0;
@@ -745,38 +767,29 @@ async function installedVersion(root) {
745
767
  }
746
768
  async function checkedEntry(root, version) {
747
769
  if (await installedVersion(root) !== version) throw new Error(`CLI \u5B89\u88C5\u7ED3\u679C\u4E0E\u672C\u6B21\u8981\u6C42\u7684 ${version} \u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u8BD5\u3002`);
748
- const entry = join3(root, "dist", "bin", "buddy.js");
770
+ const entry = join4(root, "dist", "bin", "buddy.js");
749
771
  if (!(await lstat2(entry)).isFile()) throw new Error("\u65B0\u7248 CLI \u7F3A\u5C11\u6709\u6548\u7684\u6267\u884C\u5165\u53E3\u3002");
750
772
  return entry;
751
773
  }
752
774
  async function prepareLatest(version, options) {
753
775
  const cache = options.cacheDirectory ?? defaultUpdateCache();
754
- const runNpm = options.runNpm ?? ((args, settings2) => execute2("npm", args, { ...settings2, encoding: "utf8", maxBuffer: 4 * 1024 * 1024 }));
755
- const settings = { cwd: homedir3(), signal: options.signal, timeout: 1e4 };
756
- const { stdout: stdout2 } = await runNpm(["prefix", "--global"], settings);
757
- const prefix = stdout2.trim();
758
- if (!isAbsolute2(prefix) || /[\r\n]/u.test(prefix)) throw new Error("\u65E0\u6CD5\u786E\u5B9A npm \u5168\u5C40\u5B89\u88C5\u76EE\u5F55\u3002");
759
- const globalRoot = join3(prefix, "lib", "node_modules", PACKAGE2);
760
- let isGlobal = false;
761
- try {
762
- isGlobal = !(await lstat2(globalRoot)).isSymbolicLink() && await realpath2(globalRoot) === await realpath2(options.packageRoot);
763
- } catch {
764
- }
765
- if (isGlobal) {
776
+ const runNpm = options.runNpm ?? ((args, settings) => execute2("npm", args, { ...settings, encoding: "utf8", maxBuffer: 4 * 1024 * 1024 }));
777
+ const installation = await globalInstallation(options.packageRoot, PACKAGE2);
778
+ if (installation) {
766
779
  await installUpdate(version, options);
767
- return checkedEntry(globalRoot, version);
780
+ return checkedEntry(installation.root, version);
768
781
  }
769
- const destination = join3(cache, "releases", version);
770
- return withUpdateLock(join3(cache, "locks", `release-${version}`), options.signal, async () => {
771
- const root = join3(destination, "node_modules", PACKAGE2);
782
+ const destination = join4(cache, "releases", version);
783
+ return withUpdateLock(join4(cache, "locks", `release-${version}`), options.signal, async () => {
784
+ const root = join4(destination, "node_modules", PACKAGE2);
772
785
  try {
773
786
  return await checkedEntry(root, version);
774
787
  } catch {
775
788
  }
776
- await mkdir2(join3(cache, "releases"), { recursive: true, mode: 448 });
777
- const temporary = await mkdtemp(join3(cache, "releases", ".install-"));
789
+ await mkdir2(join4(cache, "releases"), { recursive: true, mode: 448 });
790
+ const temporary = await mkdtemp(join4(cache, "releases", ".install-"));
778
791
  try {
779
- await writeFile2(join3(temporary, "package.json"), JSON.stringify({ private: true }));
792
+ await writeFile2(join4(temporary, "package.json"), JSON.stringify({ private: true }));
780
793
  await installCliWithNpm(
781
794
  [
782
795
  "install",
@@ -793,7 +806,7 @@ async function prepareLatest(version, options) {
793
806
  { cwd: temporary, signal: options.signal, timeout: 18e4 },
794
807
  runNpm
795
808
  );
796
- await checkedEntry(join3(temporary, "node_modules", PACKAGE2), version);
809
+ await checkedEntry(join4(temporary, "node_modules", PACKAGE2), version);
797
810
  options.signal?.throwIfAborted();
798
811
  await rm2(destination, { recursive: true, force: true });
799
812
  await rename(temporary, destination);
@@ -805,7 +818,7 @@ async function prepareLatest(version, options) {
805
818
  }
806
819
  async function runUpdatedCli(entry, args, options) {
807
820
  options.signal?.throwIfAborted();
808
- return new Promise((resolve2, reject) => {
821
+ return new Promise((resolve3, reject) => {
809
822
  const child = spawn(process.execPath, [entry, ...args], { cwd: options.cwd, env: options.env, stdio: "inherit" });
810
823
  let killTimer;
811
824
  const abort = () => {
@@ -825,7 +838,7 @@ async function runUpdatedCli(entry, args, options) {
825
838
  });
826
839
  child.once("exit", (code, signal) => {
827
840
  cleanup();
828
- resolve2({ exitCode: code ?? 128 + (signal ? constants.signals[signal] : 1) });
841
+ resolve3({ exitCode: code ?? 128 + (signal ? constants.signals[signal] : 1) });
829
842
  });
830
843
  options.signal?.addEventListener("abort", abort, { once: true });
831
844
  if (options.signal?.aborted) abort();
@@ -836,12 +849,19 @@ async function runAutoUpdate(args, io, options) {
836
849
  if (args[0] === "help" || args[0] === "update" || args[0] === "--version" || args[0] === "-v" || args.includes("--help") || args.includes("-h")) return void 0;
837
850
  try {
838
851
  const env = { ...options.env ?? process.env };
852
+ const pin = env.BUDDY_CLI_PIN_VERSION;
853
+ if (pin !== void 0) {
854
+ if (!/^\d+\.\d+\.\d+-dev\.\d+$/.test(pin) || pin !== options.version) {
855
+ throw new Error(`CLI \u7248\u672C\u9501\u5B9A\u4E0D\u5339\u914D\uFF1A\u8981\u6C42 ${pin}\uFF0C\u5F53\u524D ${options.version}\u3002\u8BF7\u5B89\u88C5 @my-life-buddies/cli@${pin} \u6216 unset BUDDY_CLI_PIN_VERSION\u3002`);
856
+ }
857
+ return void 0;
858
+ }
839
859
  const handoff = env[HANDOFF_ENV];
840
860
  if (handoff !== void 0) {
841
861
  delete env[HANDOFF_ENV];
842
862
  if (!options.env) delete process.env[HANDOFF_ENV];
843
863
  const expected = JSON.parse(handoff);
844
- const entry2 = await realpath2(join3(options.packageRoot, "dist", "bin", "buddy.js"));
864
+ const entry2 = await realpath2(join4(options.packageRoot, "dist", "bin", "buddy.js"));
845
865
  if (expected.parent !== process.ppid || expected.version !== options.version || expected.entry !== entry2 || JSON.stringify(expected.args) !== JSON.stringify(args)) throw new Error("CLI \u81EA\u52A8\u66F4\u65B0\u63A5\u7EED\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u547D\u4EE4\u3002");
846
866
  return void 0;
847
867
  }
@@ -949,13 +969,15 @@ try {
949
969
  const manifestPath = require2.resolve("@my-life-buddies/cli/package.json");
950
970
  const updateOptions = {
951
971
  version: require2(manifestPath).version,
952
- packageRoot: dirname2(manifestPath),
972
+ packageRoot: dirname3(manifestPath),
953
973
  signal: lifecycle.signal
954
974
  };
955
975
  const maintenance = await runSelfUpdateCommand(args, terminal, updateOptions) ?? await runAutoUpdate(args, terminal, updateOptions);
956
976
  const command = args[0];
957
977
  let platformHost;
958
978
  const host = () => platformHost ??= new BuddyPlatformHost({ signal: lifecycle.signal });
979
+ const offlineHelp = !command ? false : ["help", "--help", "-h"].includes(command) || args.includes("--help") || args.includes("-h");
980
+ if (maintenance === void 0 && !offlineHelp) resolvePlatformUrl2();
959
981
  const result = maintenance ?? await runBuddyCli(args, terminal, {
960
982
  runtimeCatalog: { signal: lifecycle.signal },
961
983
  scaffoldPlatformAgent: (root, name, runtimeVersion) => scaffoldPlatformAgent(root, name, {
@@ -975,7 +997,7 @@ try {
975
997
  process.exitCode = result.exitCode;
976
998
  } catch (cause) {
977
999
  const message = cause instanceof Error ? cause.message : String(cause);
978
- terminal.writeError(`buddy-cli: ${message}`);
1000
+ terminal.writeError(`buddy-cli-sit: ${message}`);
979
1001
  process.exitCode = 1;
980
1002
  } finally {
981
1003
  unbindTermination();