@my-life-buddies/cli 0.13.0 → 0.13.3

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/core.js CHANGED
@@ -2465,10 +2465,14 @@ var MlbDevRegistrationClient = class {
2465
2465
  #baseUrl;
2466
2466
  #developerToken;
2467
2467
  #fetch;
2468
+ #tokenStoreFor;
2469
+ #refreshToken;
2468
2470
  constructor(options) {
2469
2471
  this.#baseUrl = normalizePlatformUrl(options.baseUrl);
2470
2472
  this.#developerToken = safeCredential(options.developerToken, "developerToken");
2471
2473
  this.#fetch = options.fetch ?? globalThis.fetch;
2474
+ this.#tokenStoreFor = options.tokenStoreFor;
2475
+ this.#refreshToken = options.refreshToken ?? false;
2472
2476
  if (typeof this.#fetch !== "function") {
2473
2477
  throw new TypeError("A Fetch API implementation is required");
2474
2478
  }
@@ -2538,6 +2542,13 @@ var MlbDevRegistrationClient = class {
2538
2542
  message: "buddy.agent.json \u4E2D\u7684 buddyId \u65E0\u6548\u3002"
2539
2543
  });
2540
2544
  }
2545
+ options.signal.throwIfAborted();
2546
+ const store = this.#tokenStoreFor?.(request.devAgentId);
2547
+ const cached = this.#refreshToken ? void 0 : await store?.load();
2548
+ if (cached !== void 0) {
2549
+ options.signal.throwIfAborted();
2550
+ return Object.freeze({ devAgentId: request.devAgentId, appServerUrl: new URL(this.#baseUrl), agentToken: safeCredential(cached, "agentToken") });
2551
+ }
2541
2552
  const body = object2(await this.#request(
2542
2553
  `/cli/buddies/${encodeURIComponent(request.devAgentId)}`,
2543
2554
  {
@@ -2552,10 +2563,13 @@ var MlbDevRegistrationClient = class {
2552
2563
  message: "\u642D\u5B50\u8BE6\u60C5\u54CD\u5E94\u7F3A\u5C11\u5339\u914D\u7684 id \u6216 Buddy token\u3002"
2553
2564
  });
2554
2565
  }
2566
+ const token = safeCredential(body.token, "agentToken");
2567
+ options.signal.throwIfAborted();
2568
+ await store?.save(token);
2555
2569
  return Object.freeze({
2556
2570
  devAgentId: request.devAgentId,
2557
2571
  appServerUrl: new URL(this.#baseUrl),
2558
- agentToken: safeCredential(body.token, "agentToken")
2572
+ agentToken: token
2559
2573
  });
2560
2574
  }
2561
2575
  async listOnline(options) {
@@ -2942,7 +2956,7 @@ function validateRegistration(value, expectedAgentId) {
2942
2956
  throw new BuddyDevError({
2943
2957
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
2944
2958
  phase: "registration",
2945
- message: "DEV \u6302\u53F7\u6CA1\u6709\u8FD4\u56DE\u5339\u914D\u7684 Buddy \u8EAB\u4EFD\u4E0E\u77ED\u671F Buddy token\u3002"
2959
+ message: "DEV \u6302\u53F7\u6CA1\u6709\u8FD4\u56DE\u5339\u914D\u7684 Buddy \u8EAB\u4EFD\u4E0E\u5F00\u53D1 Token\u3002"
2946
2960
  });
2947
2961
  }
2948
2962
  return value;
@@ -3291,6 +3305,183 @@ function createBuddyDevStarter(options = {}) {
3291
3305
  });
3292
3306
  }
3293
3307
 
3308
+ // packages/cli-core/src/dev/token-store.ts
3309
+ import { createHash as createHash5 } from "node:crypto";
3310
+
3311
+ // packages/cli-core/src/cloud/credential-store.ts
3312
+ import { spawn } from "node:child_process";
3313
+ var DEFAULT_SERVICE = "com.xiaohongshu.buddy.developer-cli";
3314
+ var DEFAULT_ACCOUNT = "developer-session";
3315
+ var MAX_CREDENTIAL_BYTES = 32 * 1024;
3316
+ function safeLabel(value, fallback, name) {
3317
+ const result = value ?? fallback;
3318
+ if (!result || result !== result.trim() || /[\u0000-\u001f\u007f]/u.test(result) || result.length > 256) {
3319
+ throw new TypeError(`${name} is invalid`);
3320
+ }
3321
+ return result;
3322
+ }
3323
+ function serialize(token) {
3324
+ const value = JSON.stringify(token);
3325
+ if (Buffer.byteLength(value, "utf8") > MAX_CREDENTIAL_BYTES) {
3326
+ throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u4E91\u7AEF\u4F1A\u8BDD\u51ED\u636E\u8FC7\u5927\uFF0C\u672A\u4FDD\u5B58");
3327
+ }
3328
+ return value;
3329
+ }
3330
+ function parse(source) {
3331
+ if (Buffer.byteLength(source, "utf8") > MAX_CREDENTIAL_BYTES) {
3332
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3333
+ }
3334
+ let value;
3335
+ try {
3336
+ value = JSON.parse(source);
3337
+ } catch {
3338
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3339
+ }
3340
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3341
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3342
+ }
3343
+ const record2 = value;
3344
+ if (Object.keys(record2).length !== 3 || typeof record2.accessToken !== "string" || typeof record2.subject !== "string" || !Number.isSafeInteger(record2.expiresAt)) {
3345
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3346
+ }
3347
+ return Object.freeze({
3348
+ accessToken: record2.accessToken,
3349
+ subject: record2.subject,
3350
+ expiresAt: record2.expiresAt
3351
+ });
3352
+ }
3353
+ async function runCredentialCommand(input) {
3354
+ return await new Promise((resolve17, reject) => {
3355
+ const child = spawn(input.command, [...input.args], {
3356
+ shell: false,
3357
+ windowsHide: true,
3358
+ stdio: ["pipe", "pipe", "pipe"]
3359
+ });
3360
+ const stdout = [];
3361
+ const stderr = [];
3362
+ let outputBytes = 0;
3363
+ const collect = (target, chunk) => {
3364
+ outputBytes += chunk.byteLength;
3365
+ if (outputBytes <= MAX_CREDENTIAL_BYTES) target.push(chunk);
3366
+ };
3367
+ child.stdout.on("data", (chunk) => collect(stdout, chunk));
3368
+ child.stderr.on("data", (chunk) => collect(stderr, chunk));
3369
+ child.once("error", reject);
3370
+ child.once("close", (code2) => resolve17({
3371
+ code: code2 ?? 1,
3372
+ stdout: Buffer.concat(stdout).toString("utf8"),
3373
+ stderr: Buffer.concat(stderr).toString("utf8")
3374
+ }));
3375
+ child.stdin.on("error", () => void 0);
3376
+ child.stdin.end(input.input ?? "");
3377
+ });
3378
+ }
3379
+ var SystemCredentialStore = class {
3380
+ #platform;
3381
+ #service;
3382
+ #account;
3383
+ #run;
3384
+ constructor(options = {}) {
3385
+ this.#platform = options.platform ?? process.platform;
3386
+ this.#service = safeLabel(options.service, DEFAULT_SERVICE, "service");
3387
+ this.#account = safeLabel(options.account, DEFAULT_ACCOUNT, "account");
3388
+ this.#run = options.commandRunner ?? runCredentialCommand;
3389
+ if (this.#platform !== "darwin") {
3390
+ throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D CLI V1 \u7684\u5B89\u5168\u51ED\u636E\u5B58\u50A8\u76EE\u524D\u53EA\u652F\u6301 macOS Keychain");
3391
+ }
3392
+ }
3393
+ async load() {
3394
+ const result = await this.#run({
3395
+ command: "security",
3396
+ args: ["find-generic-password", "-s", this.#service, "-a", this.#account, "-w"]
3397
+ });
3398
+ if (result.code === 44) return void 0;
3399
+ if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u8BFB\u53D6 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u51ED\u636E");
3400
+ const raw = result.stdout.trimEnd();
3401
+ return /^(?:[a-fA-F0-9]{2})+$/u.test(raw) ? Buffer.from(raw, "hex").toString("utf8") : raw;
3402
+ }
3403
+ async save(source) {
3404
+ if (!source || /[\u0000-\u001f\u007f]/u.test(source)) throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3405
+ const line = ["add-generic-password", "-U", "-s", this.#service, "-a", this.#account, "-w", source].map((part) => `"${part.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"')}"`).join(" ") + "\n";
3406
+ if (Buffer.byteLength(line, "utf8") >= 4096) {
3407
+ throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u51ED\u636E\u8D85\u8FC7 macOS \u5199\u5165\u957F\u5EA6\u9650\u5236\uFF0C\u672A\u4FDD\u5B58\uFF1B\u8BF7\u8054\u7CFB\u5E73\u53F0\u5904\u7406");
3408
+ }
3409
+ const result = await this.#run({
3410
+ command: "security",
3411
+ args: ["-i", "-q"],
3412
+ input: line
3413
+ });
3414
+ if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u628A\u642D\u642D\u51ED\u636E\u5199\u5165 macOS \u94A5\u5319\u4E32");
3415
+ const saved = await this.load();
3416
+ if (!saved || saved !== source) throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u51ED\u636E\u5199\u5165\u540E\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
3417
+ }
3418
+ async clear() {
3419
+ const result = await this.#run({
3420
+ command: "security",
3421
+ args: ["delete-generic-password", "-s", this.#service, "-a", this.#account]
3422
+ });
3423
+ if (result.code !== 0 && result.code !== 44) {
3424
+ throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u6E05\u9664 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u51ED\u636E");
3425
+ }
3426
+ }
3427
+ };
3428
+ var SystemCloudTokenStore = class {
3429
+ #store;
3430
+ constructor(options = {}) {
3431
+ this.#store = new SystemCredentialStore(options);
3432
+ }
3433
+ async load() {
3434
+ const raw = await this.#store.load();
3435
+ return raw === void 0 ? void 0 : parse(raw);
3436
+ }
3437
+ async save(token) {
3438
+ await this.#store.save(serialize(token));
3439
+ }
3440
+ async clear() {
3441
+ await this.#store.clear();
3442
+ }
3443
+ };
3444
+
3445
+ // packages/cli-core/src/dev/token-store.ts
3446
+ var SystemBuddyTokenStore = class {
3447
+ #store;
3448
+ constructor(options) {
3449
+ if (![options.subject, options.buddyId].every((value) => value.trim() && !/[\u0000-\u001f\u007f]/u.test(value))) throw new TypeError("\u5F00\u53D1 Token \u7684\u8D26\u53F7\u548C\u642D\u5B50 ID \u65E0\u6548");
3450
+ const scope = JSON.stringify([normalizePlatformUrl(options.platformUrl).origin, options.subject, options.buddyId]);
3451
+ this.#store = new SystemCredentialStore({
3452
+ service: "com.xiaohongshu.buddy.developer-cli.dev-token",
3453
+ account: createHash5("sha256").update(scope).digest("hex"),
3454
+ platform: options.platform,
3455
+ commandRunner: options.commandRunner
3456
+ });
3457
+ }
3458
+ async load() {
3459
+ const raw = await this.#store.load();
3460
+ if (raw === void 0) return void 0;
3461
+ let value;
3462
+ try {
3463
+ value = JSON.parse(raw);
3464
+ } catch {
3465
+ throw corrupt();
3466
+ }
3467
+ if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).length !== 1 || !("token" in value)) throw corrupt();
3468
+ return validateToken(value.token);
3469
+ }
3470
+ async save(token) {
3471
+ await this.#store.save(JSON.stringify({ token: validateToken(token) }));
3472
+ }
3473
+ async clear() {
3474
+ await this.#store.clear();
3475
+ }
3476
+ };
3477
+ function corrupt() {
3478
+ return new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u672C\u673A\u5F00\u53D1\u51ED\u636E\u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6");
3479
+ }
3480
+ function validateToken(value) {
3481
+ if (typeof value !== "string" || !value.trim() || /[\u0000-\u001f\u007f]/u.test(value) || value.length > 1024) throw corrupt();
3482
+ return value;
3483
+ }
3484
+
3294
3485
  // packages/cli-core/src/commands/dev.ts
3295
3486
  var DevCommandUsageError = class extends Error {
3296
3487
  constructor(message) {
@@ -3299,12 +3490,13 @@ var DevCommandUsageError = class extends Error {
3299
3490
  }
3300
3491
  };
3301
3492
  var DEV_COMMAND_HELP = `\u7528\u6CD5:
3302
- buddy-cli dev [--app-server <App Server URL>] [--directory <\u9879\u76EE\u76EE\u5F55>]
3493
+ buddy-cli dev [--app-server <App Server URL>] [--directory <\u9879\u76EE\u76EE\u5F55>] [--refresh-token]
3303
3494
 
3304
3495
  \u8BF4\u660E:
3305
3496
  \u672A\u914D\u7F6E\u5730\u5740\u65F6\u8FDE\u63A5 MLB \u6D4B\u8BD5\u73AF\u5883 ${DEFAULT_MLB_TEST_URL}\uFF08HTTP \u4EC5\u9650\u6D4B\u8BD5\uFF09\u3002
3306
3497
  CLI \u7EDF\u4E00\u542F\u52A8\u5E76\u7BA1\u7406\u5DE5\u7A0B\u4E2D\u7684\u5B98\u65B9 Runtime\u3002
3307
- DEV \u4F1A\u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u5F00\u53D1\u8005\u4F1A\u8BDD\uFF0C\u518D\u8BFB\u53D6\u5F53\u524D buddy.agent.json \u4E2D\u7684 buddyId \u5BF9\u5E94\u7684 Buddy token\u3002`;
3498
+ DEV \u4F1A\u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u5F00\u53D1\u8005\u4F1A\u8BDD\uFF0C\u518D\u8BFB\u53D6\u5F53\u524D buddy.agent.json \u4E2D\u7684 buddyId \u5BF9\u5E94\u7684\u5F00\u53D1 Token\uFF0C\u4FDD\u5B58\u5230\u7CFB\u7EDF\u94A5\u5319\u4E32\u4F9B\u540E\u7EED\u590D\u7528\u3002
3499
+ --refresh-token \u91CD\u65B0\u9886\u53D6\u5DF2\u6709\u5F00\u53D1 Token\uFF0C\u7528\u4E8E\u670D\u52A1\u7AEF\u91CD\u7F6E\u540E\u7684\u672C\u673A\u66F4\u65B0\uFF1B\u4E0D\u4F1A\u751F\u6210\u65B0\u5BC6\u94A5\u3002`;
3308
3500
  function valueAfter(args, index, flag2) {
3309
3501
  const value = args[index + 1];
3310
3502
  if (value === void 0 || !value.trim()) throw new DevCommandUsageError(`${flag2} \u7F3A\u5C11\u503C`);
@@ -3319,6 +3511,7 @@ function parseDevArguments(args) {
3319
3511
  let directorySet = false;
3320
3512
  let appServer;
3321
3513
  let help = false;
3514
+ let refreshToken = false;
3322
3515
  for (let index = 0; index < args.length; index += 1) {
3323
3516
  const flag2 = args[index];
3324
3517
  if (flag2 === "--help" || flag2 === "-h") {
@@ -3326,6 +3519,11 @@ function parseDevArguments(args) {
3326
3519
  help = true;
3327
3520
  continue;
3328
3521
  }
3522
+ if (flag2 === "--refresh-token") {
3523
+ if (refreshToken) throw new DevCommandUsageError("--refresh-token \u4E0D\u80FD\u91CD\u590D");
3524
+ refreshToken = true;
3525
+ continue;
3526
+ }
3329
3527
  const value = valueAfter(args, index, flag2 ?? "\u53C2\u6570");
3330
3528
  index += 1;
3331
3529
  switch (flag2) {
@@ -3341,7 +3539,7 @@ function parseDevArguments(args) {
3341
3539
  throw new DevCommandUsageError(`\u672A\u77E5 dev \u53C2\u6570 ${flag2}`);
3342
3540
  }
3343
3541
  }
3344
- return { directory, appServer, help };
3542
+ return { directory, appServer, help, refreshToken };
3345
3543
  }
3346
3544
  function appServerUrl(override, env) {
3347
3545
  try {
@@ -3375,7 +3573,7 @@ async function runDevCommand(args, io, options = {}) {
3375
3573
  const root = await (options.resolveProjectRoot ?? requireBuddyAgentProjectRoot)(requestedRoot);
3376
3574
  const environment = options.env ?? process.env;
3377
3575
  const url = appServerUrl(parsed.appServer, environment);
3378
- const authorizationInput = { appServerUrl: url };
3576
+ const authorizationInput = { appServerUrl: url, ...parsed.refreshToken ? { refreshToken: true } : {} };
3379
3577
  if (!options.authorize) {
3380
3578
  throw new DevCommandUsageError("\u5F53\u524D CLI Host \u5C1A\u672A\u914D\u7F6E\u642D\u642D\u8D26\u53F7\u767B\u5F55 Adapter");
3381
3579
  }
@@ -3478,7 +3676,7 @@ var MemoryCloudTokenStore = class {
3478
3676
  return this.#token === void 0 ? void 0 : frozenClone(this.#token);
3479
3677
  }
3480
3678
  async save(token) {
3481
- this.#token = validateToken(token);
3679
+ this.#token = validateToken2(token);
3482
3680
  }
3483
3681
  async clear() {
3484
3682
  this.#token = void 0;
@@ -3534,7 +3732,7 @@ var CloudAuthenticator = class {
3534
3732
  }
3535
3733
  if (stored === void 0) return void 0;
3536
3734
  try {
3537
- const token = validateToken(stored);
3735
+ const token = validateToken2(stored);
3538
3736
  if (token.expiresAt > this.#now() + this.#minimumValidityMs) return token;
3539
3737
  } catch {
3540
3738
  }
@@ -3555,7 +3753,7 @@ var CloudAuthenticator = class {
3555
3753
  "\u6D4F\u89C8\u5668\u767B\u5F55\u8FD4\u56DE\u7684 state \u4E0D\u5339\u914D\uFF1B\u51ED\u636E\u672A\u4FDD\u5B58"
3556
3754
  );
3557
3755
  }
3558
- const token = validateToken(resultRecord.token);
3756
+ const token = validateToken2(resultRecord.token);
3559
3757
  if (token.expiresAt <= this.#now() + this.#minimumValidityMs) {
3560
3758
  throw new CloudLifecycleError("AUTH_TOKEN_EXPIRED", "\u6D4F\u89C8\u5668\u767B\u5F55\u8FD4\u56DE\u4E86\u5DF2\u8FC7\u671F\u6216\u5373\u5C06\u8FC7\u671F\u7684\u4F1A\u8BDD");
3561
3759
  }
@@ -3563,7 +3761,7 @@ var CloudAuthenticator = class {
3563
3761
  return token;
3564
3762
  }
3565
3763
  };
3566
- function validateToken(value) {
3764
+ function validateToken2(value) {
3567
3765
  try {
3568
3766
  const input = record(value, "cloud token");
3569
3767
  exactKeys(input, ["accessToken", "subject", "expiresAt"], [], "cloud token");
@@ -3866,8 +4064,8 @@ var HttpDeveloperPlatformClient = class {
3866
4064
  };
3867
4065
 
3868
4066
  // packages/cli-core/src/cloud/browser-login.ts
3869
- import { createHash as createHash5, randomBytes } from "node:crypto";
3870
- import { spawn } from "node:child_process";
4067
+ import { createHash as createHash6, randomBytes } from "node:crypto";
4068
+ import { spawn as spawn2 } from "node:child_process";
3871
4069
  import { createServer } from "node:http";
3872
4070
 
3873
4071
  // packages/cli-core/src/cloud/login-result.ts
@@ -3927,7 +4125,7 @@ function browserCommand(url) {
3927
4125
  async function openExternalUrl(url) {
3928
4126
  const launch = browserCommand(url);
3929
4127
  await new Promise((resolve17, reject) => {
3930
- const child = spawn(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
4128
+ const child = spawn2(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
3931
4129
  child.once("error", reject);
3932
4130
  child.once("exit", (code2) => code2 === 0 ? resolve17() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
3933
4131
  });
@@ -3974,7 +4172,7 @@ var LoopbackBrowserLoginAdapter = class {
3974
4172
  if (request.signal?.aborted) throw request.signal.reason;
3975
4173
  const callbackSecret = randomBytes(24).toString("hex");
3976
4174
  const codeVerifier = randomBytes(32).toString("base64url");
3977
- const codeChallenge = createHash5("sha256").update(codeVerifier).digest("base64url");
4175
+ const codeChallenge = createHash6("sha256").update(codeVerifier).digest("base64url");
3978
4176
  let requestId = "";
3979
4177
  let settle;
3980
4178
  let reject;
@@ -4110,126 +4308,8 @@ var LoopbackBrowserLoginAdapter = class {
4110
4308
  }
4111
4309
  };
4112
4310
 
4113
- // packages/cli-core/src/cloud/credential-store.ts
4114
- import { spawn as spawn2 } from "node:child_process";
4115
- var DEFAULT_SERVICE = "com.xiaohongshu.buddy.developer-cli";
4116
- var DEFAULT_ACCOUNT = "developer-session";
4117
- var MAX_CREDENTIAL_BYTES = 32 * 1024;
4118
- function safeLabel(value, fallback, name) {
4119
- const result = value ?? fallback;
4120
- if (!result || result !== result.trim() || /[\u0000-\u001f\u007f]/u.test(result) || result.length > 256) {
4121
- throw new TypeError(`${name} is invalid`);
4122
- }
4123
- return result;
4124
- }
4125
- function serialize(token) {
4126
- const value = JSON.stringify(token);
4127
- if (Buffer.byteLength(value, "utf8") > MAX_CREDENTIAL_BYTES) {
4128
- throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u4E91\u7AEF\u4F1A\u8BDD\u51ED\u636E\u8FC7\u5927\uFF0C\u672A\u4FDD\u5B58");
4129
- }
4130
- return value;
4131
- }
4132
- function parse(source) {
4133
- if (Buffer.byteLength(source, "utf8") > MAX_CREDENTIAL_BYTES) {
4134
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4135
- }
4136
- let value;
4137
- try {
4138
- value = JSON.parse(source);
4139
- } catch {
4140
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4141
- }
4142
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
4143
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4144
- }
4145
- const record2 = value;
4146
- if (Object.keys(record2).length !== 3 || typeof record2.accessToken !== "string" || typeof record2.subject !== "string" || !Number.isSafeInteger(record2.expiresAt)) {
4147
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4148
- }
4149
- return Object.freeze({
4150
- accessToken: record2.accessToken,
4151
- subject: record2.subject,
4152
- expiresAt: record2.expiresAt
4153
- });
4154
- }
4155
- async function runCredentialCommand(input) {
4156
- return await new Promise((resolve17, reject) => {
4157
- const child = spawn2(input.command, [...input.args], {
4158
- shell: false,
4159
- windowsHide: true,
4160
- stdio: ["pipe", "pipe", "pipe"]
4161
- });
4162
- const stdout = [];
4163
- const stderr = [];
4164
- let outputBytes = 0;
4165
- const collect = (target, chunk) => {
4166
- outputBytes += chunk.byteLength;
4167
- if (outputBytes <= MAX_CREDENTIAL_BYTES) target.push(chunk);
4168
- };
4169
- child.stdout.on("data", (chunk) => collect(stdout, chunk));
4170
- child.stderr.on("data", (chunk) => collect(stderr, chunk));
4171
- child.once("error", reject);
4172
- child.once("close", (code2) => resolve17({
4173
- code: code2 ?? 1,
4174
- stdout: Buffer.concat(stdout).toString("utf8"),
4175
- stderr: Buffer.concat(stderr).toString("utf8")
4176
- }));
4177
- child.stdin.on("error", () => void 0);
4178
- child.stdin.end(input.input ?? "");
4179
- });
4180
- }
4181
- var SystemCloudTokenStore = class {
4182
- #platform;
4183
- #service;
4184
- #account;
4185
- #run;
4186
- constructor(options = {}) {
4187
- this.#platform = options.platform ?? process.platform;
4188
- this.#service = safeLabel(options.service, DEFAULT_SERVICE, "service");
4189
- this.#account = safeLabel(options.account, DEFAULT_ACCOUNT, "account");
4190
- this.#run = options.commandRunner ?? runCredentialCommand;
4191
- if (this.#platform !== "darwin") {
4192
- throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D CLI V1 \u7684\u5B89\u5168\u767B\u5F55\u5B58\u50A8\u76EE\u524D\u53EA\u652F\u6301 macOS Keychain");
4193
- }
4194
- }
4195
- async load() {
4196
- const result = await this.#run({
4197
- command: "security",
4198
- args: ["find-generic-password", "-s", this.#service, "-a", this.#account, "-w"]
4199
- });
4200
- if (result.code === 44) return void 0;
4201
- if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u8BFB\u53D6 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u767B\u5F55\u72B6\u6001");
4202
- const raw = result.stdout.trimEnd();
4203
- return parse(/^(?:[a-fA-F0-9]{2})+$/u.test(raw) ? Buffer.from(raw, "hex").toString("utf8") : raw);
4204
- }
4205
- async save(token) {
4206
- const source = serialize(token);
4207
- const line = ["add-generic-password", "-U", "-s", this.#service, "-a", this.#account, "-w", source].map((part) => `"${part.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"')}"`).join(" ") + "\n";
4208
- if (Buffer.byteLength(line, "utf8") >= 4096) {
4209
- throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u767B\u5F55\u51ED\u636E\u8D85\u8FC7 macOS \u5199\u5165\u957F\u5EA6\u9650\u5236\uFF0C\u672A\u4FDD\u5B58\uFF1B\u8BF7\u8054\u7CFB\u5E73\u53F0\u5904\u7406");
4210
- }
4211
- const result = await this.#run({
4212
- command: "security",
4213
- args: ["-i", "-q"],
4214
- input: line
4215
- });
4216
- if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u628A\u642D\u642D\u767B\u5F55\u72B6\u6001\u5199\u5165 macOS \u94A5\u5319\u4E32");
4217
- const saved = await this.load();
4218
- if (!saved || serialize(saved) !== source) throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u767B\u5F55\u51ED\u636E\u5199\u5165\u540E\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55");
4219
- }
4220
- async clear() {
4221
- const result = await this.#run({
4222
- command: "security",
4223
- args: ["delete-generic-password", "-s", this.#service, "-a", this.#account]
4224
- });
4225
- if (result.code !== 0 && result.code !== 44) {
4226
- throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u6E05\u9664 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u767B\u5F55\u72B6\u6001");
4227
- }
4228
- }
4229
- };
4230
-
4231
4311
  // packages/cli-core/src/cloud/mock-client.ts
4232
- import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
4312
+ import { createHash as createHash7, randomBytes as randomBytes2 } from "node:crypto";
4233
4313
  var MockDeveloperPlatformClient = class {
4234
4314
  #now;
4235
4315
  #buddies = /* @__PURE__ */ new Map();
@@ -4257,7 +4337,7 @@ var MockDeveloperPlatformClient = class {
4257
4337
  const current = this.#require(request.id);
4258
4338
  validateBuddyMetaUpdate(request.meta);
4259
4339
  const onlyAvatar = Object.keys(request.meta).every((key) => key === "avatar");
4260
- const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash6("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
4340
+ const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash7("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
4261
4341
  const next = this.#value({ ...current, meta: { ...onlyAvatar ? current.meta : request.meta, avatar }, updatedAt: this.#now() });
4262
4342
  this.#buddies.set(request.id, next);
4263
4343
  return structuredClone(next);
@@ -5319,7 +5399,7 @@ async function scanExternalSkillPortability(options) {
5319
5399
  }
5320
5400
 
5321
5401
  // packages/cli-core/src/push/preflight.ts
5322
- import { createHash as createHash7 } from "node:crypto";
5402
+ import { createHash as createHash8 } from "node:crypto";
5323
5403
  import { lstat as lstat10, open as open5, readdir as readdir5, realpath as realpath4 } from "node:fs/promises";
5324
5404
  import { isAbsolute as isAbsolute3, join as join13, relative as relative2, resolve as resolve15, sep as sep2, win32 as win323 } from "node:path";
5325
5405
 
@@ -5419,7 +5499,7 @@ function error(options) {
5419
5499
  throw new PushPreflightError(options);
5420
5500
  }
5421
5501
  function sha256(value) {
5422
- return `sha256:${createHash7("sha256").update(value).digest("hex")}`;
5502
+ return `sha256:${createHash8("sha256").update(value).digest("hex")}`;
5423
5503
  }
5424
5504
  function positiveLimit(value, name, hardMaximum) {
5425
5505
  if (!Number.isSafeInteger(value) || value < 1 || value > hardMaximum) {
@@ -5665,7 +5745,7 @@ async function hashRegularFile(options) {
5665
5745
  message: `\u751F\u6210\u6E05\u5355\u65F6\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${options.portablePath}`
5666
5746
  });
5667
5747
  }
5668
- const hash3 = createHash7("sha256");
5748
+ const hash3 = createHash8("sha256");
5669
5749
  const captured = [];
5670
5750
  const buffer = Buffer.allocUnsafe(READ_BUFFER_BYTES);
5671
5751
  let bytes = 0;
@@ -6124,7 +6204,7 @@ async function createPushPreflight(options) {
6124
6204
  }
6125
6205
 
6126
6206
  // packages/cli-core/src/push/bundle.ts
6127
- import { createHash as createHash8 } from "node:crypto";
6207
+ import { createHash as createHash9 } from "node:crypto";
6128
6208
  import { lstat as lstat11, readFile as readFile11, realpath as realpath5 } from "node:fs/promises";
6129
6209
  import { join as join14, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
6130
6210
  import { Writable } from "node:stream";
@@ -6133,7 +6213,7 @@ import { createGzip } from "node:zlib";
6133
6213
  import { pack } from "tar-stream";
6134
6214
  var MEDIA_TYPE = "application/gzip";
6135
6215
  function digest2(bytes) {
6136
- return `sha256:${createHash8("sha256").update(bytes).digest("hex")}`;
6216
+ return `sha256:${createHash9("sha256").update(bytes).digest("hex")}`;
6137
6217
  }
6138
6218
  function changed(path, message, cause) {
6139
6219
  throw new PushPreflightError({
@@ -6182,7 +6262,7 @@ async function createPushSourceBundle(plan) {
6182
6262
  schemaVersion: "1",
6183
6263
  files: files.map((file) => ({ path: file.path, bytes: file.bytes, digest: file.digest }))
6184
6264
  });
6185
- const calculatedBundleDigest = `sha256:${createHash8("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
6265
+ const calculatedBundleDigest = `sha256:${createHash9("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
6186
6266
  if (calculatedBundleDigest !== plan.bundleDigest) {
6187
6267
  changed(plan.projectRoot, "\u63D0\u4EA4\u6E05\u5355\u8EAB\u4EFD\u5728\u6253\u5305\u524D\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C push");
6188
6268
  }
@@ -6840,6 +6920,7 @@ export {
6840
6920
  PromptCancelledError,
6841
6921
  PushPreflightError,
6842
6922
  SkillPortabilityScanError,
6923
+ SystemBuddyTokenStore,
6843
6924
  SystemCloudTokenStore,
6844
6925
  abortedDevError,
6845
6926
  applyBuddyDraftInitialization,