@my-life-buddies/cli 0.25.2 → 0.26.0

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
@@ -268,8 +268,8 @@ async function cached(definition3, root, lock) {
268
268
  }
269
269
  const skill = join2(root, "node_modules", definition3.name);
270
270
  try {
271
- const record2 = JSON.parse(await readFile3(join2(root, "package-lock.json"), "utf8"));
272
- const entry2 = record2.packages?.[`node_modules/${definition3.name}`];
271
+ const record3 = JSON.parse(await readFile3(join2(root, "package-lock.json"), "utf8"));
272
+ const entry2 = record3.packages?.[`node_modules/${definition3.name}`];
273
273
  if (entry2?.version !== lock.version || entry2.integrity !== lock.integrity) throw new Error("\u7F13\u5B58\u6821\u9A8C\u8BB0\u5F55\u4E0D\u5339\u914D");
274
274
  await installed(definition3, skill, lock.version);
275
275
  return skill;
@@ -1398,7 +1398,7 @@ async function latestRuntimeTemplate(template, options) {
1398
1398
  "--prefer-online",
1399
1399
  "--fetch-retries=0",
1400
1400
  "--fetch-timeout=20000"
1401
- ], { cwd: temporaryRoot, signal: options.signal, timeout: 6e4 });
1401
+ ], { cwd: temporaryRoot, signal: options.signal, timeout: 18e4 });
1402
1402
  const result = {
1403
1403
  packageJson: await readFile9(join8(temporaryRoot, "package.json"), "utf8"),
1404
1404
  packageLock: await readFile9(join8(temporaryRoot, "package-lock.json"), "utf8")
@@ -1414,7 +1414,8 @@ async function latestRuntimeTemplate(template, options) {
1414
1414
  return result;
1415
1415
  } catch (cause) {
1416
1416
  if (options.signal?.aborted) throw new Error("Runtime \u7248\u672C\u9009\u62E9\u5DF2\u53D6\u6D88");
1417
- const reason = cause instanceof Error && !cause.message.includes("Command failed") ? cause.message : "npm \u672A\u5B8C\u6210\u9501\u6587\u4EF6\u751F\u6210";
1417
+ const interrupted = cause instanceof Error && (cause.code === "ETIMEDOUT" || cause.killed);
1418
+ const reason = interrupted ? "\u4F9D\u8D56\u9501\u6587\u4EF6\u751F\u6210\u8D85\u65F6\u6216\u88AB\u4E2D\u65AD\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5" : cause instanceof Error && !cause.message.includes("Command failed") ? cause.message : "npm \u672A\u5B8C\u6210\u9501\u6587\u4EF6\u751F\u6210";
1418
1419
  throw new Error(`\u672A\u80FD\u9501\u5B9A\u6700\u65B0\u6B63\u5F0F\u7248 Runtime\uFF1A${reason}\u3002\u5DF2\u505C\u6B62\u751F\u6210\u5DE5\u7A0B\u4F9D\u8D56\uFF0C\u8BF7\u4FEE\u590D\u540E\u91CD\u8BD5\uFF1B\u4E0D\u4F1A\u4F7F\u7528\u9884\u7F6E\u6216\u7F13\u5B58\u7684\u65E7\u7248\u672C\u3002`, { cause });
1419
1420
  } finally {
1420
1421
  if (temporaryRoot) await rm3(temporaryRoot, { recursive: true, force: true });
@@ -1664,8 +1665,8 @@ async function selectInitModel(root, requested, io, options = {}) {
1664
1665
  throw new ModelSelectionError(`\u65E0\u6CD5\u786E\u8BA4\u6A21\u578B\uFF1A${cause instanceof Error ? cause.message : String(cause)}\u3002\u8BF7\u4FEE\u590D\u540E\u91CD\u8BD5\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u9009\u62E9\u9ED8\u8BA4\u6A21\u578B\u3002`);
1665
1666
  }
1666
1667
  }
1667
- function checkModelTemplate(template, selection) {
1668
- if (selection && runtimeDependencyVersion(JSON.parse(template.packageJson)) !== selection.runtimeVersion) {
1668
+ function checkModelTemplate(template, selection2) {
1669
+ if (selection2 && runtimeDependencyVersion(JSON.parse(template.packageJson)) !== selection2.runtimeVersion) {
1669
1670
  throw new ModelSelectionError("Runtime \u7248\u672C\u5728\u9009\u62E9\u6A21\u578B\u540E\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C init \u786E\u8BA4\u8BE5\u7248\u672C\u7684\u6A21\u578B\u3002");
1670
1671
  }
1671
1672
  return template;
@@ -2479,7 +2480,7 @@ ${KNOWLEDGE_HELP}`);
2479
2480
  }
2480
2481
 
2481
2482
  // packages/cli-core/src/index.ts
2482
- import { join as join23, resolve as resolve18 } from "node:path";
2483
+ import { join as join24, resolve as resolve19 } from "node:path";
2483
2484
 
2484
2485
  // packages/cli-core/src/init/creator.ts
2485
2486
  import { createHash as createHash3, randomUUID as randomUUID7 } from "node:crypto";
@@ -3148,10 +3149,10 @@ function browserCommand(url) {
3148
3149
  }
3149
3150
  async function openExternalUrl(url) {
3150
3151
  const launch = browserCommand(url);
3151
- await new Promise((resolve19, reject) => {
3152
+ await new Promise((resolve20, reject) => {
3152
3153
  const child = spawn(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
3153
3154
  child.once("error", reject);
3154
- child.once("exit", (code2) => code2 === 0 ? resolve19() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
3155
+ child.once("exit", (code2) => code2 === 0 ? resolve20() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
3155
3156
  });
3156
3157
  }
3157
3158
  async function write(res, status, title, message, webUrl, tone = "error") {
@@ -3163,10 +3164,10 @@ async function write(res, status, title, message, webUrl, tone = "error") {
3163
3164
  "referrer-policy": "no-referrer",
3164
3165
  "x-content-type-options": "nosniff"
3165
3166
  });
3166
- await new Promise((resolve19, reject) => {
3167
+ await new Promise((resolve20, reject) => {
3167
3168
  res.once("error", reject);
3168
- res.once("close", resolve19);
3169
- res.end(renderLoginResult(title, message, webUrl, tone), resolve19);
3169
+ res.once("close", resolve20);
3170
+ res.end(renderLoginResult(title, message, webUrl, tone), resolve20);
3170
3171
  });
3171
3172
  }
3172
3173
  async function readJson(response) {
@@ -3202,11 +3203,11 @@ var LoopbackBrowserLoginAdapter = class {
3202
3203
  let settle;
3203
3204
  let reject;
3204
3205
  let settled = false;
3205
- const result = new Promise((resolve19, rejectResult) => {
3206
+ const result = new Promise((resolve20, rejectResult) => {
3206
3207
  settle = (value) => {
3207
3208
  if (!settled) {
3208
3209
  settled = true;
3209
- resolve19(value);
3210
+ resolve20(value);
3210
3211
  }
3211
3212
  };
3212
3213
  reject = (reason) => {
@@ -3225,9 +3226,9 @@ var LoopbackBrowserLoginAdapter = class {
3225
3226
  state: request.state
3226
3227
  }).then(settle, reject);
3227
3228
  });
3228
- await new Promise((resolve19, rejectListen) => {
3229
+ await new Promise((resolve20, rejectListen) => {
3229
3230
  server.once("error", rejectListen);
3230
- server.listen(0, "127.0.0.1", () => resolve19());
3231
+ server.listen(0, "127.0.0.1", () => resolve20());
3231
3232
  });
3232
3233
  const address = server.address();
3233
3234
  if (!address || typeof address === "string") {
@@ -3260,8 +3261,8 @@ var LoopbackBrowserLoginAdapter = class {
3260
3261
  } finally {
3261
3262
  clearTimeout(timer);
3262
3263
  request.signal?.removeEventListener("abort", abort);
3263
- await new Promise((resolve19) => {
3264
- server.close(() => resolve19());
3264
+ await new Promise((resolve20) => {
3265
+ server.close(() => resolve20());
3265
3266
  server.closeIdleConnections();
3266
3267
  server.closeAllConnections();
3267
3268
  });
@@ -3345,7 +3346,9 @@ var CLI_HELP = `\u642D\u642D Developer Platform CLI
3345
3346
  knowledge \u5C06\u521B\u4F5C\u8D44\u6599\u540C\u6B65\u4E3A\u672C\u5730\u8FD0\u884C\u77E5\u8BC6
3346
3347
  dev \u5728\u7EC8\u7AEF\u542F\u52A8\u5F00\u53D1\u7248\u642D\u5B50\uFF1Bdev stop \u505C\u6B62\u672C\u673A DEV
3347
3348
  preview \u8FDE\u63A5\u5DE5\u7A0B\u5E76\u6253\u5F00\u540E\u53F0\u5F00\u53D1\u8C03\u8BD5
3348
- push \u4E0A\u4F20\u7A0B\u5E8F\u5305\u548C\u6539\u52A8\u8BF4\u660E
3349
+ push \u4E0A\u4F20\u7A0B\u5E8F\u5305\uFF0C\u53EF\u7528 --product \u540C\u6B65\u63D0\u4EA4\u5546\u54C1\u5BA1\u6838
3350
+ products \u4E3A\u5DF2\u6709\u7248\u672C\u8865\u63D0\u5546\u54C1\uFF0C\u6216\u6062\u590D\u539F\u63D0\u5BA1\u8BF7\u6C42
3351
+ release \u4ECE\u660E\u786E\u56DE\u6267\u53D1\u5E03\uFF0C\u67E5\u8BE2\u3001\u6062\u590D\u3001\u91CD\u8BD5\u6216\u53D6\u6D88\u53D1\u5E03
3349
3352
  status \u67E5\u770B\u4E91\u7AEF\u7248\u672C\u3001\u8FD0\u884C\u3001\u5BA1\u6838\u548C\u6784\u5EFA\u72B6\u6001
3350
3353
  meta \u67E5\u770B\u4E91\u7AEF\u8D44\u6599\uFF1Bmeta update \u4FEE\u6539\u8D44\u6599\u6216\u66FF\u6362\u5934\u50CF
3351
3354
  avatar \u65E7\u5934\u50CF\u547D\u4EE4\u517C\u5BB9\u5165\u53E3\uFF0C\u63A8\u8350 meta update --avatar
@@ -3491,16 +3494,16 @@ var NodeAgentProcessLauncher = class {
3491
3494
  }
3492
3495
  let hasExited = false;
3493
3496
  let spawned = false;
3494
- const exit = new Promise((resolve19) => {
3497
+ const exit = new Promise((resolve20) => {
3495
3498
  child.once("error", (error2) => {
3496
3499
  if (!spawned) {
3497
3500
  hasExited = true;
3498
- resolve19({ code: null, signal: null, error: error2 });
3501
+ resolve20({ code: null, signal: null, error: error2 });
3499
3502
  }
3500
3503
  });
3501
3504
  child.once("exit", (code2, signal) => {
3502
3505
  hasExited = true;
3503
- resolve19({ code: code2, signal });
3506
+ resolve20({ code: code2, signal });
3504
3507
  });
3505
3508
  });
3506
3509
  child.stdout?.setEncoding("utf8");
@@ -3518,11 +3521,11 @@ var NodeAgentProcessLauncher = class {
3518
3521
  }
3519
3522
  });
3520
3523
  try {
3521
- await new Promise((resolve19, reject) => {
3524
+ await new Promise((resolve20, reject) => {
3522
3525
  const onSpawn = () => {
3523
3526
  spawned = true;
3524
3527
  child.off("error", onError);
3525
- resolve19();
3528
+ resolve20();
3526
3529
  };
3527
3530
  const onError = (error2) => {
3528
3531
  child.off("spawn", onSpawn);
@@ -3561,11 +3564,11 @@ var NodeAgentProcessLauncher = class {
3561
3564
  };
3562
3565
  function waitForExit(process2, timeoutMs) {
3563
3566
  if (process2.hasExited()) return Promise.resolve(true);
3564
- return new Promise((resolve19) => {
3565
- const timeout = setTimeout(() => resolve19(false), timeoutMs);
3567
+ return new Promise((resolve20) => {
3568
+ const timeout = setTimeout(() => resolve20(false), timeoutMs);
3566
3569
  process2.exit.then(() => {
3567
3570
  clearTimeout(timeout);
3568
- resolve19(true);
3571
+ resolve20(true);
3569
3572
  });
3570
3573
  });
3571
3574
  }
@@ -3648,7 +3651,7 @@ async function waitForGroupExit(pid, isGroupAlive, timeoutMs) {
3648
3651
  while (isGroupAlive(pid)) {
3649
3652
  const remaining = deadline - Date.now();
3650
3653
  if (remaining <= 0) return false;
3651
- await new Promise((resolve19) => setTimeout(resolve19, Math.min(25, remaining)));
3654
+ await new Promise((resolve20) => setTimeout(resolve20, Math.min(25, remaining)));
3652
3655
  }
3653
3656
  return true;
3654
3657
  }
@@ -3703,11 +3706,11 @@ async function acquireDevInstanceLock(options) {
3703
3706
  }
3704
3707
  }) : void 0;
3705
3708
  try {
3706
- if (server) await new Promise((resolve19, reject) => {
3709
+ if (server) await new Promise((resolve20, reject) => {
3707
3710
  server.once("error", reject);
3708
3711
  server.listen(0, "127.0.0.1", () => {
3709
3712
  server.off("error", reject);
3710
- resolve19();
3713
+ resolve20();
3711
3714
  });
3712
3715
  });
3713
3716
  const address = server?.address();
@@ -4437,25 +4440,25 @@ import { join as join18 } from "node:path";
4437
4440
  var DATA_ACCESS_FILENAME = "data-access.json";
4438
4441
  function parseDataAccessRequirements(source) {
4439
4442
  if (source === void 0) return [];
4440
- const invalid3 = (reason) => {
4443
+ const invalid4 = (reason) => {
4441
4444
  throw new Error(`${DATA_ACCESS_FILENAME}\uFF1A${reason}`);
4442
4445
  };
4443
4446
  let value;
4444
4447
  try {
4445
4448
  value = JSON.parse(source);
4446
4449
  } catch {
4447
- return invalid3("\u4E0D\u662F\u6709\u6548 JSON");
4450
+ return invalid4("\u4E0D\u662F\u6709\u6548 JSON");
4448
4451
  }
4449
4452
  if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => key !== "requirements") || !Array.isArray(value.requirements) || value.requirements.length > 32) {
4450
- return invalid3("\u5FC5\u987B\u662F\u4EC5\u5305\u542B requirements \u6570\u7EC4\u7684\u5BF9\u8C61\uFF0C\u6700\u591A\u58F0\u660E 32 \u9879");
4453
+ return invalid4("\u5FC5\u987B\u662F\u4EC5\u5305\u542B requirements \u6570\u7EC4\u7684\u5BF9\u8C61\uFF0C\u6700\u591A\u58F0\u660E 32 \u9879");
4451
4454
  }
4452
4455
  const seen = /* @__PURE__ */ new Set();
4453
4456
  return value.requirements.map((item, index) => {
4454
4457
  if (!item || typeof item !== "object" || Array.isArray(item) || Object.keys(item).some((key) => key !== "id" && key !== "purpose") || !("id" in item) || typeof item.id !== "string" || !item.id.trim() || !("purpose" in item) || typeof item.purpose !== "string" || !item.purpose.trim() || item.purpose.trim().length > 200) {
4455
- return invalid3(`requirements[${index}] \u5FC5\u987B\u5305\u542B\u975E\u7A7A id \u548C 1\u2013200 \u5B57\u7684 purpose`);
4458
+ return invalid4(`requirements[${index}] \u5FC5\u987B\u5305\u542B\u975E\u7A7A id \u548C 1\u2013200 \u5B57\u7684 purpose`);
4456
4459
  }
4457
4460
  const id = item.id.trim(), purpose = item.purpose.trim();
4458
- if (seen.has(id)) return invalid3(`\u6570\u636E\u96C6\u4E0D\u80FD\u91CD\u590D\u58F0\u660E\uFF1A${id}`);
4461
+ if (seen.has(id)) return invalid4(`\u6570\u636E\u96C6\u4E0D\u80FD\u91CD\u590D\u58F0\u660E\uFF1A${id}`);
4459
4462
  seen.add(id);
4460
4463
  return { id, purpose };
4461
4464
  });
@@ -4987,18 +4990,18 @@ function parse(source) {
4987
4990
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
4988
4991
  throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4989
4992
  }
4990
- const record2 = value;
4991
- if (Object.keys(record2).length !== 3 || typeof record2.accessToken !== "string" || typeof record2.subject !== "string" || !Number.isSafeInteger(record2.expiresAt)) {
4993
+ const record3 = value;
4994
+ if (Object.keys(record3).length !== 3 || typeof record3.accessToken !== "string" || typeof record3.subject !== "string" || !Number.isSafeInteger(record3.expiresAt)) {
4992
4995
  throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4993
4996
  }
4994
4997
  return Object.freeze({
4995
- accessToken: record2.accessToken,
4996
- subject: record2.subject,
4997
- expiresAt: record2.expiresAt
4998
+ accessToken: record3.accessToken,
4999
+ subject: record3.subject,
5000
+ expiresAt: record3.expiresAt
4998
5001
  });
4999
5002
  }
5000
5003
  async function runCredentialCommand(input) {
5001
- return await new Promise((resolve19, reject) => {
5004
+ return await new Promise((resolve20, reject) => {
5002
5005
  const child = spawn2(input.command, [...input.args], {
5003
5006
  shell: false,
5004
5007
  windowsHide: true,
@@ -5014,7 +5017,7 @@ async function runCredentialCommand(input) {
5014
5017
  child.stdout.on("data", (chunk) => collect(stdout, chunk));
5015
5018
  child.stderr.on("data", (chunk) => collect(stderr, chunk));
5016
5019
  child.once("error", reject);
5017
- child.once("close", (code2) => resolve19({
5020
+ child.once("close", (code2) => resolve20({
5018
5021
  code: code2 ?? 1,
5019
5022
  stdout: Buffer.concat(stdout).toString("utf8"),
5020
5023
  stderr: Buffer.concat(stderr).toString("utf8")
@@ -5303,9 +5306,424 @@ async function runDevCommand(args, io, options = {}) {
5303
5306
  }
5304
5307
  }
5305
5308
 
5306
- // packages/cli-core/src/commands/cloud.ts
5309
+ // packages/cli-core/src/commands/cloud-errors.ts
5310
+ var CloudCommandUsageError = class extends Error {
5311
+ constructor(message) {
5312
+ super(message);
5313
+ this.name = "CloudCommandUsageError";
5314
+ }
5315
+ };
5316
+
5317
+ // packages/cli-core/src/commands/product-lifecycle.ts
5318
+ import { createHash as createHash10, randomUUID as randomUUID9 } from "node:crypto";
5319
+ import { resolve as resolve15 } from "node:path";
5307
5320
  import { setTimeout as delay3 } from "node:timers/promises";
5308
5321
 
5322
+ // packages/cli-core/src/cloud/product-protocol.ts
5323
+ function invalid2(message) {
5324
+ throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", message);
5325
+ }
5326
+ function record(value) {
5327
+ if (!value || typeof value !== "object" || Array.isArray(value)) invalid2("\u64CD\u4F5C\u56DE\u6267\u5FC5\u987B\u4E3A\u5BF9\u8C61");
5328
+ return value;
5329
+ }
5330
+ function isProductId(value) {
5331
+ return typeof value === "string" && /^(?:prd_[0-9]{8}|ps_[A-Za-z0-9_-]{1,61})$/u.exec(value)?.[0] === value;
5332
+ }
5333
+ function operationId(value) {
5334
+ if (typeof value !== "string" || !/^[A-Za-z0-9_-]{1,128}$/.test(value)) invalid2("\u64CD\u4F5C\u56DE\u6267\u6807\u8BC6\u65E0\u6548");
5335
+ return value;
5336
+ }
5337
+ function selectedReviewIds(value) {
5338
+ if (!Array.isArray(value) || value.length > 10 || value.some((id) => typeof id !== "string" || !/^pr_[A-Za-z0-9_-]{1,61}$/.test(id)) || new Set(value).size !== value.length) invalid2("\u5546\u54C1\u5BA1\u6838\u56DE\u6267\u96C6\u5408\u65E0\u6548");
5339
+ return value;
5340
+ }
5341
+ function parsePushMetadata(value) {
5342
+ const m = record(value);
5343
+ if (typeof m.commit !== "string" || !m.commit.trim() || m.commit.length > 2e3 || /[\u0000-\u001f\u007f]/u.test(m.commit) || typeof m.sourceSha256 !== "string" || !/^[a-f0-9]{64}$/.test(m.sourceSha256) || !Array.isArray(m.productReviews) || m.productReviews.length > 10) invalid2("\u4E0A\u4F20\u5143\u6570\u636E\u56DE\u6267\u65E0\u6548");
5344
+ const productReviews = m.productReviews.map((value2) => {
5345
+ const r = record(value2);
5346
+ if (!isProductId(r.productId) || !Number.isSafeInteger(r.expectedDraftVersion) || Number(r.expectedDraftVersion) < 1) invalid2("\u5546\u54C1\u8349\u7A3F\u7248\u672C\u56DE\u6267\u65E0\u6548");
5347
+ return { productId: r.productId, reviewId: selectedReviewIds([r.reviewId])[0], expectedDraftVersion: Number(r.expectedDraftVersion) };
5348
+ });
5349
+ if (new Set(productReviews.map((r) => r.productId)).size !== productReviews.length || new Set(productReviews.map((r) => r.reviewId)).size !== productReviews.length) invalid2("\u56DE\u6267\u5305\u542B\u91CD\u590D\u5546\u54C1\u6216\u5BA1\u6838 ID");
5350
+ return { pushId: operationId(m.pushId), commit: m.commit, sourceSha256: m.sourceSha256, productReviews };
5351
+ }
5352
+ function parsePackagePush(value) {
5353
+ const p = record(value);
5354
+ const metadata = parsePushMetadata(p.metadata);
5355
+ if (!["receiving", "stored", "completed", "product_reviews_failed", "failed"].includes(String(p.status))) invalid2("\u4E0A\u4F20\u64CD\u4F5C\u72B6\u6001\u65E0\u6548");
5356
+ if (p.uploadVersion !== null && (typeof p.uploadVersion !== "string" || !p.uploadVersion.trim() || /[\u0000-\u001f\u007f]/u.test(p.uploadVersion))) invalid2("\u4E0A\u4F20\u7248\u672C\u56DE\u6267\u65E0\u6548");
5357
+ if (operationId(p.pushId) !== metadata.pushId) invalid2("\u4E0A\u4F20\u56DE\u6267 ID \u4E0E\u5143\u6570\u636E\u4E0D\u5339\u914D");
5358
+ return { pushId: metadata.pushId, uploadVersion: p.uploadVersion, status: p.status, metadata, reviewIds: selectedReviewIds(p.reviewIds), failure: p.failure ?? null };
5359
+ }
5360
+ function parseProductRelease(value) {
5361
+ const r = record(value);
5362
+ if (r.mode !== "with_buddy" && r.mode !== "products_only") invalid2("\u53D1\u5E03\u6A21\u5F0F\u65E0\u6548");
5363
+ if (!["accepted", "activating", "active", "failed", "cancelled"].includes(String(r.status))) invalid2("\u53D1\u5E03\u64CD\u4F5C\u72B6\u6001\u65E0\u6548");
5364
+ if (typeof r.buddyVersion !== "string" || !r.buddyVersion.trim() || /[\u0000-\u001f\u007f]/u.test(r.buddyVersion)) invalid2("\u53D1\u5E03\u7248\u672C\u65E0\u6548");
5365
+ return { releaseId: operationId(r.releaseId), mode: r.mode, buddyVersion: r.buddyVersion, reviewIds: selectedReviewIds(r.reviewIds), status: r.status, ...r.failure === void 0 ? {} : { failure: r.failure } };
5366
+ }
5367
+ var CloudOperationError = class extends CloudLifecycleError {
5368
+ constructor(code2, message, details, push, release) {
5369
+ super(code2, message, details);
5370
+ this.push = push;
5371
+ this.release = release;
5372
+ }
5373
+ push;
5374
+ release;
5375
+ };
5376
+ function sameReviewIds(a, b) {
5377
+ return [...a].sort().join("\0") === [...b].sort().join("\0");
5378
+ }
5379
+ function samePushMetadata(a, b) {
5380
+ return a.pushId === b.pushId && a.commit === b.commit && a.sourceSha256 === b.sourceSha256 && JSON.stringify([...a.productReviews].sort((x, y) => x.productId.localeCompare(y.productId))) === JSON.stringify([...b.productReviews].sort((x, y) => x.productId.localeCompare(y.productId)));
5381
+ }
5382
+
5383
+ // packages/cli-core/src/cloud/operation-store.ts
5384
+ import { createHash as createHash9, randomUUID as randomUUID8 } from "node:crypto";
5385
+ import { mkdir as mkdir9, readFile as readFile19, rename as rename10, writeFile as writeFile8, chmod } from "node:fs/promises";
5386
+ import { homedir as homedir4 } from "node:os";
5387
+ import { join as join20 } from "node:path";
5388
+ var OperationStore = class {
5389
+ constructor(identity, base = join20(homedir4(), ".cache", "buddy-cli", "operations")) {
5390
+ this.identity = identity;
5391
+ this.directory = join20(base, createHash9("sha256").update(JSON.stringify(identity)).digest("hex"));
5392
+ }
5393
+ identity;
5394
+ directory;
5395
+ async ready() {
5396
+ await mkdir9(this.directory, { recursive: true, mode: 448 });
5397
+ await chmod(this.directory, 448);
5398
+ }
5399
+ path(id, suffix = "json") {
5400
+ return join20(this.directory, `${operationId(id)}.${suffix}`);
5401
+ }
5402
+ async create(record3, bytes) {
5403
+ await this.ready();
5404
+ if (record3.kind === "push") {
5405
+ if (!bytes || createHash9("sha256").update(bytes).digest("hex") !== record3.metadata.sourceSha256) throw new CloudLifecycleError("INVALID_REQUEST", "\u4FDD\u5B58\u4E0A\u4F20\u8BB0\u5F55\u65F6\u5305\u5185\u5BB9\u6821\u9A8C\u5931\u8D25");
5406
+ await writeFile8(this.path(record3.id, "tar.gz"), bytes, { flag: "wx", mode: 384 });
5407
+ }
5408
+ await writeFile8(this.path(record3.id), JSON.stringify({ identity: this.identity, operation: record3 }), { flag: "wx", mode: 384 });
5409
+ }
5410
+ async save(record3) {
5411
+ const prior = await this.read(record3.id, record3.kind);
5412
+ const input = (r) => r.kind === "push" ? r.metadata : r.kind === "release" ? r.request : { version: r.version, reviews: r.reviews };
5413
+ if (JSON.stringify(input(prior)) !== JSON.stringify(input(record3))) throw new CloudLifecycleError("INVALID_REQUEST", "\u6062\u590D\u8BB0\u5F55\u7684\u539F\u59CB\u8BF7\u6C42\u4E0D\u80FD\u66F4\u6539");
5414
+ const temporary = this.path(`${record3.id}_${randomUUID8()}`);
5415
+ await writeFile8(temporary, JSON.stringify({ identity: this.identity, operation: record3 }), { flag: "wx", mode: 384 });
5416
+ await rename10(temporary, this.path(record3.id));
5417
+ }
5418
+ async read(id, kind) {
5419
+ try {
5420
+ const value = JSON.parse(await readFile19(this.path(id), "utf8"));
5421
+ const r = value.operation;
5422
+ if (JSON.stringify(value.identity) !== JSON.stringify(this.identity) || r.kind !== kind || r.id !== id) throw new Error("identity mismatch");
5423
+ if (r.kind === "push") {
5424
+ parsePushMetadata(r.metadata);
5425
+ if (r.metadata.pushId !== id) throw new Error("push mismatch");
5426
+ if (r.receipt) parsePackagePush(r.receipt);
5427
+ }
5428
+ if (r.kind === "release") {
5429
+ parseProductRelease({ ...r.request, status: "accepted" });
5430
+ if (r.request.releaseId !== id) throw new Error("release mismatch");
5431
+ if (r.receipt) parseProductRelease(r.receipt);
5432
+ }
5433
+ if (r.kind === "submission") {
5434
+ if (typeof r.version !== "string" || !r.version.trim() || typeof r.confirmed !== "boolean" || r.reviews.length === 0) throw new Error("submission invalid");
5435
+ parsePushMetadata({ pushId: id, commit: "validate", sourceSha256: "0".repeat(64), productReviews: r.reviews });
5436
+ }
5437
+ return r;
5438
+ } catch {
5439
+ throw new CloudLifecycleError("INVALID_REQUEST", `\u627E\u4E0D\u5230\u5F53\u524D\u5E73\u53F0\u3001\u8D26\u53F7\u548C\u642D\u5B50\u7684\u6709\u6548 ${kind} \u6062\u590D\u8BB0\u5F55\uFF1A${id}\uFF1B\u4E0D\u80FD\u66F4\u6362\u5185\u5BB9\u540E\u91CD\u7528\u6B64 ID`);
5440
+ }
5441
+ }
5442
+ async archive(record3) {
5443
+ try {
5444
+ const bytes = await readFile19(this.path(record3.id, "tar.gz"));
5445
+ if (createHash9("sha256").update(bytes).digest("hex") !== record3.metadata.sourceSha256) throw new Error("hash mismatch");
5446
+ return { ...record3.bundle, mediaType: "application/gzip", bytes };
5447
+ } catch {
5448
+ throw new CloudLifecycleError("INVALID_REQUEST", "\u6062\u590D\u7528\u7684\u539F\u59CB\u4EE3\u7801\u5305\u7F3A\u5931\u6216\u88AB\u4FEE\u6539\uFF1B\u4E3A\u907F\u514D\u5185\u5BB9\u6F02\u79FB\uFF0C\u5DF2\u505C\u6B62\u91CD\u8BD5");
5449
+ }
5450
+ }
5451
+ };
5452
+
5453
+ // packages/cli-core/src/commands/product-lifecycle.ts
5454
+ var PRODUCT_HELP = {
5455
+ push: `\u7528\u6CD5: buddy-cli push --commit <\u6539\u52A8\u8BF4\u660E> [--product <\u5546\u54C1 ID> ...] [--directory <\u76EE\u5F55>]
5456
+ buddy-cli push --resume <pushId> | --status <pushId> [--directory <\u76EE\u5F55>]
5457
+ \u4E0A\u4F20\u4EE3\u7801\u5E76\u63D0\u4EA4\u660E\u786E\u9009\u4E2D\u7684\u5546\u54C1\uFF1B\u4E0D\u6307\u5B9A --product \u53EA\u4E0A\u4F20\u4EE3\u7801\u3002\u4E0D\u4F1A\u81EA\u52A8\u53D1\u5E03\u3002
5458
+ \u5546\u54C1 ID \u793A\u4F8B\uFF1Aprd_12345678\uFF1B\u5DF2\u6709 ps_ \u5546\u54C1 ID \u7EE7\u7EED\u517C\u5BB9\u3002
5459
+ \u9996\u6B21\u4E0A\u4F20\u5FC5\u987B\u5B89\u88C5 npm latest \u6700\u65B0\u7A33\u5B9A Runtime \u7684\u51C6\u786E\u7248\u672C\uFF1B\u91CD\u8BD5\u56FA\u5B9A\u4F7F\u7528\u539F\u59CB\u5305\u3001\u8349\u7A3F\u7248\u672C\u548C\u5BA1\u6838 ID\u3002
5460
+ \u7F51\u7EDC\u7ED3\u679C\u672A\u77E5\u65F6\u8BF7\u4F7F\u7528\u8F93\u51FA\u7684 --resume\uFF1B--status \u53EA\u67E5\u8BE2\u3002\u4E0D\u8981\u91CD\u65B0\u4E0A\u4F20\u3002`,
5461
+ products: `\u7528\u6CD5: buddy-cli products submit --version <\u5DF2\u4E0A\u4F20\u6216\u5F53\u524D\u53D1\u5E03\u7248\u672C> --product <\u5546\u54C1 ID> [--product <\u5546\u54C1 ID> ...] [--directory <\u76EE\u5F55>]
5462
+ buddy-cli products submit --resume <submissionId> [--directory <\u76EE\u5F55>]
5463
+ \u7528\u4E8E\u5DF2\u4E0A\u4F20\u7248\u672C\u8865\u63D0\u5546\u54C1\uFF1B\u6B63\u5E38 push --product \u5DF2\u81EA\u52A8\u63D0\u5BA1\uFF0C\u65E0\u9700\u91CD\u590D\u6267\u884C\u3002
5464
+ \u5546\u54C1 ID \u793A\u4F8B\uFF1Aprd_12345678\uFF1B\u5DF2\u6709 ps_ \u5546\u54C1 ID \u7EE7\u7EED\u517C\u5BB9\u3002
5465
+ \u6062\u590D\u4F7F\u7528\u9996\u6B21\u6301\u4E45\u4FDD\u5B58\u7684\u5546\u54C1\u96C6\u5408\u3001\u5BA1\u6838 ID \u548C\u8349\u7A3F\u7248\u672C\u3002`,
5466
+ release: `\u7528\u6CD5: buddy-cli release (--from-push <pushId> | --from-submission <submissionId>) [--products-only] [--directory <\u76EE\u5F55>]
5467
+ buddy-cli release --version <\u7248\u672C> --code-only [--directory <\u76EE\u5F55>]
5468
+ buddy-cli release (--resume | --status | --retry | --cancel) <releaseId> [--directory <\u76EE\u5F55>]
5469
+ \u53D1\u5E03\u53EA\u91C7\u7528\u6307\u5B9A\u6210\u529F\u56DE\u6267\u4E2D\u7684\u5BA1\u6838\u96C6\u5408\uFF1B\u5546\u54C1\u5931\u8D25\u4E0D\u4F1A\u81EA\u52A8\u964D\u7EA7\u4E3A\u7EAF\u4EE3\u7801\u53D1\u5E03\u3002
5470
+ \u9ED8\u8BA4\u968F\u642D\u5B50\u7248\u672C\u4E00\u8D77\u53D1\u5E03\uFF1B--products-only \u53EA\u6FC0\u6D3B\u5546\u54C1\u5E76\u6838\u5BF9\u5F53\u524D\u7EBF\u4E0A\u7248\u672C\u3002
5471
+ \u4EC5 active \u8868\u793A\u5DF2\u751F\u6548\uFF1Baccepted/activating \u8BF7\u7528 --status \u67E5\u8BE2\u3002`
5472
+ };
5473
+ function parse2(command, args) {
5474
+ if (command === "products") {
5475
+ if (args[0] !== "submit") throw new CloudCommandUsageError(PRODUCT_HELP.products);
5476
+ args = args.slice(1);
5477
+ }
5478
+ const values = /* @__PURE__ */ new Map();
5479
+ const products = [];
5480
+ const allowed = command === "push" ? ["--commit", "--resume", "--status", "--product"] : command === "products" ? ["--version", "--resume", "--product"] : ["--from-push", "--from-submission", "--version", "--code-only", "--products-only", "--resume", "--status", "--retry", "--cancel"];
5481
+ for (let i = 0; i < args.length; i++) {
5482
+ const flag2 = args[i];
5483
+ if (flag2 !== "--directory" && !allowed.includes(flag2)) throw new CloudCommandUsageError(`\u672A\u77E5\u53C2\u6570 ${flag2}`);
5484
+ if (flag2 !== "--product" && values.has(flag2)) throw new CloudCommandUsageError(`${flag2} \u4E0D\u80FD\u91CD\u590D`);
5485
+ if (["--code-only", "--products-only"].includes(flag2)) {
5486
+ values.set(flag2, "true");
5487
+ continue;
5488
+ }
5489
+ const value = args[++i];
5490
+ if (!value?.trim() || value.startsWith("--") || /[\u0000-\u001f\u007f]/u.test(value)) throw new CloudCommandUsageError(`${flag2} \u7F3A\u5C11\u6709\u6548\u503C`);
5491
+ if (flag2 === "--product") {
5492
+ if (!isProductId(value) || products.includes(value)) throw new CloudCommandUsageError("\u5546\u54C1 ID \u65E0\u6548\u6216\u91CD\u590D");
5493
+ products.push(value);
5494
+ } else values.set(flag2, value.trim());
5495
+ }
5496
+ if (products.length > 10) throw new CloudCommandUsageError("\u4E00\u6B21\u6700\u591A\u9009\u62E9 10 \u4E2A\u5546\u54C1");
5497
+ const recovery = ["--resume", "--status", "--retry", "--cancel"].filter((f) => values.has(f));
5498
+ if (recovery.length && (recovery.length !== 1 || products.length || [...values.keys()].some((f) => f !== "--directory" && !recovery.includes(f)))) throw new CloudCommandUsageError("\u6062\u590D\u6216\u67E5\u8BE2\u547D\u4EE4\u4E0D\u80FD\u540C\u65F6\u66F4\u6539\u539F\u59CB\u8BF7\u6C42");
5499
+ return { values, products };
5500
+ }
5501
+ function required(value) {
5502
+ if (!value) throw new CloudCommandUsageError("\u5E73\u53F0 Adapter \u5C1A\u672A\u652F\u6301\u5546\u54C1\u4E0A\u4F20\u548C\u53D1\u5E03\u534F\u8BAE\uFF0C\u8BF7\u5347\u7EA7 Adapter");
5503
+ return value;
5504
+ }
5505
+ function responseError(message) {
5506
+ throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", message);
5507
+ }
5508
+ async function selection(client, id, products, io) {
5509
+ const reviews = [];
5510
+ const labels = [];
5511
+ for (const productId of products) {
5512
+ const product = await required(client.getProductForSubmission).call(client, { id, productId });
5513
+ if (product.productId !== productId || product.buddyId !== id || !Number.isSafeInteger(product.draftVersion) || product.draftVersion < 1) responseError("\u5546\u54C1\u8EAB\u4EFD\u6216\u8349\u7A3F\u7248\u672C\u65E0\u6548");
5514
+ reviews.push({ productId, reviewId: `pr_${randomUUID9()}`, expectedDraftVersion: product.draftVersion });
5515
+ labels.push({ productId, name: product.name });
5516
+ io.write(`\u9009\u62E9\u5546\u54C1\uFF1A${product.name ?? productId}\uFF08${productId}\uFF09\uFF0C\u8349\u7A3F\u7248\u672C ${product.draftVersion}`);
5517
+ }
5518
+ return { reviews, labels };
5519
+ }
5520
+ function confirmPush(record3, push) {
5521
+ if (!samePushMetadata(record3.metadata, push.metadata) || push.pushId !== record3.id) responseError("\u670D\u52A1\u5668\u4E0A\u4F20\u56DE\u6267\u4E0E\u539F\u59CB\u8BF7\u6C42\u4E0D\u4E00\u81F4");
5522
+ if (push.status === "completed" && (!push.uploadVersion || !sameReviewIds(push.reviewIds, record3.metadata.productReviews.map((r) => r.reviewId)))) responseError("\u670D\u52A1\u5668\u672A\u786E\u8BA4\u5B8C\u6574\u5546\u54C1\u5BA1\u6838\u96C6\u5408");
5523
+ }
5524
+ function failureMessage(value) {
5525
+ if (!value || typeof value !== "object") return void 0;
5526
+ const detail = value;
5527
+ const code2 = typeof detail.code === "string" ? detail.code : void 0;
5528
+ const message = typeof detail.message === "string" ? detail.message : void 0;
5529
+ return [code2, message].filter(Boolean).join(" \xB7 ") || void 0;
5530
+ }
5531
+ function showPush(io, push) {
5532
+ io.write(`\u4E0A\u4F20\u7F16\u53F7\uFF1A${push.pushId}`);
5533
+ if (push.uploadVersion) io.write(`\u4E0A\u4F20\u7248\u672C\uFF1A${push.uploadVersion}`);
5534
+ io.write(`\u4E0A\u4F20\u72B6\u6001\uFF1A${push.status}`);
5535
+ if (failureMessage(push.failure)) io.writeError(`\u539F\u56E0\uFF1A${failureMessage(push.failure)}`);
5536
+ if (push.reviewIds.length) io.write(`\u5546\u54C1\u5BA1\u6838\u7F16\u53F7\uFF1A${push.reviewIds.join(", ")}`);
5537
+ if (push.status === "completed") {
5538
+ io.write(`\u672C\u6B21 push \u4E0D\u4F1A\u53D1\u5E03\u642D\u5B50\uFF1B\u786E\u8BA4\u4EE3\u7801\u53CA\u6240\u9009\u5546\u54C1\u5BA1\u6838\u7ED3\u679C\u540E\u4F7F\u7528 buddy-cli release --from-push ${push.pushId}\u3002`);
5539
+ return 0;
5540
+ }
5541
+ if (push.status === "product_reviews_failed") io.writeError(`\u4EE3\u7801\u5305\u5DF2\u4FDD\u5B58\uFF0C\u5546\u54C1\u672A\u5B8C\u6574\u63D0\u5BA1\u3002\u4FEE\u6B63\u5546\u54C1\u540E\u4F7F\u7528 products submit --version ${push.uploadVersion} --product <\u5546\u54C1 ID> \u8865\u63D0\uFF1B\u7EAF\u4EE3\u7801\u53D1\u5E03\u987B\u660E\u786E --code-only\u3002`);
5542
+ else io.writeError(`\u4E0A\u4F20\u672A\u5B8C\u6210\uFF0C\u4F7F\u7528 buddy-cli push --resume ${push.pushId} \u6062\u590D\u539F\u8BF7\u6C42\u3002`);
5543
+ return 1;
5544
+ }
5545
+ async function executePush(record3, sourceBundle, store, client, id, io, options) {
5546
+ try {
5547
+ const receipt = await client.pushPackage({ id, commit: record3.metadata.commit, metadata: record3.metadata, sourceBundle });
5548
+ const push = required(receipt.push);
5549
+ confirmPush(record3, push);
5550
+ await store.save({ ...record3, receipt: push });
5551
+ let exitCode = showPush(io, push);
5552
+ io.write(`commit\uFF1A${receipt.commit}`);
5553
+ io.write(`\u5BA1\u6838\u72B6\u6001\uFF1A${{ auditing: "\u5BA1\u6838\u4E2D", approved: "\u5DF2\u901A\u8FC7", rejected: "\u672A\u901A\u8FC7" }[receipt.auditStatus]}`);
5554
+ if (receipt.buildStatus && client.getPackageBuild && exitCode === 0) {
5555
+ let build = { buildStatus: receipt.buildStatus, buildError: receipt.buildError ?? null };
5556
+ const deadline = Date.now() + (options.buildWaitMs ?? 6e4);
5557
+ try {
5558
+ while (build.buildStatus === "building" && Date.now() < deadline) {
5559
+ await delay3(Math.min(options.buildPollMs ?? 2e3, Math.max(1, deadline - Date.now())), void 0, { signal: options.signal });
5560
+ build = await client.getPackageBuild({ id, version: receipt.version });
5561
+ }
5562
+ io.write(`\u6784\u5EFA\uFF1A${{ building: "\u6784\u5EFA\u4E2D", ready: "\u6784\u5EFA\u5B8C\u6210", failed: "\u6784\u5EFA\u5931\u8D25" }[build.buildStatus]}${build.buildError ? ` \xB7 ${build.buildError}` : ""}`);
5563
+ if (build.buildStatus === "failed") exitCode = 1;
5564
+ if (build.buildStatus === "building") io.write("\u6784\u5EFA\u4ECD\u5728\u8FDB\u884C\uFF0C\u7A0D\u540E\u8FD0\u884C buddy-cli status \u67E5\u8BE2\uFF1B\u4E0D\u8981\u91CD\u590D\u4E0A\u4F20\u3002");
5565
+ } catch (cause) {
5566
+ io.writeError(`\u4EE3\u7801\u5DF2\u4E0A\u4F20\uFF0C\u4F46\u6784\u5EFA\u72B6\u6001\u5C1A\u672A\u786E\u8BA4\uFF1A${cause instanceof Error ? cause.message : "\u7F51\u7EDC\u9519\u8BEF"}\u3002\u7528 buddy-cli status \u91CD\u67E5\uFF0C\u4E0D\u8981\u91CD\u590D\u4E0A\u4F20\u3002`);
5567
+ return { exitCode: 1, buddyId: id, version: receipt.version };
5568
+ }
5569
+ }
5570
+ return { exitCode, buddyId: id, version: receipt.version };
5571
+ } catch (cause) {
5572
+ if (cause instanceof CloudOperationError && cause.push) {
5573
+ confirmPush(record3, cause.push);
5574
+ await store.save({ ...record3, receipt: cause.push });
5575
+ showPush(io, cause.push);
5576
+ }
5577
+ io.writeError(`\u4E0A\u4F20\u7ED3\u679C\u9700\u786E\u8BA4\u3002\u6062\u590D\u547D\u4EE4\uFF1Abuddy-cli push --resume ${record3.id}`);
5578
+ throw cause;
5579
+ }
5580
+ }
5581
+ function matchRelease(request, release) {
5582
+ if (request.releaseId !== release.releaseId || request.mode !== release.mode || request.buddyVersion !== release.buddyVersion || !sameReviewIds(request.reviewIds, release.reviewIds)) responseError("\u53D1\u5E03\u56DE\u6267\u4E0E\u56FA\u5B9A\u8BF7\u6C42\u4E0D\u4E00\u81F4");
5583
+ }
5584
+ function showRelease(io, release) {
5585
+ io.write(`\u53D1\u5E03\u7F16\u53F7\uFF1A${release.releaseId}`);
5586
+ io.write(`\u53D1\u5E03\u72B6\u6001\uFF1A${release.status}`);
5587
+ io.write(`\u76EE\u6807\u7248\u672C\uFF1A${release.buddyVersion}`);
5588
+ if (failureMessage(release.failure)) io.writeError(`\u539F\u56E0\uFF1A${failureMessage(release.failure)}`);
5589
+ if (release.status === "active") {
5590
+ io.write("\u53D1\u5E03\u5DF2\u751F\u6548\u3002");
5591
+ return 0;
5592
+ }
5593
+ if (release.status === "failed") io.writeError(`\u53D1\u5E03\u672A\u751F\u6548\u3002\u4FEE\u6B63\u539F\u56E0\u540E buddy-cli release --retry ${release.releaseId}\uFF1B\u653E\u5F03\u5219 --cancel ${release.releaseId}\u3002`);
5594
+ else if (release.status === "cancelled") io.write("\u8BE5\u53D1\u5E03\u5DF2\u53D6\u6D88\u3002");
5595
+ else io.write(`\u53D1\u5E03\u4ECD\u5728\u5904\u7406\uFF0C\u8BF7\u8FD0\u884C buddy-cli release --status ${release.releaseId} \u786E\u8BA4\u662F\u5426\u751F\u6548\u3002`);
5596
+ return 1;
5597
+ }
5598
+ async function runProductLifecycle(command, args, io, options) {
5599
+ if (args.length === 1 && ["--help", "-h"].includes(args[0]) || command === "products" && args.length === 2 && args[0] === "submit" && args[1] === "--help") {
5600
+ io.write(PRODUCT_HELP[command]);
5601
+ return { exitCode: 0 };
5602
+ }
5603
+ const p = parse2(command, args);
5604
+ const v = p.values;
5605
+ if (options.mode === "local-mock") throw new CloudCommandUsageError("\u672C\u5730\u6A21\u62DF\u6A21\u5F0F\u4E0D\u4F1A\u4F2A\u9020\u6B63\u5F0F push \u6216\u53D1\u5E03\uFF0C\u8BF7\u8FDE\u63A5\u771F\u5B9E MLB Server");
5606
+ const freshPush = command === "push" && !v.has("--resume") && !v.has("--status");
5607
+ const root = await (options.resolveProjectRoot ?? (freshPush ? requireBuddyAgentProjectRoot : requireBuddyProjectRoot))(resolve15(options.cwd ?? process.cwd(), v.get("--directory") ?? "."));
5608
+ const platform = resolvePlatformUrl({ env: options.runtimeUpdate?.env });
5609
+ await checkProjectGateway(root, platform);
5610
+ const config = freshPush ? await (options.readConfig ?? readBuddyConfig)(root) : await (options.readManifest ?? readBuddyProjectManifest)(root);
5611
+ const id = config.buddyId;
5612
+ if (!id) throw new CloudCommandUsageError("\u5F53\u524D\u9879\u76EE\u7F3A\u5C11\u5E73\u53F0\u751F\u6210\u7684 buddyId\uFF0C\u8BF7\u5148\u8FD0\u884C buddy-cli init");
5613
+ const client = required(options.client);
5614
+ const session = required(options.session);
5615
+ let commit = v.get("--commit");
5616
+ if (freshPush && !commit) {
5617
+ if (!io.canPrompt || !io.input) throw new CloudCommandUsageError("\u7F3A\u5C11 --commit\uFF1B\u8BF7\u8BF4\u660E\u672C\u6B21\u63D0\u4EA4\u5BA1\u6838\u7684\u6539\u52A8\u5185\u5BB9");
5618
+ while (!commit) commit = (await io.input("\u8BF7\u8BF4\u660E\u672C\u6B21\u63D0\u4EA4\u5BA1\u6838\u7684\u6539\u52A8\u5185\u5BB9")).trim();
5619
+ }
5620
+ if (commit && (commit.length > 2e3 || /[\u0000-\u001f\u007f]/u.test(commit))) throw new CloudCommandUsageError("--commit \u987B\u4E0D\u8D85\u8FC7 2000 \u5B57\u4E14\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26");
5621
+ const runtime = freshPush ? await requireProjectRuntime(root, { ...options.runtimeUpdate, signal: options.signal }) : void 0;
5622
+ const token = await session.token({ signal: options.signal });
5623
+ const store = new OperationStore({ platform: platform.toString(), subject: token.subject, buddyId: id }, options.operationCacheDirectory);
5624
+ if (command === "push") {
5625
+ const statusId = v.get("--status");
5626
+ if (statusId) {
5627
+ const push = await required(client.getPackagePush).call(client, { id, pushId: statusId });
5628
+ if (push.pushId !== statusId) responseError("\u4E0A\u4F20\u7F16\u53F7\u4E0D\u5339\u914D");
5629
+ return { exitCode: showPush(io, push), buddyId: id, ...push.uploadVersion ? { version: push.uploadVersion } : {} };
5630
+ }
5631
+ const resume = v.get("--resume");
5632
+ if (resume) {
5633
+ const record5 = await store.read(resume, "push");
5634
+ return executePush(record5, await store.archive(record5), store, client, id, io, options);
5635
+ }
5636
+ const bundle = await required(options.preparePush)(root, config, runtime);
5637
+ for (const warning2 of bundle.warnings ?? []) io.writeError(`\u6253\u5305\u63D0\u793A [${warning2.code}]\uFF1A${warning2.message}`);
5638
+ const chosen = await selection(client, id, p.products, io);
5639
+ const pushId = `pu_${randomUUID9()}`;
5640
+ const { bytes, ...bundleInfo } = bundle;
5641
+ const record4 = { kind: "push", id: pushId, metadata: { pushId, commit, sourceSha256: createHash10("sha256").update(bytes).digest("hex"), productReviews: chosen.reviews }, bundle: bundleInfo, products: chosen.labels };
5642
+ await store.create(record4, bytes);
5643
+ io.write(`\u6062\u590D\u7F16\u53F7\uFF1A${pushId}`);
5644
+ return executePush(record4, bundle, store, client, id, io, options);
5645
+ }
5646
+ if (command === "products") {
5647
+ let record4;
5648
+ if (v.has("--resume")) record4 = await store.read(v.get("--resume"), "submission");
5649
+ else {
5650
+ const version = v.get("--version");
5651
+ if (!version || !p.products.length) throw new CloudCommandUsageError(PRODUCT_HELP.products);
5652
+ const chosen = await selection(client, id, p.products, io);
5653
+ record4 = { kind: "submission", id: `sub_${randomUUID9()}`, version, reviews: chosen.reviews, confirmed: false };
5654
+ await store.create(record4);
5655
+ }
5656
+ io.write(`\u5546\u54C1\u63D0\u4EA4\u7F16\u53F7\uFF1A${record4.id}`);
5657
+ try {
5658
+ const receipt = await required(client.submitPackageProducts).call(client, { id, version: record4.version, reviews: record4.reviews });
5659
+ if (!sameReviewIds(receipt.reviewIds, record4.reviews.map((r) => r.reviewId))) responseError("\u5E73\u53F0\u672A\u786E\u8BA4\u5B8C\u6574\u5546\u54C1\u5BA1\u6838\u96C6\u5408");
5660
+ await store.save({ ...record4, confirmed: true });
5661
+ io.write(`\u5546\u54C1\u5DF2\u63D0\u4EA4\u5BA1\u6838\uFF1A${receipt.reviewIds.join(", ")}`);
5662
+ io.write(`\u5BA1\u6838\u901A\u8FC7\u540E\uFF1Abuddy-cli release --from-submission ${record4.id}`);
5663
+ return { exitCode: 0, buddyId: id, version: record4.version };
5664
+ } catch (cause) {
5665
+ io.writeError(`\u4FDD\u7559\u539F\u8BF7\u6C42\u91CD\u8BD5\uFF1Abuddy-cli products submit --resume ${record4.id}`);
5666
+ throw cause;
5667
+ }
5668
+ }
5669
+ const action = ["--resume", "--status", "--retry", "--cancel"].find((f) => v.has(f));
5670
+ let record3;
5671
+ if (action) {
5672
+ const releaseId = v.get(action);
5673
+ if (action === "--status") {
5674
+ const release = await required(client.getProductRelease).call(client, { id, releaseId });
5675
+ if (release.releaseId !== releaseId) responseError("\u53D1\u5E03\u7F16\u53F7\u4E0D\u5339\u914D");
5676
+ return { exitCode: showRelease(io, release), buddyId: id, version: release.buddyVersion };
5677
+ }
5678
+ record3 = await store.read(releaseId, "release");
5679
+ } else {
5680
+ const sources = ["--from-push", "--from-submission", "--version"].filter((f) => v.has(f));
5681
+ if (sources.length !== 1 || v.has("--code-only") !== v.has("--version") || v.has("--code-only") && v.has("--products-only")) throw new CloudCommandUsageError(PRODUCT_HELP.release);
5682
+ let version;
5683
+ let reviewIds;
5684
+ if (v.has("--from-push")) {
5685
+ const pushRecord = await store.read(v.get("--from-push"), "push");
5686
+ const receipt = await required(client.getPackagePush).call(client, { id, pushId: pushRecord.id });
5687
+ confirmPush(pushRecord, receipt);
5688
+ await store.save({ ...pushRecord, receipt });
5689
+ if (receipt.status !== "completed" || !receipt.uploadVersion) throw new CloudCommandUsageError("\u6307\u5B9A\u4E0A\u4F20\u5C1A\u672A\u5B8C\u6574\u63D0\u5BA1\uFF0C\u4E0D\u80FD\u81EA\u52A8\u7701\u7565\u5931\u8D25\u5546\u54C1\uFF1B\u8BF7\u8865\u63D0\u6216\u660E\u786E --version <\u7248\u672C> --code-only");
5690
+ version = receipt.uploadVersion;
5691
+ reviewIds = receipt.reviewIds;
5692
+ } else if (v.has("--from-submission")) {
5693
+ const submission = await store.read(v.get("--from-submission"), "submission");
5694
+ if (!submission.confirmed) throw new CloudCommandUsageError(`\u8865\u63D0\u7ED3\u679C\u5C1A\u672A\u786E\u8BA4\uFF0C\u8BF7\u5148 products submit --resume ${submission.id}`);
5695
+ version = submission.version;
5696
+ reviewIds = submission.reviews.map((r) => r.reviewId);
5697
+ } else {
5698
+ version = v.get("--version");
5699
+ reviewIds = [];
5700
+ }
5701
+ if (v.has("--products-only")) {
5702
+ if (!reviewIds.length) throw new CloudCommandUsageError("--products-only \u9700\u8981\u660E\u786E\u7684\u5546\u54C1\u5BA1\u6838\u96C6\u5408");
5703
+ const buddy2 = await client.getBuddy({ id });
5704
+ if (buddy2.id !== id || !buddy2.released || buddy2.version !== version) throw new CloudCommandUsageError("\u4EC5\u5546\u54C1\u53D1\u5E03\u8981\u6C42\u56DE\u6267\u7248\u672C\u4E0E\u5F53\u524D\u5DF2\u53D1\u5E03\u642D\u5B50\u7248\u672C\u4E00\u81F4");
5705
+ }
5706
+ const releaseId = `rel_${randomUUID9()}`;
5707
+ record3 = { kind: "release", id: releaseId, request: { releaseId, mode: v.has("--products-only") ? "products_only" : "with_buddy", buddyVersion: version, reviewIds } };
5708
+ await store.create(record3);
5709
+ }
5710
+ io.write(`\u6062\u590D\u7F16\u53F7\uFF1A${record3.id}`);
5711
+ try {
5712
+ const receipt = action === "--retry" ? await required(client.retryProductRelease).call(client, { id, releaseId: record3.id }) : action === "--cancel" ? await required(client.cancelProductRelease).call(client, { id, releaseId: record3.id }) : await required(client.createProductRelease).call(client, { id, release: record3.request });
5713
+ matchRelease(record3.request, receipt);
5714
+ await store.save({ ...record3, receipt });
5715
+ return { exitCode: showRelease(io, receipt), buddyId: id, version: receipt.buddyVersion };
5716
+ } catch (cause) {
5717
+ if (cause instanceof CloudOperationError && cause.release) {
5718
+ matchRelease(record3.request, cause.release);
5719
+ await store.save({ ...record3, receipt: cause.release });
5720
+ showRelease(io, cause.release);
5721
+ }
5722
+ io.writeError(`\u53D1\u5E03\u7ED3\u679C\u9700\u786E\u8BA4\uFF1Abuddy-cli release --status ${record3.id}\uFF1B\u539F\u8BF7\u6C42\u6062\u590D\uFF1Abuddy-cli release --resume ${record3.id}`);
5723
+ throw cause;
5724
+ }
5725
+ }
5726
+
5309
5727
  // packages/cli-core/src/push/errors.ts
5310
5728
  var PushPreflightError = class extends Error {
5311
5729
  code;
@@ -5319,13 +5737,13 @@ var PushPreflightError = class extends Error {
5319
5737
  };
5320
5738
 
5321
5739
  // packages/cli-core/src/commands/cloud.ts
5322
- import { resolve as resolve15 } from "node:path";
5740
+ import { resolve as resolve16 } from "node:path";
5323
5741
 
5324
5742
  // packages/cli-core/src/cloud/auth.ts
5325
- import { randomUUID as randomUUID8 } from "node:crypto";
5743
+ import { randomUUID as randomUUID10 } from "node:crypto";
5326
5744
 
5327
5745
  // packages/cli-core/src/cloud/validation.ts
5328
- function record(value, path = "request") {
5746
+ function record2(value, path = "request") {
5329
5747
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
5330
5748
  return invalidRequest(`${path} \u5FC5\u987B\u662F\u5BF9\u8C61`);
5331
5749
  }
@@ -5335,12 +5753,12 @@ function record(value, path = "request") {
5335
5753
  }
5336
5754
  return value;
5337
5755
  }
5338
- function exactKeys(value, required, optional = [], path = "request") {
5339
- const allowed = /* @__PURE__ */ new Set([...required, ...optional]);
5756
+ function exactKeys(value, required2, optional = [], path = "request") {
5757
+ const allowed = /* @__PURE__ */ new Set([...required2, ...optional]);
5340
5758
  for (const key of Object.keys(value)) {
5341
5759
  if (!allowed.has(key)) invalidRequest(`${path} \u5305\u542B\u672A\u77E5\u5B57\u6BB5 ${key}`);
5342
5760
  }
5343
- for (const key of required) {
5761
+ for (const key of required2) {
5344
5762
  if (!Object.hasOwn(value, key)) invalidRequest(`${path} \u7F3A\u5C11\u5B57\u6BB5 ${key}`);
5345
5763
  }
5346
5764
  }
@@ -5390,7 +5808,7 @@ var CloudAuthenticator = class {
5390
5808
  this.#adapter = adapter;
5391
5809
  this.#store = store;
5392
5810
  this.#now = options.now ?? Date.now;
5393
- this.#createState = options.createState ?? randomUUID8;
5811
+ this.#createState = options.createState ?? randomUUID10;
5394
5812
  this.#minimumValidityMs = options.minimumValidityMs ?? 3e4;
5395
5813
  if (!Number.isSafeInteger(this.#minimumValidityMs) || this.#minimumValidityMs < 0) {
5396
5814
  throw new TypeError("minimumValidityMs must be a non-negative safe integer");
@@ -5442,7 +5860,7 @@ var CloudAuthenticator = class {
5442
5860
  state: state2,
5443
5861
  ...signal === void 0 ? {} : { signal }
5444
5862
  }));
5445
- const resultRecord = record(result, "browser login result");
5863
+ const resultRecord = record2(result, "browser login result");
5446
5864
  exactKeys(resultRecord, ["state", "token"], [], "browser login result");
5447
5865
  if (resultRecord.state !== state2) {
5448
5866
  throw new CloudLifecycleError(
@@ -5460,7 +5878,7 @@ var CloudAuthenticator = class {
5460
5878
  };
5461
5879
  function validateToken2(value) {
5462
5880
  try {
5463
- const input = record(value, "cloud token");
5881
+ const input = record2(value, "cloud token");
5464
5882
  exactKeys(input, ["accessToken", "subject", "expiresAt"], [], "cloud token");
5465
5883
  const accessToken = safeString(input.accessToken, "cloud token accessToken", {
5466
5884
  min: 16,
@@ -5538,6 +5956,7 @@ var EcsSessionMigrationStore = class {
5538
5956
  };
5539
5957
 
5540
5958
  // packages/cli-core/src/cloud/http-client.ts
5959
+ import { createHash as createHash11 } from "node:crypto";
5541
5960
  var MAX_RESPONSE_BYTES = 1024 * 1024;
5542
5961
  var DEFAULT_TIMEOUT_MS = 3e4;
5543
5962
  var DEFAULT_UPLOAD_TIMEOUT_MS = 5 * 6e4;
@@ -5548,17 +5967,17 @@ function positiveTimeout(value, fallback, name) {
5548
5967
  }
5549
5968
  function object3(value, path) {
5550
5969
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
5551
- throw invalid2(`${path} \u5FC5\u987B\u662F\u5BF9\u8C61`);
5970
+ throw invalid3(`${path} \u5FC5\u987B\u662F\u5BF9\u8C61`);
5552
5971
  }
5553
5972
  return value;
5554
5973
  }
5555
- function invalid2(message) {
5974
+ function invalid3(message) {
5556
5975
  return new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", message);
5557
5976
  }
5558
5977
  function safeText(value, path, allowNewlines = false, allowEmpty = false) {
5559
- if (typeof value !== "string" || !allowEmpty && !value.trim()) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
5978
+ if (typeof value !== "string" || !allowEmpty && !value.trim()) throw invalid3(`${path} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
5560
5979
  const invalidControl = allowNewlines ? /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/u : /[\u0000-\u001f\u007f]/u;
5561
- if (invalidControl.test(value)) throw invalid2(`${path} \u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26`);
5980
+ if (invalidControl.test(value)) throw invalid3(`${path} \u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26`);
5562
5981
  return value;
5563
5982
  }
5564
5983
  function optionalText(value, path, allowNewlines = false) {
@@ -5580,29 +5999,29 @@ function meta(value, path) {
5580
5999
  });
5581
6000
  }
5582
6001
  function flag(value, path) {
5583
- if (typeof value !== "boolean") throw invalid2(`${path} \u5FC5\u987B\u662F boolean`);
6002
+ if (typeof value !== "boolean") throw invalid3(`${path} \u5FC5\u987B\u662F boolean`);
5584
6003
  return value;
5585
6004
  }
5586
6005
  function timestamp(value, path) {
5587
- if (!Number.isSafeInteger(value) || value < 0) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6BEB\u79D2\u65F6\u95F4\u6233`);
6006
+ if (!Number.isSafeInteger(value) || value < 0) throw invalid3(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6BEB\u79D2\u65F6\u95F4\u6233`);
5588
6007
  return value;
5589
6008
  }
5590
6009
  function nullableText(value, path) {
5591
6010
  return value === null ? null : safeText(value, path);
5592
6011
  }
5593
6012
  function nonNegativeInteger(value, path) {
5594
- if (!Number.isSafeInteger(value) || value < 0) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570`);
6013
+ if (!Number.isSafeInteger(value) || value < 0) throw invalid3(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570`);
5595
6014
  return value;
5596
6015
  }
5597
6016
  function auditStatus(value, path) {
5598
6017
  if (value !== "auditing" && value !== "approved" && value !== "rejected") {
5599
- throw invalid2(`${path} \u5FC5\u987B\u662F auditing\u3001approved \u6216 rejected`);
6018
+ throw invalid3(`${path} \u5FC5\u987B\u662F auditing\u3001approved \u6216 rejected`);
5600
6019
  }
5601
6020
  return value;
5602
6021
  }
5603
6022
  function parseBuild(value) {
5604
6023
  const source = object3(value, "build");
5605
- if (!["building", "ready", "failed"].includes(String(source.buildStatus))) throw invalid2("\u6784\u5EFA\u72B6\u6001\u65E0\u6548");
6024
+ if (!["building", "ready", "failed"].includes(String(source.buildStatus))) throw invalid3("\u6784\u5EFA\u72B6\u6001\u65E0\u6548");
5606
6025
  return {
5607
6026
  buildStatus: source.buildStatus,
5608
6027
  buildError: source.buildError == null ? null : safeText(source.buildError, "build.buildError")
@@ -5652,7 +6071,7 @@ async function boundedJson(response) {
5652
6071
  total += item.value.byteLength;
5653
6072
  if (total > MAX_RESPONSE_BYTES) {
5654
6073
  void reader.cancel().catch(() => void 0);
5655
- throw invalid2("\u5E73\u53F0\u54CD\u5E94\u8D85\u8FC7 1 MiB");
6074
+ throw invalid3("\u5E73\u53F0\u54CD\u5E94\u8D85\u8FC7 1 MiB");
5656
6075
  }
5657
6076
  chunks.push(item.value);
5658
6077
  }
@@ -5668,17 +6087,17 @@ async function boundedJson(response) {
5668
6087
  try {
5669
6088
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
5670
6089
  } catch {
5671
- throw invalid2("\u5E73\u53F0\u54CD\u5E94\u4E0D\u662F\u6709\u6548 JSON");
6090
+ throw invalid3("\u5E73\u53F0\u54CD\u5E94\u4E0D\u662F\u6709\u6548 JSON");
5672
6091
  }
5673
6092
  }
5674
6093
  function serverError(response, body) {
5675
6094
  const source = typeof body === "object" && body !== null && !Array.isArray(body) ? body : void 0;
5676
6095
  const message = typeof source?.error === "string" && source.error.trim() ? source.error.slice(0, 8 * 1024) : `\u5E73\u53F0\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${response.status}\uFF09`;
5677
6096
  const code2 = response.status === 401 ? "AUTH_TOKEN_EXPIRED" : response.status === 404 ? "APP_NOT_FOUND" : response.status >= 500 ? "PLATFORM_UNAVAILABLE" : "INVALID_REQUEST";
5678
- return new CloudLifecycleError(code2, message, {
6097
+ return new CloudOperationError(code2, message, {
5679
6098
  httpStatus: response.status,
5680
6099
  retryable: response.status === 408 || response.status === 429 || response.status >= 500
5681
- });
6100
+ }, source?.push === void 0 ? void 0 : parsePackagePush(source.push), source?.release === void 0 ? void 0 : parseProductRelease(source.release));
5682
6101
  }
5683
6102
  var HttpDeveloperPlatformClient = class {
5684
6103
  #baseUrl;
@@ -5739,7 +6158,7 @@ var HttpDeveloperPlatformClient = class {
5739
6158
  const mediaType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
5740
6159
  if (mediaType !== "application/json") {
5741
6160
  await response.body?.cancel().catch(() => void 0);
5742
- throw invalid2(`\u5E73\u53F0\u54CD\u5E94 Content-Type \u65E0\u6548\uFF08HTTP ${response.status}\uFF09`);
6161
+ throw invalid3(`\u5E73\u53F0\u54CD\u5E94 Content-Type \u65E0\u6548\uFF08HTTP ${response.status}\uFF09`);
5743
6162
  }
5744
6163
  const payload = await boundedJson(response);
5745
6164
  if (!response.ok) throw serverError(response, payload);
@@ -5764,7 +6183,7 @@ var HttpDeveloperPlatformClient = class {
5764
6183
  }
5765
6184
  async listBuddies() {
5766
6185
  const source = object3(await this.#request("/cli/buddies", "GET"), "response");
5767
- if (!Array.isArray(source.buddies)) throw invalid2("response.buddies \u5FC5\u987B\u662F\u6570\u7EC4");
6186
+ if (!Array.isArray(source.buddies)) throw invalid3("response.buddies \u5FC5\u987B\u662F\u6570\u7EC4");
5768
6187
  return Object.freeze({
5769
6188
  buddies: Object.freeze(source.buddies.map((item) => buddy(item, false)))
5770
6189
  });
@@ -5784,7 +6203,7 @@ var HttpDeveloperPlatformClient = class {
5784
6203
  `/cli/buddies/${encodeURIComponent(request.id)}/packages${suffix}`,
5785
6204
  "GET"
5786
6205
  ), "response");
5787
- if (!Array.isArray(source.items)) throw invalid2("response.items \u5FC5\u987B\u662F\u6570\u7EC4");
6206
+ if (!Array.isArray(source.items)) throw invalid3("response.items \u5FC5\u987B\u662F\u6570\u7EC4");
5788
6207
  return Object.freeze({
5789
6208
  total: nonNegativeInteger(source.total, "response.total"),
5790
6209
  page: nonNegativeInteger(source.page, "response.page"),
@@ -5802,37 +6221,82 @@ var HttpDeveloperPlatformClient = class {
5802
6221
  throw new CloudLifecycleError("INVALID_REQUEST", "\u63D0\u4EA4\u5305\u4E0D\u80FD\u4E3A\u7A7A");
5803
6222
  }
5804
6223
  const query = new URLSearchParams({ commit });
6224
+ const form = request.metadata ? new FormData() : void 0;
6225
+ if (form && request.metadata) {
6226
+ if (request.metadata.commit !== commit || request.metadata.sourceSha256 !== createHash11("sha256").update(request.sourceBundle.bytes).digest("hex")) throw new CloudLifecycleError("INVALID_REQUEST", "\u4FDD\u5B58\u7684\u4E0A\u4F20\u5143\u6570\u636E\u4E0E\u7A0B\u5E8F\u5305\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u52FF\u66F4\u6362\u6062\u590D\u5305");
6227
+ form.set("metadata", JSON.stringify(request.metadata));
6228
+ form.set("archive", new Blob([new Uint8Array(request.sourceBundle.bytes)], { type: "application/gzip" }), "archive.tar.gz");
6229
+ }
5805
6230
  const source = object3(await this.#request(
5806
- `/cli/buddies/${encodeURIComponent(request.id)}/packages/push?${query.toString()}`,
6231
+ `/cli/buddies/${encodeURIComponent(request.id)}/packages/push${form ? "" : `?${query.toString()}`}`,
5807
6232
  "POST",
5808
6233
  {
5809
- binary: request.sourceBundle.bytes,
5810
- mediaType: request.sourceBundle.mediaType,
6234
+ ...form ? { form } : { binary: request.sourceBundle.bytes, mediaType: request.sourceBundle.mediaType },
5811
6235
  timeoutMs: this.#uploadTimeoutMs
5812
6236
  }
5813
6237
  ), "response");
6238
+ const push = request.metadata ? parsePackagePush(source.push) : void 0;
6239
+ if (push && request.metadata && !samePushMetadata(push.metadata, request.metadata)) throw invalid3("\u5E73\u53F0\u4E0A\u4F20\u56DE\u6267\u4E0E\u56FA\u5B9A\u8BF7\u6C42\u4E0D\u5339\u914D");
5814
6240
  return Object.freeze({
5815
6241
  version: safeText(source.version, "response.version"),
5816
6242
  commit: safeText(source.commit, "response.commit"),
5817
6243
  size: nonNegativeInteger(source.size, "response.size"),
5818
6244
  auditStatus: auditStatus(source.auditStatus, "response.auditStatus"),
5819
- ...source.buildStatus === void 0 ? {} : parseBuild(source)
6245
+ ...source.buildStatus === void 0 ? {} : parseBuild(source),
6246
+ ...push ? { push, reviewIds: selectedReviewIds(source.reviewIds) } : {}
5820
6247
  });
5821
6248
  }
6249
+ async getProductForSubmission(request) {
6250
+ const response = object3(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/products/${encodeURIComponent(request.productId)}`, "GET"), "response");
6251
+ const p = object3(response.product, "product"), draft = object3(p.draft, "product.draft"), declaration = object3(draft.declaration, "product.draft.declaration");
6252
+ if (p.productId !== request.productId || p.buddyId !== request.id) throw invalid3("\u5546\u54C1\u5F52\u5C5E\u4E0E\u8BF7\u6C42\u4E0D\u5339\u914D");
6253
+ const draftVersion = nonNegativeInteger(p.draftVersion, "product.draftVersion");
6254
+ if (draftVersion < 1) throw invalid3("\u5546\u54C1\u8349\u7A3F\u7248\u672C\u65E0\u6548");
6255
+ return { productId: request.productId, buddyId: request.id, draftVersion, name: declaration.name == null ? null : safeText(declaration.name, "product.name", false, true) };
6256
+ }
6257
+ async getPackagePush(request) {
6258
+ const source = object3(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/packages/pushes/${encodeURIComponent(request.pushId)}`, "GET"), "response");
6259
+ const push = parsePackagePush(source.push);
6260
+ if (push.pushId !== request.pushId) throw invalid3("\u4E0A\u4F20\u56DE\u6267 ID \u4E0D\u5339\u914D");
6261
+ return push;
6262
+ }
6263
+ async submitPackageProducts(request) {
6264
+ const source = object3(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/packages/${encodeURIComponent(request.version)}/product-reviews`, "POST", { json: { reviews: request.reviews } }), "response");
6265
+ return { reviewIds: selectedReviewIds(source.reviewIds) };
6266
+ }
6267
+ async createProductRelease(request) {
6268
+ const source = object3(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/product-releases`, "POST", { json: request.release }), "response");
6269
+ return parseProductRelease(source.release);
6270
+ }
6271
+ async getProductRelease(request) {
6272
+ const source = object3(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/product-releases/${encodeURIComponent(request.releaseId)}`, "GET"), "response");
6273
+ const release = parseProductRelease(source.release);
6274
+ if (release.releaseId !== request.releaseId) throw invalid3("\u53D1\u5E03\u56DE\u6267 ID \u4E0D\u5339\u914D");
6275
+ return release;
6276
+ }
6277
+ async retryProductRelease(request) {
6278
+ const source = object3(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/product-releases/${encodeURIComponent(request.releaseId)}/retry`, "POST"), "response");
6279
+ return parseProductRelease(source.release);
6280
+ }
6281
+ async cancelProductRelease(request) {
6282
+ const source = object3(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/product-releases/${encodeURIComponent(request.releaseId)}/cancel`, "POST"), "response");
6283
+ return parseProductRelease(source.release);
6284
+ }
5822
6285
  async getPackageBuild(request) {
5823
6286
  return parseBuild(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/packages/${encodeURIComponent(request.version)}/build`, "GET"));
5824
6287
  }
5825
6288
  async logout(accessToken) {
5826
6289
  const source = object3(await this.#request("/cli/auth/logout", "POST", { accessToken }), "response");
5827
- if (source.ok !== true) throw invalid2("response.ok \u5FC5\u987B\u662F true");
6290
+ if (source.ok !== true) throw invalid3("response.ok \u5FC5\u987B\u662F true");
5828
6291
  }
5829
6292
  };
5830
6293
 
5831
6294
  // packages/cli-core/src/cloud/mock-client.ts
5832
- import { createHash as createHash9, randomBytes as randomBytes3 } from "node:crypto";
6295
+ import { createHash as createHash12, randomBytes as randomBytes3 } from "node:crypto";
5833
6296
  var MockDeveloperPlatformClient = class {
5834
6297
  #now;
5835
6298
  #buddies = /* @__PURE__ */ new Map();
6299
+ #pushes = /* @__PURE__ */ new Map();
5836
6300
  #packages = /* @__PURE__ */ new Map();
5837
6301
  constructor(options = {}) {
5838
6302
  this.#now = options.now ?? Date.now;
@@ -5857,7 +6321,7 @@ var MockDeveloperPlatformClient = class {
5857
6321
  const current = this.#require(request.id);
5858
6322
  validateBuddyMetaUpdate(request.meta);
5859
6323
  const onlyAvatar = Object.keys(request.meta).every((key) => key === "avatar");
5860
- const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash9("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
6324
+ const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash12("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
5861
6325
  const next = this.#value({ ...current, meta: { ...onlyAvatar ? current.meta : request.meta, avatar }, updatedAt: this.#now() });
5862
6326
  this.#buddies.set(request.id, next);
5863
6327
  return structuredClone(next);
@@ -5894,6 +6358,8 @@ var MockDeveloperPlatformClient = class {
5894
6358
  throw new CloudLifecycleError("INVALID_REQUEST", "commit \u4E0D\u80FD\u4E3A\u7A7A");
5895
6359
  }
5896
6360
  const current = this.#require(request.id);
6361
+ const existing = request.metadata && this.#pushes.get(request.metadata.pushId);
6362
+ if (existing) return { version: existing.uploadVersion, commit: existing.metadata.commit, size: request.sourceBundle.bytes.byteLength, auditStatus: "auditing", push: structuredClone(existing), reviewIds: existing.reviewIds };
5897
6363
  const pushedAt = this.#now();
5898
6364
  const version = mockVersion(pushedAt);
5899
6365
  const versions = this.#packages.get(request.id) ?? [];
@@ -5906,12 +6372,20 @@ var MockDeveloperPlatformClient = class {
5906
6372
  version,
5907
6373
  commit: request.commit,
5908
6374
  size: request.sourceBundle.bytes.byteLength,
5909
- auditStatus: "auditing"
6375
+ auditStatus: "auditing",
6376
+ ...request.metadata ? { push: { pushId: request.metadata.pushId, uploadVersion: version, status: "completed", metadata: request.metadata, reviewIds: request.metadata.productReviews.map((r) => r.reviewId), failure: null }, reviewIds: request.metadata.productReviews.map((r) => r.reviewId) } : {}
5910
6377
  });
6378
+ if (receipt.push) this.#pushes.set(receipt.push.pushId, receipt.push);
5911
6379
  versions.unshift(Object.freeze({ ...receipt, auditNote: null }));
5912
6380
  this.#packages.set(request.id, versions);
5913
6381
  return receipt;
5914
6382
  }
6383
+ async getPackagePush(request) {
6384
+ this.#require(request.id);
6385
+ const push = this.#pushes.get(request.pushId);
6386
+ if (!push) throw new CloudLifecycleError("APP_NOT_FOUND", "\u4E0A\u4F20\u8BB0\u5F55\u4E0D\u5B58\u5728");
6387
+ return structuredClone(push);
6388
+ }
5915
6389
  async logout(_accessToken) {
5916
6390
  }
5917
6391
  #require(id) {
@@ -5933,20 +6407,12 @@ function mockVersion(now) {
5933
6407
  }
5934
6408
 
5935
6409
  // packages/cli-core/src/commands/cloud.ts
5936
- var CloudCommandUsageError = class extends Error {
5937
- constructor(message) {
5938
- super(message);
5939
- this.name = "CloudCommandUsageError";
5940
- }
5941
- };
5942
6410
  var HELP = Object.freeze({
5943
6411
  login: "\u7528\u6CD5: buddy-cli login",
5944
6412
  logout: "\u7528\u6CD5: buddy-cli logout",
5945
- push: `\u7528\u6CD5: buddy-cli push [--directory <\u9879\u76EE\u76EE\u5F55>] [--commit <\u672C\u6B21\u6539\u52A8\u8BF4\u660E>]
5946
- --directory \u9ED8\u8BA4\u5F53\u524D\u5DE5\u7A0B\uFF1B--commit \u662F\u4E0A\u4F20\u8BF4\u660E\uFF0C\u4E0D\u4F1A\u521B\u5EFA Git commit\uFF0C\u975E\u4EA4\u4E92\u8C03\u7528\u5FC5\u987B\u63D0\u4F9B\u3002
5947
- \u5DE5\u7A0B\u5FC5\u987B\u5B89\u88C5 npm \u6700\u65B0\u7A33\u5B9A\u7248 Runtime\uFF1B\u7248\u672C\u4E0D\u4E00\u81F4\u6216\u67E5\u8BE2\u5931\u8D25\u65F6\u7981\u6B62\u4E0A\u4F20\u3002
5948
- \u4E0A\u4F20\u540E\u663E\u793A\u5BA1\u6838\u53CA\u6784\u5EFA\u72B6\u6001\uFF1B\u6784\u5EFA\u672A\u5B8C\u6210\u7528 status \u91CD\u67E5\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u53D1\u5E03\u3002
5949
- \u793A\u4F8B: buddy-cli push --commit "\u8C03\u6574\u56DE\u590D\u65B9\u5F0F"`,
6413
+ push: PRODUCT_HELP.push,
6414
+ products: PRODUCT_HELP.products,
6415
+ release: PRODUCT_HELP.release,
5950
6416
  status: "\u7528\u6CD5: buddy-cli status [--directory <\u9879\u76EE\u76EE\u5F55>]",
5951
6417
  meta: `\u7528\u6CD5: buddy-cli meta [--directory <\u9879\u76EE\u76EE\u5F55> | --buddy-id <\u642D\u5B50 ID>]
5952
6418
  buddy-cli meta update [--name <\u540D\u79F0>] [--tagline <\u4E00\u53E5\u8BDD\u4ECB\u7ECD>] [--intro <\u5B8C\u6574\u4ECB\u7ECD>] [--avatar <\u56FE\u7247\u6587\u4EF6>] [--directory <\u9879\u76EE\u76EE\u5F55> | --buddy-id <\u642D\u5B50 ID>]
@@ -5962,7 +6428,7 @@ meta \u53EA\u67E5\u770B\u4E91\u7AEF\u8D44\u6599\uFF1Bmeta update \u81F3\u5C11\u6
5962
6428
  --file \u63A5\u53D7\u672C\u5730\u9759\u6001 PNG\u3001JPEG\u3001WebP \u56FE\u7247\uFF0C\u6700\u5927 5 MiB\uFF1BServer \u81EA\u52A8\u5904\u7406\u5E76\u751F\u6210\u5730\u5740\u3002
5963
6429
  \u9700\u8981\u5F53\u524D\u8D26\u53F7\u62E5\u6709\u8BE5\u642D\u5B50\uFF0C\u547D\u4EE4\u6267\u884C\u540E\u7ACB\u5373\u66F4\u65B0\u4E91\u7AEF\u8D44\u6599\u3002`
5964
6430
  });
5965
- function parse2(args, command) {
6431
+ function parse3(args, command) {
5966
6432
  const values = /* @__PURE__ */ new Map();
5967
6433
  let help = false;
5968
6434
  const update = command === "meta" && args[0] === "update";
@@ -5993,26 +6459,6 @@ function parse2(args, command) {
5993
6459
  }
5994
6460
  return { values, help, update };
5995
6461
  }
5996
- function validCommit(value) {
5997
- const commit = value.trim();
5998
- if (!commit) throw new CloudCommandUsageError("--commit \u4E0D\u80FD\u4E3A\u7A7A");
5999
- if (/[\u0000-\u001f\u007f]/u.test(commit)) {
6000
- throw new CloudCommandUsageError("--commit \u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26");
6001
- }
6002
- return commit;
6003
- }
6004
- async function pushCommit(parsed, io) {
6005
- const provided = parsed.values.get("--commit");
6006
- if (provided !== void 0) return validCommit(provided);
6007
- if (!io.canPrompt || io.input === void 0) {
6008
- throw new CloudCommandUsageError("\u7F3A\u5C11 --commit\uFF1B\u8BF7\u8BF4\u660E\u672C\u6B21\u63D0\u4EA4\u5BA1\u6838\u7684\u6539\u52A8\u5185\u5BB9");
6009
- }
6010
- while (true) {
6011
- const answer = await io.input("\u8BF7\u8BF4\u660E\u672C\u6B21\u63D0\u4EA4\u5BA1\u6838\u7684\u6539\u52A8\u5185\u5BB9");
6012
- if (answer.trim()) return validCommit(answer);
6013
- io.writeError("\u8BF7\u8F93\u5165\u975E\u7A7A\u7684 commit\u3002");
6014
- }
6015
- }
6016
6462
  function dependencies(options) {
6017
6463
  if (!options.session || !options.client) {
6018
6464
  throw new CloudCommandUsageError("\u5F53\u524D CLI Host \u5C1A\u672A\u914D\u7F6E\u642D\u642D\u8D26\u53F7\u548C\u5F00\u53D1\u8005\u5E73\u53F0 Adapter");
@@ -6020,7 +6466,7 @@ function dependencies(options) {
6020
6466
  return { session: options.session, client: options.client };
6021
6467
  }
6022
6468
  function requestedDirectory(options, parsed) {
6023
- return resolve15(options.cwd ?? process.cwd(), parsed.values.get("--directory") ?? ".");
6469
+ return resolve16(options.cwd ?? process.cwd(), parsed.values.get("--directory") ?? ".");
6024
6470
  }
6025
6471
  function auditLabel(status) {
6026
6472
  if (status === "auditing") return "\u5BA1\u6838\u4E2D";
@@ -6074,49 +6520,6 @@ async function runLogout(io, options) {
6074
6520
  io.write("\u5DF2\u9000\u51FA\u642D\u642D\u5F00\u53D1\u8005\u8D26\u53F7\uFF0C\u5E76\u6E05\u9664\u672C\u673A\u767B\u5F55\u72B6\u6001\u3002");
6075
6521
  return { exitCode: 0 };
6076
6522
  }
6077
- async function runPush(parsed, io, options) {
6078
- const root = await (options.resolveProjectRoot ?? requireBuddyAgentProjectRoot)(requestedDirectory(options, parsed));
6079
- await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
6080
- const config = await (options.readConfig ?? readBuddyConfig)(root);
6081
- const commit = await pushCommit(parsed, io);
6082
- if (!config.buddyId) throw new CloudCommandUsageError("\u5F53\u524D\u9879\u76EE\u7F3A\u5C11\u5E73\u53F0\u751F\u6210\u7684 buddyId\uFF0C\u8BF7\u5148\u8FD0\u884C buddy-cli init");
6083
- if (options.mode === "local-mock") {
6084
- throw new CloudCommandUsageError("\u672C\u5730\u6A21\u62DF\u6A21\u5F0F\u4E0D\u4F1A\u4F2A\u9020\u6B63\u5F0F push\uFF0C\u8BF7\u8FDE\u63A5\u771F\u5B9E MLB Server");
6085
- }
6086
- if (!options.preparePush) throw new CloudCommandUsageError("push \u6253\u5305 Adapter \u5C1A\u672A\u914D\u7F6E");
6087
- const { session, client } = dependencies(options);
6088
- const expectedRuntime = await requireProjectRuntime(root, { ...options.runtimeUpdate, signal: options.signal });
6089
- await session.token({ signal: options.signal });
6090
- const sourceBundle = await options.preparePush(root, config, expectedRuntime);
6091
- for (const warning2 of sourceBundle.warnings ?? []) {
6092
- io.writeError(`\u6253\u5305\u63D0\u793A [${warning2.code}]\uFF1A${warning2.message}`);
6093
- }
6094
- const receipt = await client.pushPackage({ id: config.buddyId, commit, sourceBundle });
6095
- io.write(`\u5DF2\u63D0\u4EA4\u5BA1\u6838\uFF1A${config.buddyId}`);
6096
- io.write(`\u5F85\u5BA1\u6838\u7248\u672C\uFF1A${receipt.version}`);
6097
- io.write(`commit\uFF1A${receipt.commit}`);
6098
- io.write(`\u5BA1\u6838\u72B6\u6001\uFF1A${auditLabel(receipt.auditStatus)}`);
6099
- io.write(`\u4E0A\u4F20\u5927\u5C0F\uFF1A${receipt.size} bytes`);
6100
- io.write("\u672C\u6B21 push \u63D0\u4EA4\u4EE3\u7801\u5E76\u89E6\u53D1\u5E73\u53F0\u6784\u5EFA\uFF0C\u4E0D\u4F1A\u53D1\u5E03 Agent\uFF1B\u6784\u5EFA\u5B8C\u6210\u540E\u4ECD\u9700\u5728\u540E\u53F0\u624B\u52A8\u53D1\u5E03\u3002");
6101
- if (receipt.buildStatus && client.getPackageBuild) {
6102
- io.write(`\u6784\u5EFA\uFF1A${buildLabel(receipt.buildStatus)}`);
6103
- const deadline = Date.now() + (options.buildWaitMs ?? 6e4);
6104
- let build = { buildStatus: receipt.buildStatus, buildError: receipt.buildError ?? null };
6105
- try {
6106
- while (build.buildStatus === "building" && Date.now() < deadline) {
6107
- await delay3(Math.min(options.buildPollMs ?? 2e3, Math.max(1, deadline - Date.now())), void 0, { signal: options.signal });
6108
- build = await client.getPackageBuild({ id: config.buddyId, version: receipt.version });
6109
- }
6110
- io.write(`\u6784\u5EFA\uFF1A${buildLabel(build.buildStatus)}${build.buildError ? ` \xB7 ${build.buildError}` : ""}`);
6111
- if (build.buildStatus === "failed") return { exitCode: 1, buddyId: config.buddyId, version: receipt.version };
6112
- if (build.buildStatus === "building") io.write("\u6784\u5EFA\u4ECD\u5728\u8FDB\u884C\uFF0C\u7A0D\u540E\u8FD0\u884C buddy-cli status \u67E5\u8BE2\uFF1B\u4E0D\u8981\u91CD\u590D\u4E0A\u4F20\u3002");
6113
- } catch (cause) {
6114
- io.writeError(`\u4EE3\u7801\u5DF2\u4E0A\u4F20\uFF0C\u4F46\u6784\u5EFA\u72B6\u6001\u5C1A\u672A\u786E\u8BA4\uFF1A${cause instanceof Error ? cause.message : String(cause)}\u3002\u7528 buddy-cli status \u91CD\u67E5\uFF0C\u4E0D\u8981\u91CD\u590D\u4E0A\u4F20\u3002`);
6115
- return { exitCode: 1, buddyId: config.buddyId, version: receipt.version };
6116
- }
6117
- }
6118
- return { exitCode: 0, buddyId: config.buddyId, version: receipt.version };
6119
- }
6120
6523
  function printMeta(io, buddy2) {
6121
6524
  io.write(`\u642D\u5B50\uFF1A${buddy2.meta?.name ?? "\u672A\u586B\u5199\u540D\u79F0"}\uFF08${buddy2.id}\uFF09`);
6122
6525
  io.write(`\u4E00\u53E5\u8BDD\u4ECB\u7ECD\uFF1A${buddy2.meta?.tagline || "\u672A\u586B\u5199"}`);
@@ -6151,7 +6554,7 @@ async function runMeta(parsed, io, options, legacyAvatar = false) {
6151
6554
  }
6152
6555
  let upload;
6153
6556
  try {
6154
- upload = file ? await readBuddyAvatarFile(resolve15(options.cwd ?? process.cwd(), file)) : void 0;
6557
+ upload = file ? await readBuddyAvatarFile(resolve16(options.cwd ?? process.cwd(), file)) : void 0;
6155
6558
  } catch (error2) {
6156
6559
  throw new CloudCommandUsageError(error2 instanceof Error ? error2.message : "\u65E0\u6CD5\u8BFB\u53D6\u5934\u50CF\u56FE\u7247");
6157
6560
  }
@@ -6193,7 +6596,8 @@ async function runMeta(parsed, io, options, legacyAvatar = false) {
6193
6596
  }
6194
6597
  async function runCloudCommand(command, args, io, options = {}) {
6195
6598
  try {
6196
- const parsed = parse2(args, command);
6599
+ if (command === "push" || command === "products" || command === "release") return await runProductLifecycle(command, args, io, options);
6600
+ const parsed = parse3(args, command);
6197
6601
  if (parsed.help) {
6198
6602
  io.write(HELP[command]);
6199
6603
  return { exitCode: 0 };
@@ -6206,7 +6610,6 @@ async function runCloudCommand(command, args, io, options = {}) {
6206
6610
  return { exitCode: 0 };
6207
6611
  }
6208
6612
  if (command === "logout") return await runLogout(io, options);
6209
- if (command === "push") return await runPush(parsed, io, options);
6210
6613
  if (command === "meta" || command === "avatar") return await runMeta(parsed, io, options, command === "avatar");
6211
6614
  const root = await (options.resolveProjectRoot ?? requireBuddyProjectRoot)(requestedDirectory(options, parsed));
6212
6615
  await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
@@ -6238,6 +6641,10 @@ async function runCloudCommand(command, args, io, options = {}) {
6238
6641
  exitCode: cause instanceof CloudCommandUsageError || cause instanceof BuddyProjectContextError ? 2 : 1
6239
6642
  };
6240
6643
  }
6644
+ if (["push", "products", "release"].includes(command)) {
6645
+ io.writeError(`buddy-cli: ${cause instanceof Error ? cause.message : "\u64CD\u4F5C\u672A\u5B8C\u6210\uFF0C\u8BF7\u6309\u8F93\u51FA\u7F16\u53F7\u67E5\u8BE2\u6216\u6062\u590D"}`);
6646
+ return { exitCode: 1 };
6647
+ }
6241
6648
  throw cause;
6242
6649
  }
6243
6650
  }
@@ -6245,7 +6652,7 @@ var CLOUD_COMMAND_HELP = HELP;
6245
6652
 
6246
6653
  // packages/cli-core/src/migration/index.ts
6247
6654
  import { lstat as lstat12, open as open5, readdir as readdir6, realpath as realpath7, stat } from "node:fs/promises";
6248
- import { extname, isAbsolute as isAbsolute3, join as join20, relative, resolve as resolve16, sep, win32 as win322 } from "node:path";
6655
+ import { extname, isAbsolute as isAbsolute3, join as join21, relative, resolve as resolve17, sep, win32 as win322 } from "node:path";
6249
6656
  var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
6250
6657
  maxFiles: 128,
6251
6658
  maxFileBytes: 256 * 1024,
@@ -6398,7 +6805,7 @@ async function existingProjectRoot(value) {
6398
6805
  return rejectScan("SKILL_PROJECT_ROOT_INVALID", ".", "projectRoot \u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u5DF2\u6709\u9879\u76EE\u76EE\u5F55\u3002");
6399
6806
  }
6400
6807
  try {
6401
- const root = await realpath7(resolve16(value));
6808
+ const root = await realpath7(resolve17(value));
6402
6809
  if (!(await stat(root)).isDirectory()) {
6403
6810
  return rejectScan("SKILL_PROJECT_ROOT_INVALID", ".", "projectRoot \u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u5DF2\u6709\u9879\u76EE\u76EE\u5F55\u3002");
6404
6811
  }
@@ -6414,7 +6821,7 @@ async function existingProjectRoot(value) {
6414
6821
  }
6415
6822
  }
6416
6823
  async function existingSkillRoot(projectRoot, skillPath) {
6417
- const candidate = skillPath === "." ? projectRoot : join20(projectRoot, ...skillPath.split("/"));
6824
+ const candidate = skillPath === "." ? projectRoot : join21(projectRoot, ...skillPath.split("/"));
6418
6825
  try {
6419
6826
  await lstat12(candidate);
6420
6827
  } catch (cause) {
@@ -6451,7 +6858,7 @@ async function existingSkillRoot(projectRoot, skillPath) {
6451
6858
  }
6452
6859
  async function assertEntrypoint(context) {
6453
6860
  const entryPath = reportChild(context.skillPath, "SKILL.md");
6454
- const candidate = join20(context.skillRoot, "SKILL.md");
6861
+ const candidate = join21(context.skillRoot, "SKILL.md");
6455
6862
  try {
6456
6863
  await lstat12(candidate);
6457
6864
  const target = await realpath7(candidate);
@@ -6555,7 +6962,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
6555
6962
  }
6556
6963
  for (const entry2 of entries) {
6557
6964
  const childReportPath = reportChild(reportDirectory, entry2.name);
6558
- const childPath = join20(directory, entry2.name);
6965
+ const childPath = join21(directory, entry2.name);
6559
6966
  let target;
6560
6967
  try {
6561
6968
  target = await realpath7(childPath);
@@ -7009,9 +7416,9 @@ async function scanExternalSkillPortability(options) {
7009
7416
  }
7010
7417
 
7011
7418
  // packages/cli-core/src/push/preflight.ts
7012
- import { createHash as createHash10 } from "node:crypto";
7419
+ import { createHash as createHash13 } from "node:crypto";
7013
7420
  import { lstat as lstat13, open as open6, readdir as readdir7, realpath as realpath8 } from "node:fs/promises";
7014
- import { isAbsolute as isAbsolute4, join as join21, relative as relative2, resolve as resolve17, sep as sep2, win32 as win323 } from "node:path";
7421
+ import { isAbsolute as isAbsolute4, join as join22, relative as relative2, resolve as resolve18, sep as sep2, win32 as win323 } from "node:path";
7015
7422
  var MEBIBYTE = 1024 * 1024;
7016
7423
  var DEFAULT_PUSH_MANIFEST_LIMITS = Object.freeze({
7017
7424
  maxFiles: 1e4,
@@ -7095,7 +7502,7 @@ function error(options) {
7095
7502
  throw new PushPreflightError(options);
7096
7503
  }
7097
7504
  function sha256(value) {
7098
- return `sha256:${createHash10("sha256").update(value).digest("hex")}`;
7505
+ return `sha256:${createHash13("sha256").update(value).digest("hex")}`;
7099
7506
  }
7100
7507
  function positiveLimit(value, name, hardMaximum) {
7101
7508
  if (!Number.isSafeInteger(value) || value < 1 || value > hardMaximum) {
@@ -7185,7 +7592,7 @@ function normalizeBookletPath(value) {
7185
7592
  return normalized;
7186
7593
  }
7187
7594
  async function canonicalProjectRoot(projectRoot) {
7188
- const absolute = resolve17(projectRoot);
7595
+ const absolute = resolve18(projectRoot);
7189
7596
  let entry2;
7190
7597
  try {
7191
7598
  entry2 = await lstat13(absolute);
@@ -7216,7 +7623,7 @@ async function canonicalProjectRoot(projectRoot) {
7216
7623
  }
7217
7624
  }
7218
7625
  async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
7219
- const path = join21(projectRoot, filename);
7626
+ const path = join22(projectRoot, filename);
7220
7627
  let entry2;
7221
7628
  try {
7222
7629
  entry2 = await lstat13(path);
@@ -7341,7 +7748,7 @@ async function hashRegularFile(options) {
7341
7748
  message: `\u751F\u6210\u6E05\u5355\u65F6\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${options.portablePath}`
7342
7749
  });
7343
7750
  }
7344
- const hash3 = createHash10("sha256");
7751
+ const hash3 = createHash13("sha256");
7345
7752
  const captured = [];
7346
7753
  const buffer = Buffer.allocUnsafe(READ_BUFFER_BYTES);
7347
7754
  let bytes = 0;
@@ -7419,7 +7826,7 @@ async function createManifest(options) {
7419
7826
  sensitiveEntriesExcluded += 1;
7420
7827
  continue;
7421
7828
  }
7422
- const absolutePath = join21(directory, name);
7829
+ const absolutePath = join22(directory, name);
7423
7830
  let entry2;
7424
7831
  try {
7425
7832
  entry2 = await lstat13(absolutePath);
@@ -7673,7 +8080,7 @@ async function assertCapturedConfigStable(options) {
7673
8080
  }
7674
8081
  let current;
7675
8082
  try {
7676
- const path = join21(options.projectRoot, options.filename);
8083
+ const path = join22(options.projectRoot, options.filename);
7677
8084
  const entry2 = await lstat13(path);
7678
8085
  if (!entry2.isFile() || entry2.isSymbolicLink()) {
7679
8086
  error({
@@ -7719,7 +8126,7 @@ async function createPushPreflight(options) {
7719
8126
  parseCapturedProject(initialAgentEntry);
7720
8127
  let initialDataEntry;
7721
8128
  try {
7722
- await lstat13(join21(projectRoot, DATA_ACCESS_FILENAME));
8129
+ await lstat13(join22(projectRoot, DATA_ACCESS_FILENAME));
7723
8130
  initialDataEntry = await captureConfigWithinLimit(projectRoot, limits.maxFileBytes, DATA_ACCESS_FILENAME);
7724
8131
  } catch (cause) {
7725
8132
  if (cause.code !== "ENOENT") throw cause;
@@ -7820,16 +8227,16 @@ async function createPushPreflight(options) {
7820
8227
  }
7821
8228
 
7822
8229
  // packages/cli-core/src/push/bundle.ts
7823
- import { createHash as createHash11 } from "node:crypto";
7824
- import { lstat as lstat14, readFile as readFile19, realpath as realpath9 } from "node:fs/promises";
7825
- import { join as join22, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
8230
+ import { createHash as createHash14 } from "node:crypto";
8231
+ import { lstat as lstat14, readFile as readFile20, realpath as realpath9 } from "node:fs/promises";
8232
+ import { join as join23, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
7826
8233
  import { Writable } from "node:stream";
7827
8234
  import { pipeline } from "node:stream/promises";
7828
8235
  import { createGzip } from "node:zlib";
7829
8236
  import { pack } from "tar-stream";
7830
8237
  var MEDIA_TYPE = "application/gzip";
7831
8238
  function digest3(bytes) {
7832
- return `sha256:${createHash11("sha256").update(bytes).digest("hex")}`;
8239
+ return `sha256:${createHash14("sha256").update(bytes).digest("hex")}`;
7833
8240
  }
7834
8241
  function changed(path, message, cause) {
7835
8242
  throw new PushPreflightError({
@@ -7844,7 +8251,7 @@ function inside(root, target) {
7844
8251
  return path === "" || path !== ".." && !path.startsWith(`..${sep3}`) && !path.startsWith("/") && !win324.isAbsolute(path);
7845
8252
  }
7846
8253
  async function capture(root, file) {
7847
- const absolute = join22(root, ...file.path.split("/"));
8254
+ const absolute = join23(root, ...file.path.split("/"));
7848
8255
  try {
7849
8256
  const entry2 = await lstat14(absolute);
7850
8257
  if (!entry2.isFile() || entry2.isSymbolicLink() || entry2.size !== file.bytes) {
@@ -7852,7 +8259,7 @@ async function capture(root, file) {
7852
8259
  }
7853
8260
  const canonical = await realpath9(absolute);
7854
8261
  if (!inside(root, canonical)) changed(file.path, `\u63D0\u4EA4\u6587\u4EF6\u8D8A\u8FC7\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${file.path}`);
7855
- const contents = await readFile19(absolute);
8262
+ const contents = await readFile20(absolute);
7856
8263
  if (contents.byteLength !== file.bytes || digest3(contents) !== file.digest) {
7857
8264
  changed(file.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u5185\u5BB9\u53D1\u751F\u53D8\u5316\uFF1A${file.path}`);
7858
8265
  }
@@ -7878,7 +8285,7 @@ async function createPushSourceBundle(plan) {
7878
8285
  schemaVersion: "1",
7879
8286
  files: files.map((file) => ({ path: file.path, bytes: file.bytes, digest: file.digest }))
7880
8287
  });
7881
- const calculatedBundleDigest = `sha256:${createHash11("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
8288
+ const calculatedBundleDigest = `sha256:${createHash14("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
7882
8289
  if (calculatedBundleDigest !== plan.bundleDigest) {
7883
8290
  changed(plan.projectRoot, "\u63D0\u4EA4\u6E05\u5355\u8EAB\u4EFD\u5728\u6253\u5305\u524D\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C push");
7884
8291
  }
@@ -7979,7 +8386,7 @@ async function resolveApplicationDraft(name, tagline, intro, requestedBuddyId, o
7979
8386
  confirmMeta: args.confirmMeta,
7980
8387
  avatarSkill: { version: args.avatarSkillVersion, signal: options.cloud?.signal },
7981
8388
  requestedBuddyId,
7982
- cwd: resolve18(options.cwd ?? process.cwd()),
8389
+ cwd: resolve19(options.cwd ?? process.cwd()),
7983
8390
  client: platformDependencies(options).client,
7984
8391
  io
7985
8392
  });
@@ -8143,7 +8550,7 @@ function defaultProjectDirectory(name) {
8143
8550
  return `./${folder2}`;
8144
8551
  }
8145
8552
  async function initializeProjectRoute(route, args, io, options, application) {
8146
- const cwd = resolve18(options.cwd ?? process.cwd());
8553
+ const cwd = resolve19(options.cwd ?? process.cwd());
8147
8554
  const { name, tagline, intro } = application;
8148
8555
  const directoryInput = await textAnswer(
8149
8556
  io,
@@ -8152,7 +8559,7 @@ async function initializeProjectRoute(route, args, io, options, application) {
8152
8559
  "\u9879\u76EE\u76EE\u5F55\uFF08\u7A7A\u76EE\u5F55\u6216\u5DF2\u6709\u642D\u642D\u5DE5\u7A0B\uFF09",
8153
8560
  defaultProjectDirectory(name)
8154
8561
  );
8155
- const rootDirectory = resolve18(cwd, directoryInput);
8562
+ const rootDirectory = resolve19(cwd, directoryInput);
8156
8563
  await assertInitializableBuddyTarget(rootDirectory);
8157
8564
  const initializationTarget = { directory: rootDirectory, kind: "new" };
8158
8565
  let initializationPlan = options.initializeProject ? void 0 : await planBuddyProjectInitialization(initializationTarget);
@@ -8198,7 +8605,7 @@ async function initializeProjectRoute(route, args, io, options, application) {
8198
8605
  }
8199
8606
  async function runRoute(route, args, io, options) {
8200
8607
  if (!io.canPrompt) assertNonInteractiveProjectArguments(route, args);
8201
- const cwd = resolve18(options.cwd ?? process.cwd());
8608
+ const cwd = resolve19(options.cwd ?? process.cwd());
8202
8609
  const name = await textAnswer(io, args.name, "--name", "\u642D\u5B50\u540D\u79F0", void 0, BUDDY_PROFILE_TEXT_LIMITS.name);
8203
8610
  const tagline = await textAnswer(
8204
8611
  io,
@@ -8226,7 +8633,7 @@ async function runRoute(route, args, io, options) {
8226
8633
  "\u9879\u76EE\u76EE\u5F55",
8227
8634
  defaultProjectDirectory(name)
8228
8635
  );
8229
- const rootDirectory = resolve18(cwd, directoryInput);
8636
+ const rootDirectory = resolve19(cwd, directoryInput);
8230
8637
  await assertInitializableBuddyTarget(rootDirectory);
8231
8638
  let plan = await planBuddyDraftInitialization(rootDirectory);
8232
8639
  const existingBuddyId = plan.existingManifest?.buddyId;
@@ -8262,11 +8669,11 @@ async function runRoute(route, args, io, options) {
8262
8669
  return { ...result, route: "create", draft, buddyId };
8263
8670
  }
8264
8671
  async function resumeProjectArguments(args, cwd, options, io) {
8265
- const root = resolve18(cwd, args.directory?.trim() || ".");
8672
+ const root = resolve19(cwd, args.directory?.trim() || ".");
8266
8673
  await assertInitializableBuddyTarget(root);
8267
8674
  let entry2;
8268
8675
  try {
8269
- entry2 = await lstat15(join23(root, "package.json"));
8676
+ entry2 = await lstat15(join24(root, "package.json"));
8270
8677
  } catch (cause) {
8271
8678
  if (cause.code === "ENOENT") {
8272
8679
  const draft = await readMetaDraft(root);
@@ -8307,7 +8714,7 @@ async function runBuddyCli(args, io, options = {}) {
8307
8714
  try {
8308
8715
  const [command, ...rest] = args;
8309
8716
  if (!command) {
8310
- const cwd = resolve18(options.cwd ?? process.cwd());
8717
+ const cwd = resolve19(options.cwd ?? process.cwd());
8311
8718
  let projectRoot;
8312
8719
  try {
8313
8720
  projectRoot = await findBuddyProjectRoot(cwd);
@@ -8357,7 +8764,7 @@ async function runBuddyCli(args, io, options = {}) {
8357
8764
  ...options.dev
8358
8765
  });
8359
8766
  }
8360
- if (command === "login" || command === "logout" || command === "push" || command === "status" || command === "meta" || command === "avatar") {
8767
+ if (command === "login" || command === "logout" || command === "push" || command === "products" || command === "release" || command === "status" || command === "meta" || command === "avatar") {
8361
8768
  return await runCloudCommand(command, rest, io, {
8362
8769
  cwd: options.cwd,
8363
8770
  runtimeUpdate: options.runtimeCatalog,
@@ -8372,13 +8779,13 @@ async function runBuddyCli(args, io, options = {}) {
8372
8779
  }
8373
8780
  let route = routeFromMode(parsed.mode);
8374
8781
  if (route === void 0 && !io.canPrompt) requireModeForNonInteractive();
8375
- const cwd = resolve18(options.cwd ?? process.cwd());
8782
+ const cwd = resolve19(options.cwd ?? process.cwd());
8376
8783
  await assertInitializableBuddyTarget(cwd);
8377
8784
  if (parsed.directory !== void 0) {
8378
8785
  if (!parsed.directory.trim()) throw new CliUsageError("--directory \u4E0D\u80FD\u4E3A\u7A7A");
8379
- await assertInitializableBuddyTarget(resolve18(cwd, parsed.directory));
8786
+ await assertInitializableBuddyTarget(resolve19(cwd, parsed.directory));
8380
8787
  }
8381
- await checkProjectGateway(resolve18(cwd, parsed.directory ?? "."), resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
8788
+ await checkProjectGateway(resolve19(cwd, parsed.directory ?? "."), resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
8382
8789
  await authenticate(options);
8383
8790
  await resumeProjectArguments(parsed, cwd, options, io);
8384
8791
  route ??= routeFromMode(parsed.mode);
@@ -8492,6 +8899,7 @@ export {
8492
8899
  CloudAuthenticator,
8493
8900
  CloudCommandUsageError,
8494
8901
  CloudLifecycleError,
8902
+ CloudOperationError,
8495
8903
  DEFAULT_DEVELOPER_WEB_URL,
8496
8904
  DEFAULT_MLB_TEST_URL,
8497
8905
  DEFAULT_PUSH_MANIFEST_LIMITS,