@my-life-buddies/cli 0.13.0 → 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/core.js CHANGED
@@ -16,6 +16,12 @@ function runtimeDependencyVersion(pkg) {
16
16
  const version = dependencies2[BUDDY_RUNTIME_PACKAGE];
17
17
  return typeof version === "string" && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(version) ? version : void 0;
18
18
  }
19
+ function runtimeUsesEnvironmentIdentity(pkg) {
20
+ const version = runtimeDependencyVersion(pkg);
21
+ if (!version) return false;
22
+ const [major, minor] = version.split(".").map(Number);
23
+ return major > 0 || minor >= 16;
24
+ }
19
25
 
20
26
  // packages/cli-core/src/config/runtime-catalog.ts
21
27
  async function loadRuntime(projectRoot) {
@@ -529,7 +535,7 @@ import { lstat as lstat4 } from "node:fs/promises";
529
535
  import { join as join5 } from "node:path";
530
536
 
531
537
  // packages/cli-core/src/init/scaffold.ts
532
- import { lstat as lstat3, mkdir as mkdir4, open as open2, readFile as readFile6, rmdir as rmdir2, unlink as unlink3 } from "node:fs/promises";
538
+ import { lstat as lstat3, mkdir as mkdir4, open as open2, readFile as readFile6, rmdir as rmdir2, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
533
539
  import { resolve as resolve3 } from "node:path";
534
540
 
535
541
  // packages/cli-core/src/config/models.ts
@@ -766,8 +772,6 @@ process.on("SIGTERM", stop);
766
772
  let runtime;
767
773
  try {
768
774
  runtime = await BuddyServer.start({
769
- buddyId: process.env.BUDDY_ID,
770
- token: process.env.BUDDY_TOKEN,
771
775
  dataRequirements: config.datasets ?? [],
772
776
  buddy: createBuddyOptions,
773
777
  });
@@ -786,6 +790,32 @@ try {
786
790
  }
787
791
  `;
788
792
  }
793
+ function legacyPlatformStartTemplate() {
794
+ return platformStartTemplate().replace(" dataRequirements: config.datasets ?? [],", " buddyId: process.env.BUDDY_ID,\n token: process.env.BUDDY_TOKEN,\n dataRequirements: config.datasets ?? [],");
795
+ }
796
+ async function migrateRuntimeStartup(projectRoot) {
797
+ const packagePath = resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
798
+ const entryPath = resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY);
799
+ for (const path of [packagePath, entryPath]) {
800
+ if (!(await lstat3(path)).isFile()) throw new Error("\u542F\u52A8\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u7B26\u53F7\u94FE\u63A5");
801
+ }
802
+ const pkg = JSON.parse(await readFile6(packagePath, "utf8"));
803
+ if (!runtimeUsesEnvironmentIdentity(pkg)) return false;
804
+ const current = await readFile6(entryPath, "utf8");
805
+ const latest = platformStartTemplate();
806
+ const legacy = legacyPlatformStartTemplate();
807
+ let changed2 = false;
808
+ if (current.replace(/\r\n/gu, "\n") === legacy) {
809
+ await writeFile5(entryPath, latest, "utf8");
810
+ changed2 = true;
811
+ }
812
+ if (pkg.scripts?.start === "node start.mjs") {
813
+ pkg.scripts.start = "node --env-file-if-exists=.env start.mjs";
814
+ await writeFile5(packagePath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
815
+ changed2 = true;
816
+ }
817
+ return changed2;
818
+ }
789
819
  async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
790
820
  const path = resolve3(projectRoot, BUDDY_PLATFORM_AGENT_ENTRY);
791
821
  const hasAlternateLockfile = (await Promise.all(["pnpm-lock.yaml", "yarn.lock"].map(async (name2) => {
@@ -804,7 +834,9 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
804
834
  { path: resolve3(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate() },
805
835
  { path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile6(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
806
836
  ...hasAlternateLockfile ? [] : [{ path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK), content: await readFile6(new URL("../../resources/agent-template/package-lock.json", import.meta.url), "utf8") }],
807
- { path: resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() }
837
+ { path: resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() },
838
+ { path: resolve3(projectRoot, ".gitignore"), content: "node_modules/\n/.env\n" },
839
+ { path: resolve3(projectRoot, ".env.example"), content: "# \u9996\u6B21\u8FD0\u884C buddy-cli dev \u6216\u5728\u540E\u53F0\u542F\u52A8 DEV \u65F6\uFF0CCLI \u4F1A\u51C6\u5907 .env\u3002\nBUDDY_ID=\nBUDDY_TOKEN=\n# \u53EF\u9009\uFF1A\u4F7F\u7528\u5176\u4ED6\u5E73\u53F0\u65F6\u8BBE\u7F6E MLB_GATEWAY_URL\u3002\n" }
808
840
  ];
809
841
  const handles = [];
810
842
  const createdDirectories = [];
@@ -847,12 +879,17 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
847
879
  throw new Error("\u5DF2\u6709 package.json \u4E0E\u5F85\u8865\u9F50\u7684\u9501\u6587\u4EF6\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u7528\u5DE5\u7A0B\u7684\u5305\u7BA1\u7406\u5668\u6062\u590D\u5339\u914D\u7684\u4F9D\u8D56\u6587\u4EF6\u540E\u91CD\u8BD5");
848
880
  }
849
881
  }
882
+ const effectivePackage = handles.some((file) => file.path === packageFile.path) ? packageFile.content : await readFile6(packageFile.path, "utf8");
883
+ if (!runtimeUsesEnvironmentIdentity(JSON.parse(effectivePackage))) {
884
+ files.find((file) => file.path === resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY)).content = legacyPlatformStartTemplate();
885
+ }
850
886
  for (const { path: filePath, handle } of handles) {
851
887
  const file = files.find((candidate) => candidate.path === filePath);
852
888
  await handle.writeFile(file.content, "utf8");
853
889
  await handle.sync();
854
890
  }
855
- return Object.freeze({ path, created: handles.length > 0 || createdDirectories.length > 0 });
891
+ const migrated = await migrateRuntimeStartup(projectRoot);
892
+ return Object.freeze({ path, created: migrated || handles.length > 0 || createdDirectories.length > 0 });
856
893
  } catch (cause) {
857
894
  await Promise.all(handles.map(({ handle }) => handle.close().catch(() => void 0)));
858
895
  await Promise.all(handles.map(({ path: createdPath }) => unlink3(createdPath).catch(() => void 0)));
@@ -1635,7 +1672,7 @@ ${DATASETS_COMMAND_HELP}`);
1635
1672
 
1636
1673
  // packages/cli-core/src/commands/knowledge.ts
1637
1674
  import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
1638
- import { lstat as lstat7, mkdir as mkdir6, readFile as readFile8, rename as rename5, unlink as unlink5, writeFile as writeFile5 } from "node:fs/promises";
1675
+ import { lstat as lstat7, mkdir as mkdir6, readFile as readFile8, rename as rename5, unlink as unlink5, writeFile as writeFile6 } from "node:fs/promises";
1639
1676
  import { dirname as dirname2, join as join8, resolve as resolve8 } from "node:path";
1640
1677
  var MANIFEST = "knowledge-manifest.json";
1641
1678
  var INDEX = "resources/knowledge/index.md";
@@ -1705,7 +1742,7 @@ async function atomicWrite(root, path, value) {
1705
1742
  const full = await safePath(root, path);
1706
1743
  await mkdir6(dirname2(full), { recursive: true });
1707
1744
  const temporary = `${full}.${randomUUID4()}.tmp`;
1708
- await writeFile5(temporary, value, { flag: "wx", mode: 384 });
1745
+ await writeFile6(temporary, value, { flag: "wx", mode: 384 });
1709
1746
  try {
1710
1747
  await rename5(temporary, full);
1711
1748
  } finally {
@@ -1947,11 +1984,11 @@ ${KNOWLEDGE_HELP}`);
1947
1984
  }
1948
1985
 
1949
1986
  // packages/cli-core/src/index.ts
1950
- import { join as join15, resolve as resolve16 } from "node:path";
1987
+ import { join as join16, resolve as resolve16 } from "node:path";
1951
1988
 
1952
1989
  // packages/cli-core/src/init/creator.ts
1953
1990
  import { randomUUID as randomUUID5 } from "node:crypto";
1954
- import { link as link2, lstat as lstat8, mkdir as mkdir7, readFile as readFile9, unlink as unlink6, writeFile as writeFile6 } from "node:fs/promises";
1991
+ import { link as link2, lstat as lstat8, mkdir as mkdir7, readFile as readFile9, unlink as unlink6, writeFile as writeFile7 } from "node:fs/promises";
1955
1992
  import { join as join9 } from "node:path";
1956
1993
  import { fileURLToPath as fileURLToPath2 } from "node:url";
1957
1994
 
@@ -2022,7 +2059,7 @@ ${KNOWLEDGE_GUIDE}
2022
2059
  | \u56DE\u7B54\u65F6\u9700\u8981\u53C2\u8003\u7684\u5386\u53F2\u3001\u8BA1\u5212\u548C\u72B6\u6001 | Runtime \u4F1A\u4ECE MLB \u91CD\u5EFA\u4F1A\u8BDD\u5386\u53F2\uFF1B\u957F\u671F\u8BA1\u5212\u548C\u7ED3\u6784\u5316\u72B6\u6001\u4E0D\u80FD\u53EA\u4F9D\u8D56\u5B83\u4E00\u76F4\u7559\u5728\u6700\u8FD1\u804A\u5929\u91CC\u3002\u6309\u9700\u6C42\u4F7F\u7528 Memory\u3001\u6388\u6743\u6570\u636E\u6216\u4E1A\u52A1 Tool\uFF0C\u4E0D\u8981\u627F\u8BFA\u9ED8\u8BA4\u914D\u7F6E\u5DF2\u7ECF\u8986\u76D6\u3002 |
2023
2060
  | \u6A21\u578B\u548C\u5E73\u53F0\u8D44\u6E90 | \u5DF2\u786E\u5B9A\u7684\u6A21\u578B\u76F4\u63A5\u6CBF\u7528\uFF1B\u672A\u6307\u5B9A\u65F6\u67E5\u8BE2 \`buddy-cli models\`\uFF0C\u6838\u5BF9\u53EF\u7528\u6027\u5E76\u91C7\u7528\u6EE1\u8DB3\u9700\u6C42\u7684\u9009\u62E9\uFF0C\u4E0D\u9ED8\u8BA4\u518D\u95EE\u4E00\u8F6E\u9009\u578B\u95EE\u9898\uFF0C\u4E5F\u4E0D\u7F16\u9020\u4EF7\u683C\u6216\u80FD\u529B\u3002\u6A21\u677F\u628A\u914D\u7F6E\u4E2D\u7684\u6A21\u578B\u4EA4\u7ED9 \`initialState.model\`\uFF1B\u81EA\u5B9A\u4E49\u5DE5\u5382\u4E5F\u53EF\u6309\u4F1A\u8BDD\u9009\u62E9\u53D7\u652F\u6301\u6A21\u578B\uFF1B\u4F1A\u4EA7\u751F\u65B0\u7684\u8D39\u7528\u3001\u6570\u636E\u4F7F\u7528\u6216\u6743\u9650\u8FB9\u754C\u65F6\u5148\u786E\u8BA4\u3002 |
2024
2061
 
2025
- \`src/buddy-options.mjs\` \u662F\u6BCF\u573A\u4F1A\u8BDD\u7684\u4E1A\u52A1\u88C5\u914D\u5165\u53E3\uFF0C\u5BFC\u51FA \`createBuddyOptions(conversation)\`\uFF0C\u8FD4\u56DE \`initialState\`\u3001\u5728 \`initialState.tools\` \u6CE8\u518C\u7684\u4E1A\u52A1\u53CA\u5E73\u53F0\u5DE5\u5177\u548C\u53EF\u9009\u56DE\u5408\u94A9\u5B50\u3002\`start.mjs\` \u4ECE \`./src/buddy-options.mjs\` \u5BFC\u5165\u5DE5\u5382\u5E76\u4F20\u7ED9 \`BuddyServer.start({ buddyId: process.env.BUDDY_ID, token: process.env.BUDDY_TOKEN, dataRequirements: config.datasets ?? [], buddy: createBuddyOptions })\`\uFF1B\u7EC4\u88C5\u5668\u8BFB\u53D6 \`buddy.agent.json.model\`\uFF0C\u7701\u7565\u65F6\u7528 \`kimi-k2.6\`\uFF0C\u653E\u5165 \`initialState.model\`\uFF1B\u7528 \`new URL("../agent.md", import.meta.url)\` \u8BFB\u53D6\u6839\u76EE\u5F55 Prompt\u3002\u9ED8\u8BA4\u6A21\u677F\u53EA\u662F\u8D77\u70B9\uFF0C\u53EA\u6539\u8BF4\u660E\u4E0D\u7B49\u4E8E\u6539\u53D8\u4E86\u4FDD\u5B58\u3001\u67E5\u8BE2\u6216\u5904\u7406\u903B\u8F91\u3002
2062
+ \`src/buddy-options.mjs\` \u662F\u6BCF\u573A\u4F1A\u8BDD\u7684\u4E1A\u52A1\u88C5\u914D\u5165\u53E3\uFF0C\u5BFC\u51FA \`createBuddyOptions(conversation)\`\uFF0C\u8FD4\u56DE \`initialState\`\u3001\u5728 \`initialState.tools\` \u6CE8\u518C\u7684\u4E1A\u52A1\u53CA\u5E73\u53F0\u5DE5\u5177\u548C\u53EF\u9009\u56DE\u5408\u94A9\u5B50\u3002\`start.mjs\` \u4ECE \`./src/buddy-options.mjs\` \u5BFC\u5165\u5DE5\u5382\u5E76\u4F20\u7ED9 \`BuddyServer.start({ dataRequirements: config.datasets ?? [], buddy: createBuddyOptions })\`\uFF1B\u7EC4\u88C5\u5668\u8BFB\u53D6 \`buddy.agent.json.model\`\uFF0C\u7701\u7565\u65F6\u7528 \`kimi-k2.6\`\uFF0C\u653E\u5165 \`initialState.model\`\uFF1B\u7528 \`new URL("../agent.md", import.meta.url)\` \u8BFB\u53D6\u6839\u76EE\u5F55 Prompt\u3002\u9ED8\u8BA4\u6A21\u677F\u53EA\u662F\u8D77\u70B9\uFF0C\u53EA\u6539\u8BF4\u660E\u4E0D\u7B49\u4E8E\u6539\u53D8\u4E86\u4FDD\u5B58\u3001\u67E5\u8BE2\u6216\u5904\u7406\u903B\u8F91\u3002 Runtime 0.16.0 \u4ECE\u73AF\u5883\u53D8\u91CF\u8BFB\u53D6\u8EAB\u4EFD\u548C\u4EE4\u724C\uFF1B\u9996\u6B21\u542F\u52A8 DEV \u65F6 CLI \u51C6\u5907\u5DE5\u7A0B \`.env\`\uFF0CNode \u7528 \`--env-file-if-exists=.env\` \u52A0\u8F7D\u3002\u4E0D\u8981\u5C06 token \u5199\u5165\u4E1A\u52A1\u4EE3\u7801\u3002
2026
2063
 
2027
2064
  ### \u6309\u76EE\u5F55\u804C\u8D23\u7EC4\u7EC7\u5B9E\u73B0
2028
2065
 
@@ -2052,11 +2089,11 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
2052
2089
 
2053
2090
  \u5E73\u53F0\u80FD\u529B\u8981\u4EE5\u5B9E\u9645\u63A5\u5165\u4E3A\u51C6\u3002\u5F53\u524D Runtime \u63D0\u4F9B\u4F1A\u8BDD\u6D88\u606F\u3001Memory\u3001\u6388\u6743\u6570\u636E\u3001\u5C0F\u6302\u4EF6\u548C\u672C\u5730 Markdown \u8D44\u6599\u80FD\u529B\uFF1B\u6CA1\u6709\u63A5\u901A\u7684 Files\u3001Knowledge \u4E0D\u80FD\u56E0\u624B\u518C\u63D0\u5230\u5C31\u5BA3\u79F0\u53EF\u7528\u3002\u666E\u901A Tool \u4E5F\u4E0D\u4EE3\u8868\u5DF2\u7ECF\u63D0\u4F9B\u5B9A\u65F6\u3001\u957F\u671F\u4EFB\u52A1\u3001\u540E\u53F0\u8C03\u5EA6\u6216\u4E3B\u52A8\u89E6\u8FBE\u3002\u624B\u518C\u63CF\u8FF0\u7684\u4ED8\u8D39\u3001\u53D1\u5E03\u7B49\u670D\u52A1\u8BBE\u8BA1\u4E5F\u4E0D\u6784\u6210\u6267\u884C\u6536\u8D39\u6216\u53D1\u5E03\u52A8\u4F5C\u7684\u6388\u6743\u3002
2054
2091
 
2055
- \u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002Runtime 0.12.2 \u542B 10 \u9879\uFF0CCLI \u4E0D\u590D\u5236\u679A\u4E3E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`buddy.agent.json.datasets\`\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0C\u7528\u9014\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u6700\u591A 200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
2092
+ \u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002\u4EE5\u5DE5\u7A0B\u5B89\u88C5\u7248\u672C\u5BFC\u51FA\u7684\u76EE\u5F55\u4E3A\u51C6\uFF0CCLI \u4E0D\u590D\u5236\u679A\u4E3E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`buddy.agent.json.datasets\`\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0C\u7528\u9014\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u6700\u591A 200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
2056
2093
 
2057
2094
  \`start.mjs\` \u5C06\u58F0\u660E\u4EA4\u7ED9 \`StartOptions.dataRequirements\`\u3002Runtime \u5728\u5B9E\u9645\u6570\u636E\u67E5\u8BE2\u3001HealthKit \u6388\u6743\u548C\u4E3B\u52A8\u670D\u52A1\u8BF7\u6C42\u4E2D\u643A\u5E26\u5B8C\u6574\u58F0\u660E\uFF0C\u7531 Server \u6821\u9A8C\u8303\u56F4\u4E0E\u7528\u6237\u540C\u610F\uFF1B\u586B\u5199\u914D\u7F6E\u4E0D\u8868\u793A\u5DF2\u7ECF\u6388\u6743\u3002\u670D\u52A1\u7AEF\u4ECE\u4E0A\u4F20\u5305\u89E3\u6790\u5E76\u7ED1\u5B9A\u53D1\u5E03\u7248\u672C\u4ECD\u5F85\u5B9E\u73B0\u3002
2058
2095
 
2059
- \u6A21\u578B\u9700\u8981\u67E5\u6570\u636E\u65F6\uFF0C\u5728 \`src/buddy-options.mjs\` \u7684 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.data_access_query\`\uFF1B\u9700\u8981\u5411\u7528\u6237\u7533\u8BF7\u65F6\u52A0\u5165 \`conversation.tools.data_access_request\`\uFF0C\u4F4D\u7F6E\u3001\u65E5\u5386\u7684\u4E00\u6B21\u6027\u7ED3\u679C\u901A\u8FC7 \`data_access_read_result\` \u8BFB\u53D6\uFF0CHealthKit \u5219\u91CD\u65B0\u67E5\u8BE2 Dataset\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query/request/readResult\`\u3002\u65B0\u5EFA\u5DE5\u7A0B\u52A8\u6001\u9009\u62E9\u516C\u5171 npm latest \u5E76\u9501\u5B9A\u51C6\u786E\u7248\u672C\uFF1B\u8054\u7F51\u5931\u8D25\u65F6\u660E\u786E\u63D0\u793A\u4F7F\u7528\u968F CLI \u9644\u5E26\u7684 Runtime 0.12.2\u3002\u5DF2\u6709\u5DE5\u7A0B\u901A\u8FC7\u5305\u7BA1\u7406\u5668\u663E\u5F0F\u5347\u7EA7\u4F9D\u8D56\u3002
2096
+ \u6A21\u578B\u9700\u8981\u67E5\u6570\u636E\u65F6\uFF0C\u5728 \`src/buddy-options.mjs\` \u7684 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.data_access_query\`\uFF1B\u9700\u8981\u5411\u7528\u6237\u7533\u8BF7\u65F6\u52A0\u5165 \`conversation.tools.data_access_request\`\uFF0C\u4F4D\u7F6E\u3001\u65E5\u5386\u7684\u4E00\u6B21\u6027\u7ED3\u679C\u901A\u8FC7 \`data_access_read_result\` \u8BFB\u53D6\uFF0CHealthKit \u5219\u91CD\u65B0\u67E5\u8BE2 Dataset\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query/request/readResult\`\u3002\u65B0\u5EFA\u5DE5\u7A0B\u52A8\u6001\u9009\u62E9\u516C\u5171 npm latest \u5E76\u9501\u5B9A\u51C6\u786E\u7248\u672C\uFF1B\u8054\u7F51\u5931\u8D25\u65F6\u660E\u786E\u63D0\u793A\u4F7F\u7528\u968F CLI \u9644\u5E26\u7684 Runtime 0.16.0\u3002\u5DF2\u6709\u5DE5\u7A0B\u901A\u8FC7\u5305\u7BA1\u7406\u5668\u663E\u5F0F\u5347\u7EA7\u4F9D\u8D56\u3002
2060
2097
 
2061
2098
  \u5C0F\u6302\u4EF6\u7684\u6A21\u578B\u5DE5\u5177\u4E3A \`widget_create\`\u3001\`widget_read\`\uFF08\u6574\u4E2A\u5C0F\u6302\u4EF6\uFF09\u3001\`widget_read_module\`\uFF08\u4E00\u4E2A\u6A21\u5757\uFF09\u3001\`widget_rename\`\u3001\`widget_write_record\`\u3001\`widget_delete_record\`\u3001\`widget_delete\`\uFF08\u6574\u4E2A\u5C0F\u6302\u4EF6\u8FDE\u8BB0\u5F55\uFF09\u548C \`widget_send\`\uFF0C\u6309\u4E1A\u52A1\u9700\u8981\u6CE8\u518C\u5230 \`initialState.tools\`\u3002\u4FEE\u6539\u8BB0\u5F55\u7528 \`conversation.widget.writeRecord(id, input)\`\uFF1B\u5220\u4E00\u6761\u8BB0\u5F55\u7528 \`conversation.widget.deleteRecord(id, module, recordId)\`\uFF0C\u4E0D\u80FD\u7528\u5220\u9664\u6574\u4E2A\u5C0F\u6302\u4EF6\u7684 \`conversation.widget.delete(id)\` \u4EE3\u66FF\u3002\u4E24\u4E2A\u8BFB\u53D6\u5DE5\u5177\u53EF\u7528\u4E8E\u4E3B\u52A8\u56DE\u5408\uFF0C\u5176\u4F59\u516D\u4E2A\u5199\u5165\u5DE5\u5177\u7531 Runtime \u963B\u6B62\u5728\u4E3B\u52A8\u56DE\u5408\u6267\u884C\u3002
2062
2099
 
@@ -2153,7 +2190,7 @@ async function safeRead(path) {
2153
2190
  }
2154
2191
  async function writeOnce(path, bytes) {
2155
2192
  const temporary = `${path}.${randomUUID5()}.tmp`;
2156
- await writeFile6(temporary, bytes, { flag: "wx", mode: 384 });
2193
+ await writeFile7(temporary, bytes, { flag: "wx", mode: 384 });
2157
2194
  try {
2158
2195
  await link2(temporary, path).catch((cause) => {
2159
2196
  if (cause.code !== "EEXIST") throw cause;
@@ -2376,6 +2413,13 @@ function resolvePlatformUrl(options = {}) {
2376
2413
  return normalizePlatformUrl(options.override ?? configured ?? DEFAULT_MLB_TEST_URL);
2377
2414
  }
2378
2415
 
2416
+ // packages/cli-core/src/dev/project-env.ts
2417
+ import { constants } from "node:fs";
2418
+ import { open as open4, rename as rename6, unlink as unlink7 } from "node:fs/promises";
2419
+ import { randomUUID as randomUUID6 } from "node:crypto";
2420
+ import { join as join10 } from "node:path";
2421
+ import { parseEnv } from "node:util";
2422
+
2379
2423
  // packages/cli-core/src/dev/errors.ts
2380
2424
  var BuddyDevError = class extends Error {
2381
2425
  code;
@@ -2404,6 +2448,124 @@ function throwIfDevAborted(signal) {
2404
2448
  if (signal?.aborted) throw abortedDevError(signal);
2405
2449
  }
2406
2450
 
2451
+ // packages/cli-core/src/dev/project-env.ts
2452
+ function invalid(message) {
2453
+ return new BuddyDevError({ code: "DEV_CONFIG_INVALID", phase: "config", message });
2454
+ }
2455
+ async function readLocalFile(path) {
2456
+ let file;
2457
+ try {
2458
+ file = await open4(path, constants.O_RDONLY | constants.O_NOFOLLOW);
2459
+ const stat2 = await file.stat();
2460
+ if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > 256 * 1024) throw invalid("\u672C\u5730\u914D\u7F6E\u5FC5\u987B\u662F\u5C0F\u4E8E 256 KB \u7684\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u94FE\u63A5\u3002");
2461
+ return await file.readFile("utf8");
2462
+ } catch (cause) {
2463
+ if (cause.code === "ENOENT") return "";
2464
+ if (cause instanceof BuddyDevError) throw cause;
2465
+ throw invalid("\u65E0\u6CD5\u8BFB\u53D6\u5DE5\u7A0B\u672C\u5730\u914D\u7F6E\uFF0C\u8BF7\u68C0\u67E5 .env \u548C .gitignore \u7684\u6587\u4EF6\u7C7B\u578B\u4E0E\u6743\u9650\u3002");
2466
+ } finally {
2467
+ await file?.close();
2468
+ }
2469
+ }
2470
+ async function readProjectEnvironment(projectRoot, buddyId) {
2471
+ const source = await readLocalFile(join10(projectRoot, ".env"));
2472
+ let values;
2473
+ try {
2474
+ values = parseEnv(source);
2475
+ } catch {
2476
+ throw invalid("\u5DE5\u7A0B .env \u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002");
2477
+ }
2478
+ if (values.BUDDY_ID && values.BUDDY_ID !== buddyId) throw invalid(".env \u7684 BUDDY_ID \u4E0E buddy.agent.json \u4E0D\u4E00\u81F4\uFF0C\u8BF7\u5148\u4FEE\u6B63\u5DE5\u7A0B\u8EAB\u4EFD\u3002");
2479
+ return values;
2480
+ }
2481
+ async function projectBuddyToken(projectRoot, buddyId, gatewayUrl) {
2482
+ const values = await readProjectEnvironment(projectRoot, buddyId);
2483
+ if (!values.BUDDY_TOKEN) return void 0;
2484
+ if (!values.BUDDY_ID) throw invalid(".env \u4E2D\u6709 BUDDY_TOKEN\uFF0C\u4F46\u7F3A\u5C11 BUDDY_ID\uFF0C\u8BF7\u8865\u9F50\u540E\u91CD\u8BD5\u3002");
2485
+ if (values.MLB_GATEWAY_URL) {
2486
+ let gateway;
2487
+ try {
2488
+ gateway = normalizePlatformUrl(values.MLB_GATEWAY_URL);
2489
+ } catch {
2490
+ throw invalid(".env \u4E2D\u7684 MLB_GATEWAY_URL \u65E0\u6548\u3002");
2491
+ }
2492
+ if (gateway.href !== gatewayUrl.href) throw invalid(".env \u7684\u5E73\u53F0\u5730\u5740\u4E0E\u672C\u6B21\u542F\u52A8\u4E0D\u540C\uFF1B\u8BF7\u786E\u8BA4\u5E73\u53F0\u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u5F00\u53D1\u4EE4\u724C\u3002");
2493
+ }
2494
+ if (!values.BUDDY_TOKEN.trim() || /[\u0000-\u001f\u007f]/u.test(values.BUDDY_TOKEN)) throw invalid(".env \u4E2D\u7684\u5F00\u53D1\u4EE4\u724C\u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u3002");
2495
+ return values.BUDDY_TOKEN;
2496
+ }
2497
+ function quote(value) {
2498
+ if (/[\u0000-\u001f\u007f]/u.test(value)) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26\u3002");
2499
+ const delimiter = ["'", '"', "`"].find((character) => !value.includes(character));
2500
+ if (!delimiter) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u5305\u542B\u65E0\u6CD5\u5199\u5165 .env \u7684\u5F15\u53F7\u7EC4\u5408\u3002");
2501
+ return `${delimiter}${value}${delimiter}`;
2502
+ }
2503
+ function updateValues(source, values) {
2504
+ const assignment = /^[\t ]*(?:export[\t ]+)?([A-Za-z_][A-Za-z0-9_]*)[\t ]*=[\t ]*/gm;
2505
+ let output = "", cursor = 0, match;
2506
+ const written = /* @__PURE__ */ new Set();
2507
+ while (match = assignment.exec(source)) {
2508
+ const valueStart = assignment.lastIndex;
2509
+ let end = source.indexOf("\n", valueStart);
2510
+ if (end < 0) end = source.length;
2511
+ let commentStart = valueStart;
2512
+ const delimiter = source[valueStart];
2513
+ if (delimiter && ["'", '"', "`"].includes(delimiter)) {
2514
+ const close = source.indexOf(delimiter, valueStart + 1);
2515
+ if (close < 0) throw invalid(".env \u4E2D\u6709\u672A\u95ED\u5408\u7684\u5F15\u53F7\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002");
2516
+ commentStart = close + 1;
2517
+ end = source.indexOf("\n", close + 1);
2518
+ if (end < 0) end = source.length;
2519
+ }
2520
+ assignment.lastIndex = end;
2521
+ const name = match[1];
2522
+ if (!(name in values)) continue;
2523
+ const comment = source.slice(commentStart, end).match(/[\t ]*#[^\r\n]*/u)?.[0] ?? "";
2524
+ output += source.slice(cursor, match.index);
2525
+ output += written.has(name) ? comment : `${name}=${quote(values[name])}${comment ? ` ${comment.trimStart()}` : ""}`;
2526
+ if (source[end - 1] === "\r") output += "\r";
2527
+ cursor = end;
2528
+ written.add(name);
2529
+ }
2530
+ output += source.slice(cursor);
2531
+ const newline = source.includes("\r\n") ? "\r\n" : "\n";
2532
+ for (const [name, value] of Object.entries(values)) if (!written.has(name)) {
2533
+ if (output && !output.endsWith("\n")) output += newline;
2534
+ output += `${name}=${quote(value)}${newline}`;
2535
+ }
2536
+ const parsed = parseEnv(output);
2537
+ if (Object.entries(values).some(([name, value]) => parsed[name] !== value)) throw invalid("\u65E0\u6CD5\u5B8C\u6574\u66F4\u65B0 .env\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u683C\u5F0F\u3002");
2538
+ return output;
2539
+ }
2540
+ async function replaceFile(path, contents, mode) {
2541
+ const temporary = `${path}.${randomUUID6()}.tmp`;
2542
+ let file;
2543
+ try {
2544
+ file = await open4(temporary, "wx", mode);
2545
+ await file.writeFile(contents, "utf8");
2546
+ await file.sync();
2547
+ await file.close();
2548
+ file = void 0;
2549
+ await rename6(temporary, path);
2550
+ } finally {
2551
+ await file?.close();
2552
+ await unlink7(temporary).catch((cause) => {
2553
+ if (cause.code !== "ENOENT") throw cause;
2554
+ });
2555
+ }
2556
+ }
2557
+ async function writeProjectEnvironment(projectRoot, values) {
2558
+ await readProjectEnvironment(projectRoot, values.BUDDY_ID);
2559
+ const envPath = join10(projectRoot, ".env"), ignorePath = join10(projectRoot, ".gitignore");
2560
+ const contents = updateValues(await readLocalFile(envPath), values);
2561
+ const ignored = await readLocalFile(ignorePath);
2562
+ if (ignored.trimEnd().split(/\r?\n/u).at(-1) !== "/.env") {
2563
+ await replaceFile(ignorePath, `${ignored}${ignored && !ignored.endsWith("\n") ? "\n" : ""}/.env
2564
+ `, 420);
2565
+ }
2566
+ await replaceFile(envPath, contents, 384);
2567
+ }
2568
+
2407
2569
  // packages/cli-core/src/dev/app-server.ts
2408
2570
  var MAX_JSON_BODY_LENGTH = 1048576;
2409
2571
  function safeCredential(value, name) {
@@ -2465,10 +2627,14 @@ var MlbDevRegistrationClient = class {
2465
2627
  #baseUrl;
2466
2628
  #developerToken;
2467
2629
  #fetch;
2630
+ #tokenStoreFor;
2631
+ #refreshToken;
2468
2632
  constructor(options) {
2469
2633
  this.#baseUrl = normalizePlatformUrl(options.baseUrl);
2470
2634
  this.#developerToken = safeCredential(options.developerToken, "developerToken");
2471
2635
  this.#fetch = options.fetch ?? globalThis.fetch;
2636
+ this.#tokenStoreFor = options.tokenStoreFor;
2637
+ this.#refreshToken = options.refreshToken ?? false;
2472
2638
  if (typeof this.#fetch !== "function") {
2473
2639
  throw new TypeError("A Fetch API implementation is required");
2474
2640
  }
@@ -2538,6 +2704,18 @@ var MlbDevRegistrationClient = class {
2538
2704
  message: "buddy.agent.json \u4E2D\u7684 buddyId \u65E0\u6548\u3002"
2539
2705
  });
2540
2706
  }
2707
+ options.signal.throwIfAborted();
2708
+ if (request.projectRoot) {
2709
+ await readProjectEnvironment(request.projectRoot, request.devAgentId);
2710
+ const localToken = this.#refreshToken ? void 0 : await projectBuddyToken(request.projectRoot, request.devAgentId, this.#baseUrl);
2711
+ if (localToken !== void 0) return Object.freeze({ devAgentId: request.devAgentId, appServerUrl: new URL(this.#baseUrl), agentToken: localToken });
2712
+ }
2713
+ const store = this.#tokenStoreFor?.(request.devAgentId);
2714
+ const cached = this.#refreshToken ? void 0 : await store?.load();
2715
+ if (cached !== void 0) {
2716
+ options.signal.throwIfAborted();
2717
+ return Object.freeze({ devAgentId: request.devAgentId, appServerUrl: new URL(this.#baseUrl), agentToken: safeCredential(cached, "agentToken") });
2718
+ }
2541
2719
  const body = object2(await this.#request(
2542
2720
  `/cli/buddies/${encodeURIComponent(request.devAgentId)}`,
2543
2721
  {
@@ -2552,10 +2730,13 @@ var MlbDevRegistrationClient = class {
2552
2730
  message: "\u642D\u5B50\u8BE6\u60C5\u54CD\u5E94\u7F3A\u5C11\u5339\u914D\u7684 id \u6216 Buddy token\u3002"
2553
2731
  });
2554
2732
  }
2733
+ const token = safeCredential(body.token, "agentToken");
2734
+ options.signal.throwIfAborted();
2735
+ if (!request.projectRoot) await store?.save(token);
2555
2736
  return Object.freeze({
2556
2737
  devAgentId: request.devAgentId,
2557
2738
  appServerUrl: new URL(this.#baseUrl),
2558
- agentToken: safeCredential(body.token, "agentToken")
2739
+ agentToken: token
2559
2740
  });
2560
2741
  }
2561
2742
  async listOnline(options) {
@@ -2653,7 +2834,7 @@ function buildAgentEnvironment(options) {
2653
2834
  // packages/cli-core/src/dev/orchestrator.ts
2654
2835
  import { createHash as createHash4 } from "node:crypto";
2655
2836
  import { readFile as readFile10 } from "node:fs/promises";
2656
- import { join as join11, resolve as resolve10 } from "node:path";
2837
+ import { join as join12, resolve as resolve10 } from "node:path";
2657
2838
 
2658
2839
  // packages/cli-core/src/dev/launch.ts
2659
2840
  import { lstatSync, readFileSync } from "node:fs";
@@ -2698,9 +2879,10 @@ async function officialAgentLaunchPlan(input) {
2698
2879
  cause
2699
2880
  });
2700
2881
  }
2882
+ await migrateRuntimeStartup(input.projectRoot);
2701
2883
  return Object.freeze({
2702
2884
  command: process.execPath,
2703
- args: Object.freeze([entry2])
2885
+ args: Object.freeze(["--env-file-if-exists=.env", entry2])
2704
2886
  });
2705
2887
  }
2706
2888
 
@@ -2903,14 +3085,14 @@ function processTreeControllerFor(platform) {
2903
3085
  // packages/cli-core/src/dev/instance-lock.ts
2904
3086
  import { createHash as createHash3 } from "node:crypto";
2905
3087
  import { homedir as homedir2 } from "node:os";
2906
- import { join as join10 } from "node:path";
3088
+ import { join as join11 } from "node:path";
2907
3089
  function alreadyRunningError() {
2908
3090
  const message = "\u8FD9\u4E2A\u642D\u5B50\u5DF2\u6709 DEV \u5B9E\u4F8B\u5728\u8FD0\u884C\u3002\u8BF7\u5148\u5728\u539F\u9884\u89C8\u9875\u70B9\u51FB\u300C\u505C\u6B62 DEV\u300D\uFF0C\u6216\u5728\u8FD0\u884C dev \u7684\u7EC8\u7AEF\u6309 Ctrl+C\uFF0C\u518D\u542F\u52A8\u3002";
2909
3091
  return Object.assign(new BuddyDevError({ code: "DEV_ALREADY_RUNNING", phase: "launch", message }), { publicMessage: message });
2910
3092
  }
2911
3093
  async function acquireDevInstanceLock(options) {
2912
3094
  return acquireProcessLock({
2913
- directory: options.directory ?? join10(homedir2(), ".buddy", "dev-locks"),
3095
+ directory: options.directory ?? join11(homedir2(), ".buddy", "dev-locks"),
2914
3096
  key: createHash3("sha256").update(`${new URL(options.gatewayUrl).origin}
2915
3097
  ${options.devAgentId}`).digest("hex"),
2916
3098
  busyError: alreadyRunningError
@@ -2942,7 +3124,7 @@ function validateRegistration(value, expectedAgentId) {
2942
3124
  throw new BuddyDevError({
2943
3125
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
2944
3126
  phase: "registration",
2945
- message: "DEV \u6302\u53F7\u6CA1\u6709\u8FD4\u56DE\u5339\u914D\u7684 Buddy \u8EAB\u4EFD\u4E0E\u77ED\u671F Buddy token\u3002"
3127
+ message: "DEV \u6302\u53F7\u6CA1\u6709\u8FD4\u56DE\u5339\u914D\u7684 Buddy \u8EAB\u4EFD\u4E0E\u5F00\u53D1 Token\u3002"
2946
3128
  });
2947
3129
  }
2948
3130
  return value;
@@ -2979,6 +3161,7 @@ async function launchPlanFor(config, options, projectRoot, signal) {
2979
3161
  async function registerDevAgent(options) {
2980
3162
  try {
2981
3163
  return validateRegistration(await options.client.register({
3164
+ projectRoot: options.projectRoot,
2982
3165
  devAgentId: options.devAgentId,
2983
3166
  configSource: options.configSource,
2984
3167
  configDigest: options.configDigest
@@ -3169,7 +3352,7 @@ async function startBuddyDev(options) {
3169
3352
  let config;
3170
3353
  let configSource;
3171
3354
  try {
3172
- configSource = await readFile10(join11(projectRoot, BUDDY_AGENT_FILENAME), "utf8");
3355
+ configSource = await readFile10(join12(projectRoot, BUDDY_AGENT_FILENAME), "utf8");
3173
3356
  config = combineBuddyProject(parseBuddyAgentConfig(configSource));
3174
3357
  } catch (cause) {
3175
3358
  throw new BuddyDevError({
@@ -3179,8 +3362,10 @@ async function startBuddyDev(options) {
3179
3362
  cause
3180
3363
  });
3181
3364
  }
3365
+ await readProjectEnvironment(projectRoot, devAgentId);
3182
3366
  const launchPlan = await launchPlanFor(config, options, projectRoot, signal);
3183
3367
  const registration = await registerDevAgent({
3368
+ projectRoot,
3184
3369
  client: options.registrationClient,
3185
3370
  devAgentId,
3186
3371
  configSource,
@@ -3204,13 +3389,19 @@ async function startBuddyDev(options) {
3204
3389
  buddyToken: registration.agentToken,
3205
3390
  gatewayUrl: registration.appServerUrl
3206
3391
  });
3392
+ await writeProjectEnvironment(projectRoot, {
3393
+ BUDDY_ID: environment.BUDDY_ID,
3394
+ BUDDY_TOKEN: environment.BUDDY_TOKEN,
3395
+ MLB_GATEWAY_URL: environment.MLB_GATEWAY_URL
3396
+ });
3397
+ const { BUDDY_ID: _id, BUDDY_TOKEN: _token, MLB_GATEWAY_URL: _gateway, ...childEnvironment } = environment;
3207
3398
  const launcher = options.processLauncher ?? new NodeAgentProcessLauncher();
3208
3399
  processTree = options.processTree ?? processTreeControllerFor(platform);
3209
3400
  agentProcess = await launcher.spawn({
3210
3401
  command: launchPlan.command,
3211
3402
  args: launchPlan.args,
3212
3403
  cwd: projectRoot,
3213
- env: environment,
3404
+ env: childEnvironment,
3214
3405
  shell: false,
3215
3406
  detached: platform === "darwin",
3216
3407
  ...options.onLog === void 0 ? {} : {
@@ -3291,6 +3482,183 @@ function createBuddyDevStarter(options = {}) {
3291
3482
  });
3292
3483
  }
3293
3484
 
3485
+ // packages/cli-core/src/dev/token-store.ts
3486
+ import { createHash as createHash5 } from "node:crypto";
3487
+
3488
+ // packages/cli-core/src/cloud/credential-store.ts
3489
+ import { spawn } from "node:child_process";
3490
+ var DEFAULT_SERVICE = "com.xiaohongshu.buddy.developer-cli";
3491
+ var DEFAULT_ACCOUNT = "developer-session";
3492
+ var MAX_CREDENTIAL_BYTES = 32 * 1024;
3493
+ function safeLabel(value, fallback, name) {
3494
+ const result = value ?? fallback;
3495
+ if (!result || result !== result.trim() || /[\u0000-\u001f\u007f]/u.test(result) || result.length > 256) {
3496
+ throw new TypeError(`${name} is invalid`);
3497
+ }
3498
+ return result;
3499
+ }
3500
+ function serialize(token) {
3501
+ const value = JSON.stringify(token);
3502
+ if (Buffer.byteLength(value, "utf8") > MAX_CREDENTIAL_BYTES) {
3503
+ throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u4E91\u7AEF\u4F1A\u8BDD\u51ED\u636E\u8FC7\u5927\uFF0C\u672A\u4FDD\u5B58");
3504
+ }
3505
+ return value;
3506
+ }
3507
+ function parse(source) {
3508
+ if (Buffer.byteLength(source, "utf8") > MAX_CREDENTIAL_BYTES) {
3509
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3510
+ }
3511
+ let value;
3512
+ try {
3513
+ value = JSON.parse(source);
3514
+ } catch {
3515
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3516
+ }
3517
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3518
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3519
+ }
3520
+ const record2 = value;
3521
+ if (Object.keys(record2).length !== 3 || typeof record2.accessToken !== "string" || typeof record2.subject !== "string" || !Number.isSafeInteger(record2.expiresAt)) {
3522
+ throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3523
+ }
3524
+ return Object.freeze({
3525
+ accessToken: record2.accessToken,
3526
+ subject: record2.subject,
3527
+ expiresAt: record2.expiresAt
3528
+ });
3529
+ }
3530
+ async function runCredentialCommand(input) {
3531
+ return await new Promise((resolve17, reject) => {
3532
+ const child = spawn(input.command, [...input.args], {
3533
+ shell: false,
3534
+ windowsHide: true,
3535
+ stdio: ["pipe", "pipe", "pipe"]
3536
+ });
3537
+ const stdout = [];
3538
+ const stderr = [];
3539
+ let outputBytes = 0;
3540
+ const collect = (target, chunk) => {
3541
+ outputBytes += chunk.byteLength;
3542
+ if (outputBytes <= MAX_CREDENTIAL_BYTES) target.push(chunk);
3543
+ };
3544
+ child.stdout.on("data", (chunk) => collect(stdout, chunk));
3545
+ child.stderr.on("data", (chunk) => collect(stderr, chunk));
3546
+ child.once("error", reject);
3547
+ child.once("close", (code2) => resolve17({
3548
+ code: code2 ?? 1,
3549
+ stdout: Buffer.concat(stdout).toString("utf8"),
3550
+ stderr: Buffer.concat(stderr).toString("utf8")
3551
+ }));
3552
+ child.stdin.on("error", () => void 0);
3553
+ child.stdin.end(input.input ?? "");
3554
+ });
3555
+ }
3556
+ var SystemCredentialStore = class {
3557
+ #platform;
3558
+ #service;
3559
+ #account;
3560
+ #run;
3561
+ constructor(options = {}) {
3562
+ this.#platform = options.platform ?? process.platform;
3563
+ this.#service = safeLabel(options.service, DEFAULT_SERVICE, "service");
3564
+ this.#account = safeLabel(options.account, DEFAULT_ACCOUNT, "account");
3565
+ this.#run = options.commandRunner ?? runCredentialCommand;
3566
+ if (this.#platform !== "darwin") {
3567
+ throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D CLI V1 \u7684\u5B89\u5168\u51ED\u636E\u5B58\u50A8\u76EE\u524D\u53EA\u652F\u6301 macOS Keychain");
3568
+ }
3569
+ }
3570
+ async load() {
3571
+ const result = await this.#run({
3572
+ command: "security",
3573
+ args: ["find-generic-password", "-s", this.#service, "-a", this.#account, "-w"]
3574
+ });
3575
+ if (result.code === 44) return void 0;
3576
+ if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u8BFB\u53D6 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u51ED\u636E");
3577
+ const raw = result.stdout.trimEnd();
3578
+ return /^(?:[a-fA-F0-9]{2})+$/u.test(raw) ? Buffer.from(raw, "hex").toString("utf8") : raw;
3579
+ }
3580
+ async save(source) {
3581
+ if (!source || /[\u0000-\u001f\u007f]/u.test(source)) throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
3582
+ const line = ["add-generic-password", "-U", "-s", this.#service, "-a", this.#account, "-w", source].map((part) => `"${part.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"')}"`).join(" ") + "\n";
3583
+ if (Buffer.byteLength(line, "utf8") >= 4096) {
3584
+ throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u51ED\u636E\u8D85\u8FC7 macOS \u5199\u5165\u957F\u5EA6\u9650\u5236\uFF0C\u672A\u4FDD\u5B58\uFF1B\u8BF7\u8054\u7CFB\u5E73\u53F0\u5904\u7406");
3585
+ }
3586
+ const result = await this.#run({
3587
+ command: "security",
3588
+ args: ["-i", "-q"],
3589
+ input: line
3590
+ });
3591
+ if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u628A\u642D\u642D\u51ED\u636E\u5199\u5165 macOS \u94A5\u5319\u4E32");
3592
+ const saved = await this.load();
3593
+ if (!saved || saved !== source) throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u51ED\u636E\u5199\u5165\u540E\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5");
3594
+ }
3595
+ async clear() {
3596
+ const result = await this.#run({
3597
+ command: "security",
3598
+ args: ["delete-generic-password", "-s", this.#service, "-a", this.#account]
3599
+ });
3600
+ if (result.code !== 0 && result.code !== 44) {
3601
+ throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u6E05\u9664 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u51ED\u636E");
3602
+ }
3603
+ }
3604
+ };
3605
+ var SystemCloudTokenStore = class {
3606
+ #store;
3607
+ constructor(options = {}) {
3608
+ this.#store = new SystemCredentialStore(options);
3609
+ }
3610
+ async load() {
3611
+ const raw = await this.#store.load();
3612
+ return raw === void 0 ? void 0 : parse(raw);
3613
+ }
3614
+ async save(token) {
3615
+ await this.#store.save(serialize(token));
3616
+ }
3617
+ async clear() {
3618
+ await this.#store.clear();
3619
+ }
3620
+ };
3621
+
3622
+ // packages/cli-core/src/dev/token-store.ts
3623
+ var SystemBuddyTokenStore = class {
3624
+ #store;
3625
+ constructor(options) {
3626
+ if (![options.subject, options.buddyId].every((value) => value.trim() && !/[\u0000-\u001f\u007f]/u.test(value))) throw new TypeError("\u5F00\u53D1 Token \u7684\u8D26\u53F7\u548C\u642D\u5B50 ID \u65E0\u6548");
3627
+ const scope = JSON.stringify([normalizePlatformUrl(options.platformUrl).origin, options.subject, options.buddyId]);
3628
+ this.#store = new SystemCredentialStore({
3629
+ service: "com.xiaohongshu.buddy.developer-cli.dev-token",
3630
+ account: createHash5("sha256").update(scope).digest("hex"),
3631
+ platform: options.platform,
3632
+ commandRunner: options.commandRunner
3633
+ });
3634
+ }
3635
+ async load() {
3636
+ const raw = await this.#store.load();
3637
+ if (raw === void 0) return void 0;
3638
+ let value;
3639
+ try {
3640
+ value = JSON.parse(raw);
3641
+ } catch {
3642
+ throw corrupt();
3643
+ }
3644
+ if (typeof value !== "object" || value === null || Array.isArray(value) || Object.keys(value).length !== 1 || !("token" in value)) throw corrupt();
3645
+ return validateToken(value.token);
3646
+ }
3647
+ async save(token) {
3648
+ await this.#store.save(JSON.stringify({ token: validateToken(token) }));
3649
+ }
3650
+ async clear() {
3651
+ await this.#store.clear();
3652
+ }
3653
+ };
3654
+ function corrupt() {
3655
+ return new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u672C\u673A\u5F00\u53D1\u51ED\u636E\u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6");
3656
+ }
3657
+ function validateToken(value) {
3658
+ if (typeof value !== "string" || !value.trim() || /[\u0000-\u001f\u007f]/u.test(value) || value.length > 1024) throw corrupt();
3659
+ return value;
3660
+ }
3661
+
3294
3662
  // packages/cli-core/src/commands/dev.ts
3295
3663
  var DevCommandUsageError = class extends Error {
3296
3664
  constructor(message) {
@@ -3299,12 +3667,13 @@ var DevCommandUsageError = class extends Error {
3299
3667
  }
3300
3668
  };
3301
3669
  var DEV_COMMAND_HELP = `\u7528\u6CD5:
3302
- buddy-cli dev [--app-server <App Server URL>] [--directory <\u9879\u76EE\u76EE\u5F55>]
3670
+ buddy-cli dev [--app-server <App Server URL>] [--directory <\u9879\u76EE\u76EE\u5F55>] [--refresh-token]
3303
3671
 
3304
3672
  \u8BF4\u660E:
3305
3673
  \u672A\u914D\u7F6E\u5730\u5740\u65F6\u8FDE\u63A5 MLB \u6D4B\u8BD5\u73AF\u5883 ${DEFAULT_MLB_TEST_URL}\uFF08HTTP \u4EC5\u9650\u6D4B\u8BD5\uFF09\u3002
3306
3674
  CLI \u7EDF\u4E00\u542F\u52A8\u5E76\u7BA1\u7406\u5DE5\u7A0B\u4E2D\u7684\u5B98\u65B9 Runtime\u3002
3307
- DEV \u4F1A\u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u5F00\u53D1\u8005\u4F1A\u8BDD\uFF0C\u518D\u8BFB\u53D6\u5F53\u524D buddy.agent.json \u4E2D\u7684 buddyId \u5BF9\u5E94\u7684 Buddy token\u3002`;
3675
+ DEV \u4F1A\u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u5F00\u53D1\u8005\u4F1A\u8BDD\uFF0C\u5C06\u5F53\u524D\u642D\u5B50\u7684\u5F00\u53D1 Token \u5199\u5165\u5DE5\u7A0B .env\uFF0C\u540E\u7EED\u4F18\u5148\u590D\u7528\uFF1B\u767B\u5F55\u51ED\u636E\u4ECD\u4F7F\u7528\u7CFB\u7EDF\u51ED\u636E\u5B58\u50A8\u3002
3676
+ --refresh-token \u91CD\u65B0\u9886\u53D6\u5DF2\u6709\u5F00\u53D1 Token\uFF0C\u7528\u4E8E\u670D\u52A1\u7AEF\u91CD\u7F6E\u540E\u7684\u672C\u673A\u66F4\u65B0\uFF1B\u4E0D\u4F1A\u751F\u6210\u65B0\u5BC6\u94A5\u3002`;
3308
3677
  function valueAfter(args, index, flag2) {
3309
3678
  const value = args[index + 1];
3310
3679
  if (value === void 0 || !value.trim()) throw new DevCommandUsageError(`${flag2} \u7F3A\u5C11\u503C`);
@@ -3319,6 +3688,7 @@ function parseDevArguments(args) {
3319
3688
  let directorySet = false;
3320
3689
  let appServer;
3321
3690
  let help = false;
3691
+ let refreshToken = false;
3322
3692
  for (let index = 0; index < args.length; index += 1) {
3323
3693
  const flag2 = args[index];
3324
3694
  if (flag2 === "--help" || flag2 === "-h") {
@@ -3326,6 +3696,11 @@ function parseDevArguments(args) {
3326
3696
  help = true;
3327
3697
  continue;
3328
3698
  }
3699
+ if (flag2 === "--refresh-token") {
3700
+ if (refreshToken) throw new DevCommandUsageError("--refresh-token \u4E0D\u80FD\u91CD\u590D");
3701
+ refreshToken = true;
3702
+ continue;
3703
+ }
3329
3704
  const value = valueAfter(args, index, flag2 ?? "\u53C2\u6570");
3330
3705
  index += 1;
3331
3706
  switch (flag2) {
@@ -3341,7 +3716,7 @@ function parseDevArguments(args) {
3341
3716
  throw new DevCommandUsageError(`\u672A\u77E5 dev \u53C2\u6570 ${flag2}`);
3342
3717
  }
3343
3718
  }
3344
- return { directory, appServer, help };
3719
+ return { directory, appServer, help, refreshToken };
3345
3720
  }
3346
3721
  function appServerUrl(override, env) {
3347
3722
  try {
@@ -3375,7 +3750,7 @@ async function runDevCommand(args, io, options = {}) {
3375
3750
  const root = await (options.resolveProjectRoot ?? requireBuddyAgentProjectRoot)(requestedRoot);
3376
3751
  const environment = options.env ?? process.env;
3377
3752
  const url = appServerUrl(parsed.appServer, environment);
3378
- const authorizationInput = { appServerUrl: url };
3753
+ const authorizationInput = { appServerUrl: url, ...parsed.refreshToken ? { refreshToken: true } : {} };
3379
3754
  if (!options.authorize) {
3380
3755
  throw new DevCommandUsageError("\u5F53\u524D CLI Host \u5C1A\u672A\u914D\u7F6E\u642D\u642D\u8D26\u53F7\u767B\u5F55 Adapter");
3381
3756
  }
@@ -3427,7 +3802,7 @@ async function runDevCommand(args, io, options = {}) {
3427
3802
  import { resolve as resolve13 } from "node:path";
3428
3803
 
3429
3804
  // packages/cli-core/src/cloud/auth.ts
3430
- import { randomUUID as randomUUID6 } from "node:crypto";
3805
+ import { randomUUID as randomUUID7 } from "node:crypto";
3431
3806
 
3432
3807
  // packages/cli-core/src/cloud/validation.ts
3433
3808
  function record(value, path = "request") {
@@ -3478,7 +3853,7 @@ var MemoryCloudTokenStore = class {
3478
3853
  return this.#token === void 0 ? void 0 : frozenClone(this.#token);
3479
3854
  }
3480
3855
  async save(token) {
3481
- this.#token = validateToken(token);
3856
+ this.#token = validateToken2(token);
3482
3857
  }
3483
3858
  async clear() {
3484
3859
  this.#token = void 0;
@@ -3495,7 +3870,7 @@ var CloudAuthenticator = class {
3495
3870
  this.#adapter = adapter;
3496
3871
  this.#store = store;
3497
3872
  this.#now = options.now ?? Date.now;
3498
- this.#createState = options.createState ?? randomUUID6;
3873
+ this.#createState = options.createState ?? randomUUID7;
3499
3874
  this.#minimumValidityMs = options.minimumValidityMs ?? 3e4;
3500
3875
  if (!Number.isSafeInteger(this.#minimumValidityMs) || this.#minimumValidityMs < 0) {
3501
3876
  throw new TypeError("minimumValidityMs must be a non-negative safe integer");
@@ -3534,7 +3909,7 @@ var CloudAuthenticator = class {
3534
3909
  }
3535
3910
  if (stored === void 0) return void 0;
3536
3911
  try {
3537
- const token = validateToken(stored);
3912
+ const token = validateToken2(stored);
3538
3913
  if (token.expiresAt > this.#now() + this.#minimumValidityMs) return token;
3539
3914
  } catch {
3540
3915
  }
@@ -3555,7 +3930,7 @@ var CloudAuthenticator = class {
3555
3930
  "\u6D4F\u89C8\u5668\u767B\u5F55\u8FD4\u56DE\u7684 state \u4E0D\u5339\u914D\uFF1B\u51ED\u636E\u672A\u4FDD\u5B58"
3556
3931
  );
3557
3932
  }
3558
- const token = validateToken(resultRecord.token);
3933
+ const token = validateToken2(resultRecord.token);
3559
3934
  if (token.expiresAt <= this.#now() + this.#minimumValidityMs) {
3560
3935
  throw new CloudLifecycleError("AUTH_TOKEN_EXPIRED", "\u6D4F\u89C8\u5668\u767B\u5F55\u8FD4\u56DE\u4E86\u5DF2\u8FC7\u671F\u6216\u5373\u5C06\u8FC7\u671F\u7684\u4F1A\u8BDD");
3561
3936
  }
@@ -3563,7 +3938,7 @@ var CloudAuthenticator = class {
3563
3938
  return token;
3564
3939
  }
3565
3940
  };
3566
- function validateToken(value) {
3941
+ function validateToken2(value) {
3567
3942
  try {
3568
3943
  const input = record(value, "cloud token");
3569
3944
  exactKeys(input, ["accessToken", "subject", "expiresAt"], [], "cloud token");
@@ -3597,17 +3972,17 @@ function positiveTimeout(value, fallback, name) {
3597
3972
  }
3598
3973
  function object3(value, path) {
3599
3974
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
3600
- throw invalid(`${path} \u5FC5\u987B\u662F\u5BF9\u8C61`);
3975
+ throw invalid2(`${path} \u5FC5\u987B\u662F\u5BF9\u8C61`);
3601
3976
  }
3602
3977
  return value;
3603
3978
  }
3604
- function invalid(message) {
3979
+ function invalid2(message) {
3605
3980
  return new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", message);
3606
3981
  }
3607
3982
  function safeText(value, path, allowNewlines = false, allowEmpty = false) {
3608
- if (typeof value !== "string" || !allowEmpty && !value.trim()) throw invalid(`${path} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
3983
+ if (typeof value !== "string" || !allowEmpty && !value.trim()) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
3609
3984
  const invalidControl = allowNewlines ? /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/u : /[\u0000-\u001f\u007f]/u;
3610
- if (invalidControl.test(value)) throw invalid(`${path} \u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26`);
3985
+ if (invalidControl.test(value)) throw invalid2(`${path} \u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26`);
3611
3986
  return value;
3612
3987
  }
3613
3988
  function optionalText(value, path, allowNewlines = false) {
@@ -3629,23 +4004,23 @@ function meta(value, path) {
3629
4004
  });
3630
4005
  }
3631
4006
  function flag(value, path) {
3632
- if (typeof value !== "boolean") throw invalid(`${path} \u5FC5\u987B\u662F boolean`);
4007
+ if (typeof value !== "boolean") throw invalid2(`${path} \u5FC5\u987B\u662F boolean`);
3633
4008
  return value;
3634
4009
  }
3635
4010
  function timestamp(value, path) {
3636
- if (!Number.isSafeInteger(value) || value < 0) throw invalid(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6BEB\u79D2\u65F6\u95F4\u6233`);
4011
+ if (!Number.isSafeInteger(value) || value < 0) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6BEB\u79D2\u65F6\u95F4\u6233`);
3637
4012
  return value;
3638
4013
  }
3639
4014
  function nullableText(value, path) {
3640
4015
  return value === null ? null : safeText(value, path);
3641
4016
  }
3642
4017
  function nonNegativeInteger(value, path) {
3643
- if (!Number.isSafeInteger(value) || value < 0) throw invalid(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570`);
4018
+ if (!Number.isSafeInteger(value) || value < 0) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570`);
3644
4019
  return value;
3645
4020
  }
3646
4021
  function auditStatus(value, path) {
3647
4022
  if (value !== "auditing" && value !== "approved" && value !== "rejected") {
3648
- throw invalid(`${path} \u5FC5\u987B\u662F auditing\u3001approved \u6216 rejected`);
4023
+ throw invalid2(`${path} \u5FC5\u987B\u662F auditing\u3001approved \u6216 rejected`);
3649
4024
  }
3650
4025
  return value;
3651
4026
  }
@@ -3693,7 +4068,7 @@ async function boundedJson(response) {
3693
4068
  total += item.value.byteLength;
3694
4069
  if (total > MAX_RESPONSE_BYTES) {
3695
4070
  void reader.cancel().catch(() => void 0);
3696
- throw invalid("\u5E73\u53F0\u54CD\u5E94\u8D85\u8FC7 1 MiB");
4071
+ throw invalid2("\u5E73\u53F0\u54CD\u5E94\u8D85\u8FC7 1 MiB");
3697
4072
  }
3698
4073
  chunks.push(item.value);
3699
4074
  }
@@ -3709,7 +4084,7 @@ async function boundedJson(response) {
3709
4084
  try {
3710
4085
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
3711
4086
  } catch {
3712
- throw invalid("\u5E73\u53F0\u54CD\u5E94\u4E0D\u662F\u6709\u6548 JSON");
4087
+ throw invalid2("\u5E73\u53F0\u54CD\u5E94\u4E0D\u662F\u6709\u6548 JSON");
3713
4088
  }
3714
4089
  }
3715
4090
  function serverError(response, body) {
@@ -3780,7 +4155,7 @@ var HttpDeveloperPlatformClient = class {
3780
4155
  const mediaType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
3781
4156
  if (mediaType !== "application/json") {
3782
4157
  await response.body?.cancel().catch(() => void 0);
3783
- throw invalid(`\u5E73\u53F0\u54CD\u5E94 Content-Type \u65E0\u6548\uFF08HTTP ${response.status}\uFF09`);
4158
+ throw invalid2(`\u5E73\u53F0\u54CD\u5E94 Content-Type \u65E0\u6548\uFF08HTTP ${response.status}\uFF09`);
3784
4159
  }
3785
4160
  const payload = await boundedJson(response);
3786
4161
  if (!response.ok) throw serverError(response, payload);
@@ -3805,7 +4180,7 @@ var HttpDeveloperPlatformClient = class {
3805
4180
  }
3806
4181
  async listBuddies() {
3807
4182
  const source = object3(await this.#request("/cli/buddies", "GET"), "response");
3808
- if (!Array.isArray(source.buddies)) throw invalid("response.buddies \u5FC5\u987B\u662F\u6570\u7EC4");
4183
+ if (!Array.isArray(source.buddies)) throw invalid2("response.buddies \u5FC5\u987B\u662F\u6570\u7EC4");
3809
4184
  return Object.freeze({
3810
4185
  buddies: Object.freeze(source.buddies.map((item) => buddy(item, false)))
3811
4186
  });
@@ -3825,7 +4200,7 @@ var HttpDeveloperPlatformClient = class {
3825
4200
  `/cli/buddies/${encodeURIComponent(request.id)}/packages${suffix}`,
3826
4201
  "GET"
3827
4202
  ), "response");
3828
- if (!Array.isArray(source.items)) throw invalid("response.items \u5FC5\u987B\u662F\u6570\u7EC4");
4203
+ if (!Array.isArray(source.items)) throw invalid2("response.items \u5FC5\u987B\u662F\u6570\u7EC4");
3829
4204
  return Object.freeze({
3830
4205
  total: nonNegativeInteger(source.total, "response.total"),
3831
4206
  page: nonNegativeInteger(source.page, "response.page"),
@@ -3861,13 +4236,13 @@ var HttpDeveloperPlatformClient = class {
3861
4236
  }
3862
4237
  async logout(accessToken) {
3863
4238
  const source = object3(await this.#request("/cli/auth/logout", "POST", { accessToken }), "response");
3864
- if (source.ok !== true) throw invalid("response.ok \u5FC5\u987B\u662F true");
4239
+ if (source.ok !== true) throw invalid2("response.ok \u5FC5\u987B\u662F true");
3865
4240
  }
3866
4241
  };
3867
4242
 
3868
4243
  // packages/cli-core/src/cloud/browser-login.ts
3869
- import { createHash as createHash5, randomBytes } from "node:crypto";
3870
- import { spawn } from "node:child_process";
4244
+ import { createHash as createHash6, randomBytes } from "node:crypto";
4245
+ import { spawn as spawn2 } from "node:child_process";
3871
4246
  import { createServer } from "node:http";
3872
4247
 
3873
4248
  // packages/cli-core/src/cloud/login-result.ts
@@ -3927,7 +4302,7 @@ function browserCommand(url) {
3927
4302
  async function openExternalUrl(url) {
3928
4303
  const launch = browserCommand(url);
3929
4304
  await new Promise((resolve17, reject) => {
3930
- const child = spawn(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
4305
+ const child = spawn2(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
3931
4306
  child.once("error", reject);
3932
4307
  child.once("exit", (code2) => code2 === 0 ? resolve17() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
3933
4308
  });
@@ -3974,7 +4349,7 @@ var LoopbackBrowserLoginAdapter = class {
3974
4349
  if (request.signal?.aborted) throw request.signal.reason;
3975
4350
  const callbackSecret = randomBytes(24).toString("hex");
3976
4351
  const codeVerifier = randomBytes(32).toString("base64url");
3977
- const codeChallenge = createHash5("sha256").update(codeVerifier).digest("base64url");
4352
+ const codeChallenge = createHash6("sha256").update(codeVerifier).digest("base64url");
3978
4353
  let requestId = "";
3979
4354
  let settle;
3980
4355
  let reject;
@@ -4110,126 +4485,8 @@ var LoopbackBrowserLoginAdapter = class {
4110
4485
  }
4111
4486
  };
4112
4487
 
4113
- // packages/cli-core/src/cloud/credential-store.ts
4114
- import { spawn as spawn2 } from "node:child_process";
4115
- var DEFAULT_SERVICE = "com.xiaohongshu.buddy.developer-cli";
4116
- var DEFAULT_ACCOUNT = "developer-session";
4117
- var MAX_CREDENTIAL_BYTES = 32 * 1024;
4118
- function safeLabel(value, fallback, name) {
4119
- const result = value ?? fallback;
4120
- if (!result || result !== result.trim() || /[\u0000-\u001f\u007f]/u.test(result) || result.length > 256) {
4121
- throw new TypeError(`${name} is invalid`);
4122
- }
4123
- return result;
4124
- }
4125
- function serialize(token) {
4126
- const value = JSON.stringify(token);
4127
- if (Buffer.byteLength(value, "utf8") > MAX_CREDENTIAL_BYTES) {
4128
- throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u4E91\u7AEF\u4F1A\u8BDD\u51ED\u636E\u8FC7\u5927\uFF0C\u672A\u4FDD\u5B58");
4129
- }
4130
- return value;
4131
- }
4132
- function parse(source) {
4133
- if (Buffer.byteLength(source, "utf8") > MAX_CREDENTIAL_BYTES) {
4134
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4135
- }
4136
- let value;
4137
- try {
4138
- value = JSON.parse(source);
4139
- } catch {
4140
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4141
- }
4142
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
4143
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4144
- }
4145
- const record2 = value;
4146
- if (Object.keys(record2).length !== 3 || typeof record2.accessToken !== "string" || typeof record2.subject !== "string" || !Number.isSafeInteger(record2.expiresAt)) {
4147
- throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u7CFB\u7EDF\u51ED\u636E\u683C\u5F0F\u65E0\u6548");
4148
- }
4149
- return Object.freeze({
4150
- accessToken: record2.accessToken,
4151
- subject: record2.subject,
4152
- expiresAt: record2.expiresAt
4153
- });
4154
- }
4155
- async function runCredentialCommand(input) {
4156
- return await new Promise((resolve17, reject) => {
4157
- const child = spawn2(input.command, [...input.args], {
4158
- shell: false,
4159
- windowsHide: true,
4160
- stdio: ["pipe", "pipe", "pipe"]
4161
- });
4162
- const stdout = [];
4163
- const stderr = [];
4164
- let outputBytes = 0;
4165
- const collect = (target, chunk) => {
4166
- outputBytes += chunk.byteLength;
4167
- if (outputBytes <= MAX_CREDENTIAL_BYTES) target.push(chunk);
4168
- };
4169
- child.stdout.on("data", (chunk) => collect(stdout, chunk));
4170
- child.stderr.on("data", (chunk) => collect(stderr, chunk));
4171
- child.once("error", reject);
4172
- child.once("close", (code2) => resolve17({
4173
- code: code2 ?? 1,
4174
- stdout: Buffer.concat(stdout).toString("utf8"),
4175
- stderr: Buffer.concat(stderr).toString("utf8")
4176
- }));
4177
- child.stdin.on("error", () => void 0);
4178
- child.stdin.end(input.input ?? "");
4179
- });
4180
- }
4181
- var SystemCloudTokenStore = class {
4182
- #platform;
4183
- #service;
4184
- #account;
4185
- #run;
4186
- constructor(options = {}) {
4187
- this.#platform = options.platform ?? process.platform;
4188
- this.#service = safeLabel(options.service, DEFAULT_SERVICE, "service");
4189
- this.#account = safeLabel(options.account, DEFAULT_ACCOUNT, "account");
4190
- this.#run = options.commandRunner ?? runCredentialCommand;
4191
- if (this.#platform !== "darwin") {
4192
- throw new CloudLifecycleError("INVALID_REQUEST", "\u642D\u642D CLI V1 \u7684\u5B89\u5168\u767B\u5F55\u5B58\u50A8\u76EE\u524D\u53EA\u652F\u6301 macOS Keychain");
4193
- }
4194
- }
4195
- async load() {
4196
- const result = await this.#run({
4197
- command: "security",
4198
- args: ["find-generic-password", "-s", this.#service, "-a", this.#account, "-w"]
4199
- });
4200
- if (result.code === 44) return void 0;
4201
- if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u8BFB\u53D6 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u767B\u5F55\u72B6\u6001");
4202
- const raw = result.stdout.trimEnd();
4203
- return parse(/^(?:[a-fA-F0-9]{2})+$/u.test(raw) ? Buffer.from(raw, "hex").toString("utf8") : raw);
4204
- }
4205
- async save(token) {
4206
- const source = serialize(token);
4207
- const line = ["add-generic-password", "-U", "-s", this.#service, "-a", this.#account, "-w", source].map((part) => `"${part.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"')}"`).join(" ") + "\n";
4208
- if (Buffer.byteLength(line, "utf8") >= 4096) {
4209
- throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u767B\u5F55\u51ED\u636E\u8D85\u8FC7 macOS \u5199\u5165\u957F\u5EA6\u9650\u5236\uFF0C\u672A\u4FDD\u5B58\uFF1B\u8BF7\u8054\u7CFB\u5E73\u53F0\u5904\u7406");
4210
- }
4211
- const result = await this.#run({
4212
- command: "security",
4213
- args: ["-i", "-q"],
4214
- input: line
4215
- });
4216
- if (result.code !== 0) throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u628A\u642D\u642D\u767B\u5F55\u72B6\u6001\u5199\u5165 macOS \u94A5\u5319\u4E32");
4217
- const saved = await this.load();
4218
- if (!saved || serialize(saved) !== source) throw new CloudLifecycleError("AUTH_CREDENTIAL_CORRUPT", "\u767B\u5F55\u51ED\u636E\u5199\u5165\u540E\u6821\u9A8C\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55");
4219
- }
4220
- async clear() {
4221
- const result = await this.#run({
4222
- command: "security",
4223
- args: ["delete-generic-password", "-s", this.#service, "-a", this.#account]
4224
- });
4225
- if (result.code !== 0 && result.code !== 44) {
4226
- throw new CloudLifecycleError("AUTH_TOKEN_INVALID", "\u65E0\u6CD5\u6E05\u9664 macOS \u94A5\u5319\u4E32\u4E2D\u7684\u642D\u642D\u767B\u5F55\u72B6\u6001");
4227
- }
4228
- }
4229
- };
4230
-
4231
4488
  // packages/cli-core/src/cloud/mock-client.ts
4232
- import { createHash as createHash6, randomBytes as randomBytes2 } from "node:crypto";
4489
+ import { createHash as createHash7, randomBytes as randomBytes2 } from "node:crypto";
4233
4490
  var MockDeveloperPlatformClient = class {
4234
4491
  #now;
4235
4492
  #buddies = /* @__PURE__ */ new Map();
@@ -4257,7 +4514,7 @@ var MockDeveloperPlatformClient = class {
4257
4514
  const current = this.#require(request.id);
4258
4515
  validateBuddyMetaUpdate(request.meta);
4259
4516
  const onlyAvatar = Object.keys(request.meta).every((key) => key === "avatar");
4260
- const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash6("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
4517
+ const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash7("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
4261
4518
  const next = this.#value({ ...current, meta: { ...onlyAvatar ? current.meta : request.meta, avatar }, updatedAt: this.#now() });
4262
4519
  this.#buddies.set(request.id, next);
4263
4520
  return structuredClone(next);
@@ -4554,8 +4811,8 @@ async function runCloudCommand(command, args, io, options = {}) {
4554
4811
  var CLOUD_COMMAND_HELP = HELP;
4555
4812
 
4556
4813
  // packages/cli-core/src/migration/index.ts
4557
- import { lstat as lstat9, open as open4, readdir as readdir4, realpath as realpath3, stat } from "node:fs/promises";
4558
- import { extname, isAbsolute as isAbsolute2, join as join12, relative, resolve as resolve14, sep, win32 as win322 } from "node:path";
4814
+ import { lstat as lstat9, open as open5, readdir as readdir4, realpath as realpath3, stat } from "node:fs/promises";
4815
+ import { extname, isAbsolute as isAbsolute2, join as join13, relative, resolve as resolve14, sep, win32 as win322 } from "node:path";
4559
4816
  var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
4560
4817
  maxFiles: 128,
4561
4818
  maxFileBytes: 256 * 1024,
@@ -4724,7 +4981,7 @@ async function existingProjectRoot(value) {
4724
4981
  }
4725
4982
  }
4726
4983
  async function existingSkillRoot(projectRoot, skillPath) {
4727
- const candidate = skillPath === "." ? projectRoot : join12(projectRoot, ...skillPath.split("/"));
4984
+ const candidate = skillPath === "." ? projectRoot : join13(projectRoot, ...skillPath.split("/"));
4728
4985
  try {
4729
4986
  await lstat9(candidate);
4730
4987
  } catch (cause) {
@@ -4761,7 +5018,7 @@ async function existingSkillRoot(projectRoot, skillPath) {
4761
5018
  }
4762
5019
  async function assertEntrypoint(context) {
4763
5020
  const entryPath = reportChild(context.skillPath, "SKILL.md");
4764
- const candidate = join12(context.skillRoot, "SKILL.md");
5021
+ const candidate = join13(context.skillRoot, "SKILL.md");
4765
5022
  try {
4766
5023
  await lstat9(candidate);
4767
5024
  const target = await realpath3(candidate);
@@ -4865,7 +5122,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
4865
5122
  }
4866
5123
  for (const entry2 of entries) {
4867
5124
  const childReportPath = reportChild(reportDirectory, entry2.name);
4868
- const childPath = join12(directory, entry2.name);
5125
+ const childPath = join13(directory, entry2.name);
4869
5126
  let target;
4870
5127
  try {
4871
5128
  target = await realpath3(childPath);
@@ -4907,7 +5164,7 @@ async function scanFile(actualPath, reportPath, context) {
4907
5164
  }
4908
5165
  let handle;
4909
5166
  try {
4910
- handle = await open4(actualPath, "r");
5167
+ handle = await open5(actualPath, "r");
4911
5168
  } catch (cause) {
4912
5169
  return rejectScan("SKILL_SCAN_IO_ERROR", reportPath, "\u65E0\u6CD5\u6253\u5F00 Skill \u6587\u4EF6\u3002", cause);
4913
5170
  }
@@ -5319,9 +5576,9 @@ async function scanExternalSkillPortability(options) {
5319
5576
  }
5320
5577
 
5321
5578
  // packages/cli-core/src/push/preflight.ts
5322
- import { createHash as createHash7 } from "node:crypto";
5323
- import { lstat as lstat10, open as open5, readdir as readdir5, realpath as realpath4 } from "node:fs/promises";
5324
- import { isAbsolute as isAbsolute3, join as join13, relative as relative2, resolve as resolve15, sep as sep2, win32 as win323 } from "node:path";
5579
+ import { createHash as createHash8 } from "node:crypto";
5580
+ import { lstat as lstat10, open as open6, readdir as readdir5, realpath as realpath4 } from "node:fs/promises";
5581
+ import { isAbsolute as isAbsolute3, join as join14, relative as relative2, resolve as resolve15, sep as sep2, win32 as win323 } from "node:path";
5325
5582
 
5326
5583
  // packages/cli-core/src/push/errors.ts
5327
5584
  var PushPreflightError = class extends Error {
@@ -5419,7 +5676,7 @@ function error(options) {
5419
5676
  throw new PushPreflightError(options);
5420
5677
  }
5421
5678
  function sha256(value) {
5422
- return `sha256:${createHash7("sha256").update(value).digest("hex")}`;
5679
+ return `sha256:${createHash8("sha256").update(value).digest("hex")}`;
5423
5680
  }
5424
5681
  function positiveLimit(value, name, hardMaximum) {
5425
5682
  if (!Number.isSafeInteger(value) || value < 1 || value > hardMaximum) {
@@ -5540,7 +5797,7 @@ async function canonicalProjectRoot(projectRoot) {
5540
5797
  }
5541
5798
  }
5542
5799
  async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
5543
- const path = join13(projectRoot, filename);
5800
+ const path = join14(projectRoot, filename);
5544
5801
  let entry2;
5545
5802
  try {
5546
5803
  entry2 = await lstat10(path);
@@ -5650,7 +5907,7 @@ function sameFileIdentity(left, right) {
5650
5907
  return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs;
5651
5908
  }
5652
5909
  async function hashRegularFile(options) {
5653
- const handle = await open5(options.absolutePath, "r").catch((cause) => error({
5910
+ const handle = await open6(options.absolutePath, "r").catch((cause) => error({
5654
5911
  code: "PUSH_PROJECT_INVALID",
5655
5912
  path: options.portablePath,
5656
5913
  message: `\u65E0\u6CD5\u8BFB\u53D6\u63D0\u4EA4\u6587\u4EF6\uFF1A${options.portablePath}`,
@@ -5665,7 +5922,7 @@ async function hashRegularFile(options) {
5665
5922
  message: `\u751F\u6210\u6E05\u5355\u65F6\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${options.portablePath}`
5666
5923
  });
5667
5924
  }
5668
- const hash3 = createHash7("sha256");
5925
+ const hash3 = createHash8("sha256");
5669
5926
  const captured = [];
5670
5927
  const buffer = Buffer.allocUnsafe(READ_BUFFER_BYTES);
5671
5928
  let bytes = 0;
@@ -5743,7 +6000,7 @@ async function createManifest(options) {
5743
6000
  sensitiveEntriesExcluded += 1;
5744
6001
  continue;
5745
6002
  }
5746
- const absolutePath = join13(directory, name);
6003
+ const absolutePath = join14(directory, name);
5747
6004
  let entry2;
5748
6005
  try {
5749
6006
  entry2 = await lstat10(absolutePath);
@@ -5969,11 +6226,12 @@ function assertOfficialProjectIncluded(files) {
5969
6226
  message: `package.json \u7684 dependencies \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C\uFF0C\u5E76\u63D0\u4EA4\u76F8\u5E94\u9501\u6587\u4EF6\u3002`
5970
6227
  });
5971
6228
  }
5972
- if (typeof pkg !== "object" || pkg === null || Array.isArray(pkg) || !("scripts" in pkg) || typeof pkg.scripts !== "object" || pkg.scripts === null || !("start" in pkg.scripts) || pkg.scripts.start !== `node ${BUDDY_PLATFORM_START_ENTRY}`) {
6229
+ const expectedStart = `node ${runtimeUsesEnvironmentIdentity(pkg) ? "--env-file-if-exists=.env " : ""}${BUDDY_PLATFORM_START_ENTRY}`;
6230
+ if (typeof pkg !== "object" || pkg === null || Array.isArray(pkg) || !("scripts" in pkg) || typeof pkg.scripts !== "object" || pkg.scripts === null || !("start" in pkg.scripts) || pkg.scripts.start !== expectedStart) {
5973
6231
  error({
5974
6232
  code: "PUSH_PROJECT_INVALID",
5975
6233
  path: BUDDY_PLATFORM_PACKAGE_JSON,
5976
- message: `\u5B98\u65B9 Runtime \u5DE5\u7A0B\u7684 package.json \u5FC5\u987B\u8BBE\u7F6E scripts.start \u4E3A "node ${BUDDY_PLATFORM_START_ENTRY}"\uFF0C\u4F7F\u4E91\u7AEF\u4E0E\u672C\u5730\u4F7F\u7528\u540C\u4E00\u542F\u52A8\u5165\u53E3\u3002`
6234
+ message: `\u5B98\u65B9 Runtime \u5DE5\u7A0B\u7684 package.json \u5FC5\u987B\u8BBE\u7F6E scripts.start \u4E3A "${expectedStart}"\uFF0C\u4F7F\u4E91\u7AEF\u4E0E\u672C\u5730\u4F7F\u7528\u540C\u4E00\u542F\u52A8\u5165\u53E3\u3002`
5977
6235
  });
5978
6236
  }
5979
6237
  }
@@ -5995,7 +6253,7 @@ async function assertCapturedConfigStable(options) {
5995
6253
  }
5996
6254
  let current;
5997
6255
  try {
5998
- const path = join13(options.projectRoot, options.filename);
6256
+ const path = join14(options.projectRoot, options.filename);
5999
6257
  const entry2 = await lstat10(path);
6000
6258
  if (!entry2.isFile() || entry2.isSymbolicLink()) {
6001
6259
  error({
@@ -6124,16 +6382,16 @@ async function createPushPreflight(options) {
6124
6382
  }
6125
6383
 
6126
6384
  // packages/cli-core/src/push/bundle.ts
6127
- import { createHash as createHash8 } from "node:crypto";
6385
+ import { createHash as createHash9 } from "node:crypto";
6128
6386
  import { lstat as lstat11, readFile as readFile11, realpath as realpath5 } from "node:fs/promises";
6129
- import { join as join14, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
6387
+ import { join as join15, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
6130
6388
  import { Writable } from "node:stream";
6131
6389
  import { pipeline } from "node:stream/promises";
6132
6390
  import { createGzip } from "node:zlib";
6133
6391
  import { pack } from "tar-stream";
6134
6392
  var MEDIA_TYPE = "application/gzip";
6135
6393
  function digest2(bytes) {
6136
- return `sha256:${createHash8("sha256").update(bytes).digest("hex")}`;
6394
+ return `sha256:${createHash9("sha256").update(bytes).digest("hex")}`;
6137
6395
  }
6138
6396
  function changed(path, message, cause) {
6139
6397
  throw new PushPreflightError({
@@ -6148,7 +6406,7 @@ function inside(root, target) {
6148
6406
  return path === "" || path !== ".." && !path.startsWith(`..${sep3}`) && !path.startsWith("/") && !win324.isAbsolute(path);
6149
6407
  }
6150
6408
  async function capture(root, file) {
6151
- const absolute = join14(root, ...file.path.split("/"));
6409
+ const absolute = join15(root, ...file.path.split("/"));
6152
6410
  try {
6153
6411
  const entry2 = await lstat11(absolute);
6154
6412
  if (!entry2.isFile() || entry2.isSymbolicLink() || entry2.size !== file.bytes) {
@@ -6182,7 +6440,7 @@ async function createPushSourceBundle(plan) {
6182
6440
  schemaVersion: "1",
6183
6441
  files: files.map((file) => ({ path: file.path, bytes: file.bytes, digest: file.digest }))
6184
6442
  });
6185
- const calculatedBundleDigest = `sha256:${createHash8("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
6443
+ const calculatedBundleDigest = `sha256:${createHash9("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
6186
6444
  if (calculatedBundleDigest !== plan.bundleDigest) {
6187
6445
  changed(plan.projectRoot, "\u63D0\u4EA4\u6E05\u5355\u8EAB\u4EFD\u5728\u6253\u5305\u524D\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C push");
6188
6446
  }
@@ -6607,7 +6865,7 @@ async function resumeProjectArguments(args, cwd, options) {
6607
6865
  await assertInitializableBuddyTarget(root);
6608
6866
  let entry2;
6609
6867
  try {
6610
- entry2 = await lstat12(join15(root, "buddy.agent.json"));
6868
+ entry2 = await lstat12(join16(root, "buddy.agent.json"));
6611
6869
  } catch (cause) {
6612
6870
  if (cause.code === "ENOENT") {
6613
6871
  const draft = await readMetaDraft(root);
@@ -6840,6 +7098,7 @@ export {
6840
7098
  PromptCancelledError,
6841
7099
  PushPreflightError,
6842
7100
  SkillPortabilityScanError,
7101
+ SystemBuddyTokenStore,
6843
7102
  SystemCloudTokenStore,
6844
7103
  abortedDevError,
6845
7104
  applyBuddyDraftInitialization,
@@ -6861,6 +7120,7 @@ export {
6861
7120
  isSafeProjectRelativePath,
6862
7121
  isWindowsReservedPathSegment,
6863
7122
  latestRuntimeTemplate,
7123
+ migrateRuntimeStartup,
6864
7124
  normalizePlatformUrl,
6865
7125
  openExternalUrl,
6866
7126
  parseBuddyAgentConfig,