@my-life-buddies/cli 0.15.1 → 0.17.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
@@ -215,21 +215,16 @@ async function readRuntimeModelCatalog(projectRoot) {
215
215
  }
216
216
  return Object.freeze({ runtimeVersion, models: Object.freeze([...models]) });
217
217
  }
218
- async function validateRuntimeModel(projectRoot, model) {
219
- if (model === void 0) return;
220
- const catalog = await readRuntimeModelCatalog(projectRoot);
221
- if (!catalog.models.includes(model)) throw new Error(`/model\uFF1A\u5DE5\u7A0B Runtime ${catalog.runtimeVersion} \u4E0D\u652F\u6301 ${model}\uFF1B\u53EF\u9009 ${catalog.models.join("\u3001")}`);
222
- }
223
218
  async function validateRuntimeDatasets(projectRoot, requirements = []) {
224
219
  const catalog = await readRuntimeDataCatalog(projectRoot);
225
220
  const ids = new Set(catalog.datasets.map((item) => item.id));
226
221
  for (const [index, item] of requirements.entries()) {
227
- if (!ids.has(item.id)) throw new Error(`/datasets/${index}/id\uFF1A\u5DE5\u7A0B Runtime ${catalog.runtimeVersion} \u4E0D\u652F\u6301 ${item.id}`);
222
+ if (!ids.has(item.id)) throw new Error(`data-access.json/requirements/${index}/id\uFF1A\u5DE5\u7A0B Runtime ${catalog.runtimeVersion} \u4E0D\u652F\u6301 ${item.id}`);
228
223
  }
229
224
  }
230
225
 
231
226
  // packages/cli-core/src/project-context.ts
232
- import { lstat as lstat7, realpath as realpath3 } from "node:fs/promises";
227
+ import { lstat as lstat7, realpath as realpath3, readFile as readFile10 } from "node:fs/promises";
233
228
  import { dirname, join as join9, resolve as resolve5 } from "node:path";
234
229
 
235
230
  // packages/cli-core/src/config/index.ts
@@ -240,68 +235,29 @@ import {
240
235
  open as open3,
241
236
  readFile as readFile9,
242
237
  readdir as readdir3,
243
- rename as rename5,
238
+ rename as rename6,
244
239
  unlink as unlink4
245
240
  } from "node:fs/promises";
246
- import { randomUUID as randomUUID3 } from "node:crypto";
241
+ import { randomUUID as randomUUID4 } from "node:crypto";
247
242
  import { isAbsolute as isAbsolute2, join as join8, resolve as resolve4, win32 } from "node:path";
248
243
  import { isDeepStrictEqual } from "node:util";
249
244
  import { Ajv2020 } from "ajv/dist/2020.js";
250
245
 
251
- // packages/cli-core/src/config/buddy.agent.schema.json
252
- var buddy_agent_schema_default = {
246
+ // packages/cli-core/src/config/buddy.package.schema.json
247
+ var buddy_package_schema_default = {
253
248
  $schema: "https://json-schema.org/draft/2020-12/schema",
254
- title: "buddy.agent.json",
255
- description: "\u642D\u642D\u9879\u76EE\u8EAB\u4EFD\u3001\u6A21\u578B\u9009\u62E9\u4E0E\u6570\u636E\u8BBF\u95EE\u9700\u6C42\uFF1B\u5DE5\u7A0B\u662F\u5426\u53EF\u8FD0\u884C\u7531\u5B9E\u9645\u6587\u4EF6\u5224\u65AD",
249
+ title: "Buddy package.json",
250
+ description: "package.json \u9876\u5C42 buddyId \u6807\u8BC6\u5E73\u53F0\u642D\u5B50\uFF1B\u5176\u4F59 npm \u5DE5\u7A0B\u5B57\u6BB5\u4FDD\u7559",
256
251
  type: "object",
257
- additionalProperties: false,
258
252
  required: [
259
- "schemaVersion",
260
253
  "buddyId"
261
254
  ],
262
255
  properties: {
263
- schemaVersion: {
264
- const: 1
265
- },
266
256
  buddyId: {
267
257
  type: "string",
268
258
  minLength: 1,
269
259
  maxLength: 256,
270
- pattern: "^[^\\s\\u0000-\\u001f\\u007f]+$",
271
- description: "\u5E73\u53F0\u751F\u6210\u7684\u7A33\u5B9A\u642D\u5B50 ID"
272
- },
273
- model: {
274
- type: "string",
275
- minLength: 1,
276
- maxLength: 128,
277
- pattern: "^[^\\s\\u0000-\\u001f\\u007f]+$",
278
- description: "\u4ECE buddy-cli models \u67E5\u770B Runtime \u6A21\u578B\u76EE\u5F55\uFF1B\u5DE5\u7A0B\u5185\u8BFB\u53D6\u5B89\u88C5\u7248\u672C\uFF0C\u5DE5\u7A0B\u5916\u8BFB\u53D6 npm \u6700\u65B0\u7248\u3002\u8FD0\u884C\u4E0E\u4E0A\u4F20\u9884\u68C0\u6309\u5DE5\u7A0B Runtime \u6821\u9A8C\u3002"
279
- },
280
- datasets: {
281
- type: "array",
282
- description: "\u672C\u642D\u5B50\u7533\u8BF7\u7684\u6570\u636E\u96C6\u53CA\u7528\u9014\uFF1B\u7701\u7565\u6216\u7A7A\u6570\u7EC4\u8868\u793A\u4E0D\u7533\u8BF7\u6570\u636E\uFF0C\u58F0\u660E\u4E0D\u4EE3\u8868\u7528\u6237\u5DF2\u6388\u6743",
283
- default: [],
284
- items: {
285
- type: "object",
286
- additionalProperties: false,
287
- required: ["id", "purpose"],
288
- properties: {
289
- id: {
290
- type: "string",
291
- minLength: 1,
292
- maxLength: 128,
293
- pattern: "^[^\\s\\u0000-\\u001f\\u007f]+$",
294
- description: "\u53D6\u503C\u6765\u81EA\u5DE5\u7A0B Runtime \u5BFC\u51FA\u7684 DATA_ACCESS_CAPABILITIES\uFF0C\u7531\u8FD0\u884C\u4E0E\u4E0A\u4F20\u9884\u68C0\u6821\u9A8C\u3002\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\u3002"
295
- },
296
- purpose: {
297
- type: "string",
298
- minLength: 1,
299
- maxLength: 200,
300
- pattern: "\\S",
301
- description: "\u5411\u7528\u6237\u8BF4\u660E\u8FD9\u53EA\u642D\u5B50\u4E3A\u4F55\u9700\u8981\u8BE5\u6570\u636E"
302
- }
303
- }
304
- }
260
+ pattern: "^[^\\s\\u0000-\\u001f\\u007f]+$"
305
261
  }
306
262
  }
307
263
  };
@@ -818,8 +774,9 @@ import { lstat as lstat5 } from "node:fs/promises";
818
774
  import { join as join7 } from "node:path";
819
775
 
820
776
  // packages/cli-core/src/init/scaffold.ts
821
- import { lstat as lstat4, mkdir as mkdir5, open as open2, readFile as readFile8, rmdir as rmdir2, unlink as unlink3, writeFile as writeFile6 } from "node:fs/promises";
777
+ import { lstat as lstat4, mkdir as mkdir5, open as open2, readFile as readFile8, rename as rename5, rmdir as rmdir2, unlink as unlink3 } from "node:fs/promises";
822
778
  import { resolve as resolve3 } from "node:path";
779
+ import { randomUUID as randomUUID3 } from "node:crypto";
823
780
 
824
781
  // packages/cli-core/src/config/models.ts
825
782
  var MODEL_IDS = Object.freeze([
@@ -909,14 +866,13 @@ function platformAgentTemplate(name) {
909
866
  return `${promptFor(name)}
910
867
  `;
911
868
  }
912
- function platformFactoryTemplate() {
869
+ function platformFactoryTemplate(model = DEFAULT_MODEL_ID) {
913
870
  return `import { readFileSync } from "node:fs";
914
871
 
915
872
  const systemPrompt = readFileSync(new URL("../agent.md", import.meta.url), "utf8").trim();
916
873
  if (!systemPrompt) throw new Error("agent.md must contain the Buddy system prompt");
917
- const config = JSON.parse(readFileSync(new URL("../buddy.agent.json", import.meta.url), "utf8"));
918
874
  /** @type {import("@my-life-buddies/buddy-runtime").ModelId} */
919
- const model = config.model ?? "${DEFAULT_MODEL_ID}";
875
+ const model = ${JSON.stringify(model)};
920
876
 
921
877
  /**
922
878
  * Builds BuddyOptions when the Runtime creates an agent for a conversation.
@@ -924,7 +880,7 @@ const model = config.model ?? "${DEFAULT_MODEL_ID}";
924
880
  * Shared business code can live in ./services/; directories do not enable capabilities.
925
881
  * Use conversation.memory / dataAccess / widget / resource / proactive for platform capabilities.
926
882
  * Add conversation.tools.data_access_query / data_access_request / data_access_read_result
927
- * to initialState.tools for model-driven data access; declarations come from buddy.agent.json.datasets.
883
+ * to initialState.tools for model-driven data access; declarations come from data-access.json.requirements.
928
884
  * Add conversation.tools.ask_question for multiple-choice questions.
929
885
  * Add conversation.tools.resource_list / resource_read to discover and read reference material.
930
886
  * Place widget assets in ../widgets/<type-id>/index.html and schema.json.
@@ -947,27 +903,16 @@ export default function createBuddyOptions(_conversation) {
947
903
  }
948
904
  function platformStartTemplate() {
949
905
  return `// Generated startup: local DEV and hosted execution use the same Buddy Runtime.
950
- import { readFileSync } from "node:fs";
951
906
  import { BuddyServer } from "@my-life-buddies/buddy-runtime";
952
907
  import createBuddyOptions from "./src/buddy-options.mjs";
953
908
 
954
- const config = JSON.parse(readFileSync(new URL("./buddy.agent.json", import.meta.url), "utf8"));
955
- if (!config || config.schemaVersion !== 1 || typeof config.buddyId !== "string" || !config.buddyId) {
956
- throw new Error("buddy.agent.json is not a complete Buddy project");
957
- }
958
- if (process.env.BUDDY_ID && process.env.BUDDY_ID !== config.buddyId) {
959
- throw new Error("BUDDY_ID does not match buddy.agent.json");
960
- }
961
909
  const lifecycle = new AbortController();
962
910
  const stop = () => lifecycle.abort();
963
911
  process.on("SIGINT", stop);
964
912
  process.on("SIGTERM", stop);
965
913
  let runtime;
966
914
  try {
967
- runtime = await BuddyServer.start({
968
- dataRequirements: config.datasets ?? [],
969
- buddy: createBuddyOptions,
970
- });
915
+ runtime = await BuddyServer.start(createBuddyOptions);
971
916
  if (!lifecycle.signal.aborted) {
972
917
  await new Promise((resolve) => lifecycle.signal.addEventListener("abort", resolve, { once: true }));
973
918
  }
@@ -983,34 +928,13 @@ try {
983
928
  }
984
929
  `;
985
930
  }
986
- function legacyPlatformStartTemplate() {
987
- return platformStartTemplate().replace(" dataRequirements: config.datasets ?? [],", " buddyId: process.env.BUDDY_ID,\n token: process.env.BUDDY_TOKEN,\n dataRequirements: config.datasets ?? [],");
988
- }
989
- async function migrateRuntimeStartup(projectRoot) {
990
- const packagePath = resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
991
- const entryPath = resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY);
992
- for (const path of [packagePath, entryPath]) {
993
- if (!(await lstat4(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");
994
- }
995
- const pkg = JSON.parse(await readFile8(packagePath, "utf8"));
996
- if (!runtimeUsesEnvironmentIdentity(pkg)) return false;
997
- const current = await readFile8(entryPath, "utf8");
998
- const latest = platformStartTemplate();
999
- const legacy = legacyPlatformStartTemplate();
1000
- let changed2 = false;
1001
- if (current.replace(/\r\n/gu, "\n") === legacy) {
1002
- await writeFile6(entryPath, latest, "utf8");
1003
- changed2 = true;
1004
- }
1005
- if (pkg.scripts?.start === "node start.mjs") {
1006
- pkg.scripts.start = "node --env-file-if-exists=.env start.mjs";
1007
- await writeFile6(packagePath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
1008
- changed2 = true;
1009
- }
1010
- return changed2;
1011
- }
1012
931
  async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1013
932
  const path = resolve3(projectRoot, BUDDY_PLATFORM_AGENT_ENTRY);
933
+ const packagePath = resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
934
+ if (!(await lstat4(packagePath)).isFile()) throw new Error("package.json \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6");
935
+ const originalPackage = await readFile8(packagePath, "utf8");
936
+ const projectPackage = parseBuddyProjectManifest(originalPackage);
937
+ const isIdentityDraft = Object.keys(projectPackage).every((key) => key === "buddyId");
1014
938
  const hasAlternateLockfile = (await Promise.all(["pnpm-lock.yaml", "yarn.lock"].map(async (name2) => {
1015
939
  try {
1016
940
  if (!(await lstat4(resolve3(projectRoot, name2))).isFile()) {
@@ -1024,10 +948,11 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1024
948
  }))).some(Boolean);
1025
949
  const files = [
1026
950
  { path, content: platformAgentTemplate(name) },
1027
- { path: resolve3(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate() },
951
+ { path: resolve3(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate(options.model) },
1028
952
  { path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile8(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
1029
953
  ...hasAlternateLockfile ? [] : [{ path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK), content: await readFile8(new URL("../../resources/agent-template/package-lock.json", import.meta.url), "utf8") }],
1030
954
  { path: resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() },
955
+ { path: resolve3(projectRoot, "data-access.json"), content: '{\n "requirements": []\n}\n' },
1031
956
  { path: resolve3(projectRoot, ".gitignore"), content: "node_modules/\n/.env\n" },
1032
957
  { 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" }
1033
958
  ];
@@ -1058,13 +983,17 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1058
983
  }
1059
984
  const packageFile = files.find((file) => file.path === resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON));
1060
985
  const lockFile = files.find((file) => file.path === resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK));
1061
- if (options.resolveDependencies && lockFile && handles.some((file) => file.path === packageFile.path) && handles.some((file) => file.path === lockFile.path)) {
986
+ packageFile.content = JSON.stringify({ ...JSON.parse(packageFile.content), buddyId: projectPackage.buddyId }, null, 2) + "\n";
987
+ if (options.resolveDependencies && isIdentityDraft && lockFile && handles.some((file) => file.path === lockFile.path)) {
1062
988
  const template = await options.resolveDependencies({ packageJson: packageFile.content, packageLock: lockFile.content });
989
+ if (parseBuddyProjectManifest(template.packageJson).buddyId !== projectPackage.buddyId) {
990
+ throw new Error("\u4F9D\u8D56\u89E3\u6790\u6539\u53D8\u4E86 package.json.buddyId\uFF0C\u5DF2\u505C\u6B62\u8865\u9F50\u5DE5\u7A0B");
991
+ }
1063
992
  packageFile.content = template.packageJson;
1064
993
  lockFile.content = template.packageLock;
1065
994
  }
1066
- if (lockFile && (handles.some((file) => file.path === packageFile.path) || handles.some((file) => file.path === lockFile.path))) {
1067
- const packageContents = handles.some((file) => file.path === packageFile.path) ? packageFile.content : await readFile8(packageFile.path, "utf8");
995
+ if (lockFile && (isIdentityDraft || handles.some((file) => file.path === lockFile.path))) {
996
+ const packageContents = isIdentityDraft ? packageFile.content : await readFile8(packageFile.path, "utf8");
1068
997
  const lockContents = handles.some((file) => file.path === lockFile.path) ? lockFile.content : await readFile8(lockFile.path, "utf8");
1069
998
  const declared = JSON.parse(packageContents).dependencies ?? {};
1070
999
  const locked = JSON.parse(lockContents).packages?.[""]?.dependencies ?? {};
@@ -1072,17 +1001,30 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1072
1001
  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");
1073
1002
  }
1074
1003
  }
1075
- const effectivePackage = handles.some((file) => file.path === packageFile.path) ? packageFile.content : await readFile8(packageFile.path, "utf8");
1076
- if (!runtimeUsesEnvironmentIdentity(JSON.parse(effectivePackage))) {
1077
- files.find((file) => file.path === resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY)).content = legacyPlatformStartTemplate();
1078
- }
1079
1004
  for (const { path: filePath, handle } of handles) {
1080
1005
  const file = files.find((candidate) => candidate.path === filePath);
1081
1006
  await handle.writeFile(file.content, "utf8");
1082
1007
  await handle.sync();
1083
1008
  }
1084
- const migrated = await migrateRuntimeStartup(projectRoot);
1085
- return Object.freeze({ path, created: migrated || handles.length > 0 || createdDirectories.length > 0 });
1009
+ if (isIdentityDraft) {
1010
+ const temporary = `${packagePath}.${randomUUID3()}.tmp`;
1011
+ const handle = await open2(temporary, "wx", 384);
1012
+ try {
1013
+ await handle.writeFile(packageFile.content, "utf8");
1014
+ await handle.sync();
1015
+ await handle.close();
1016
+ if (!(await lstat4(packagePath)).isFile() || await readFile8(packagePath, "utf8") !== originalPackage) {
1017
+ throw new Error("\u8865\u9F50\u5DE5\u7A0B\u65F6 package.json \u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u8BD5");
1018
+ }
1019
+ await rename5(temporary, packagePath);
1020
+ } finally {
1021
+ await handle.close().catch(() => void 0);
1022
+ await unlink3(temporary).catch((cause) => {
1023
+ if (cause.code !== "ENOENT") throw cause;
1024
+ });
1025
+ }
1026
+ }
1027
+ return Object.freeze({ path, created: isIdentityDraft || handles.length > 0 || createdDirectories.length > 0 });
1086
1028
  } catch (cause) {
1087
1029
  await Promise.all(handles.map(({ handle }) => handle.close().catch(() => void 0)));
1088
1030
  await Promise.all(handles.map(({ path: createdPath }) => unlink3(createdPath).catch(() => void 0)));
@@ -1117,8 +1059,8 @@ async function missingBuddyAgentFiles(projectRoot) {
1117
1059
  }
1118
1060
 
1119
1061
  // packages/cli-core/src/config/index.ts
1120
- var BUDDY_AGENT_FILENAME = "buddy.agent.json";
1121
- var BUDDY_AGENT_SCHEMA = buddy_agent_schema_default;
1062
+ var BUDDY_PACKAGE_FILENAME = "package.json";
1063
+ var BUDDY_PACKAGE_SCHEMA = buddy_package_schema_default;
1122
1064
  var BuddyConfigValidationError = class extends Error {
1123
1065
  constructor(issues) {
1124
1066
  super(issues.map((issue2) => `${issue2.path}: ${issue2.message}`).join("\n"));
@@ -1128,7 +1070,7 @@ var BuddyConfigValidationError = class extends Error {
1128
1070
  issues;
1129
1071
  };
1130
1072
  var ajv = new Ajv2020({ allErrors: true, strict: true });
1131
- var validateAgentSchema = ajv.compile(buddy_agent_schema_default);
1073
+ var validateAgentSchema = ajv.compile(buddy_package_schema_default);
1132
1074
  function schemaIssues(errors) {
1133
1075
  return (errors ?? []).map((error2) => ({
1134
1076
  path: error2.instancePath || "/",
@@ -1154,7 +1096,7 @@ function validateBuddyConfig(value) {
1154
1096
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
1155
1097
  return { ok: false, issues: [{ path: "/", message: "\u914D\u7F6E\u5FC5\u987B\u662F\u5BF9\u8C61" }] };
1156
1098
  }
1157
- const result = validateBuddyAgentConfig({ schemaVersion: 1, ...value });
1099
+ const result = validateBuddyAgentConfig(value);
1158
1100
  return result.ok ? { ok: true, value } : result;
1159
1101
  }
1160
1102
  function assertBuddyConfig(value) {
@@ -1174,15 +1116,7 @@ function validateBuddyProjectManifest(value) {
1174
1116
  if (!validateAgentSchema(value)) {
1175
1117
  return { ok: false, issues: schemaIssues(validateAgentSchema.errors) };
1176
1118
  }
1177
- const manifest = value;
1178
- const seen = /* @__PURE__ */ new Set();
1179
- for (const [index, dataset] of (manifest.datasets ?? []).entries()) {
1180
- if (seen.has(dataset.id)) {
1181
- return { ok: false, issues: [{ path: `/datasets/${index}/id`, message: `\u6570\u636E\u96C6\u4E0D\u80FD\u91CD\u590D\u58F0\u660E\uFF1A${dataset.id}` }] };
1182
- }
1183
- seen.add(dataset.id);
1184
- }
1185
- return { ok: true, value: manifest };
1119
+ return { ok: true, value };
1186
1120
  }
1187
1121
  function validateBuddyAgentConfig(value) {
1188
1122
  return validateBuddyProjectManifest(value);
@@ -1208,18 +1142,13 @@ function serializeBuddyAgentConfig(config) {
1208
1142
  `;
1209
1143
  }
1210
1144
  function buddyAgentConfig(config) {
1211
- return assertBuddyAgentConfig({ schemaVersion: 1, ...config });
1145
+ return assertBuddyAgentConfig({ buddyId: config.buddyId });
1212
1146
  }
1213
1147
  function combineBuddyProject(config) {
1214
- const { schemaVersion: _version, ...project } = assertBuddyAgentConfig(config);
1215
- return project;
1148
+ return { buddyId: assertBuddyAgentConfig(config).buddyId };
1216
1149
  }
1217
1150
  function createBuddyConfig(options) {
1218
- return assertBuddyConfig({
1219
- buddyId: options.buddyId,
1220
- ...options.model === void 0 ? {} : { model: options.model },
1221
- datasets: options.datasets ?? []
1222
- });
1151
+ return assertBuddyConfig({ buddyId: options.buddyId });
1223
1152
  }
1224
1153
  var ProjectInitializationError = class extends Error {
1225
1154
  constructor(code2, message, targetPath, options) {
@@ -1296,7 +1225,7 @@ async function readExistingManifest(agentConfigPath) {
1296
1225
  if (state2.kind !== "other") {
1297
1226
  throw new ProjectInitializationError(
1298
1227
  "TARGET_CHANGED",
1299
- `${BUDDY_AGENT_FILENAME} \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u76EE\u5F55\u3002`,
1228
+ `${BUDDY_PACKAGE_FILENAME} \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u76EE\u5F55\u3002`,
1300
1229
  agentConfigPath
1301
1230
  );
1302
1231
  }
@@ -1304,7 +1233,7 @@ async function readExistingManifest(agentConfigPath) {
1304
1233
  if (!entry2.isFile() || entry2.isSymbolicLink()) {
1305
1234
  throw new ProjectInitializationError(
1306
1235
  "TARGET_CHANGED",
1307
- `${BUDDY_AGENT_FILENAME} \u5FC5\u987B\u662F\u9879\u76EE\u5185\u7684\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\u3002`,
1236
+ `${BUDDY_PACKAGE_FILENAME} \u5FC5\u987B\u662F\u9879\u76EE\u5185\u7684\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\u3002`,
1308
1237
  agentConfigPath
1309
1238
  );
1310
1239
  }
@@ -1313,7 +1242,7 @@ async function readExistingManifest(agentConfigPath) {
1313
1242
  } catch (cause) {
1314
1243
  throw new ProjectInitializationError(
1315
1244
  "TARGET_CHANGED",
1316
- `\u65E0\u6CD5\u8BFB\u53D6\u6216\u6821\u9A8C\u5DF2\u6709 ${BUDDY_AGENT_FILENAME}\u3002`,
1245
+ `\u65E0\u6CD5\u8BFB\u53D6\u6216\u6821\u9A8C\u5DF2\u6709 ${BUDDY_PACKAGE_FILENAME}\u3002`,
1317
1246
  agentConfigPath,
1318
1247
  { cause }
1319
1248
  );
@@ -1321,7 +1250,7 @@ async function readExistingManifest(agentConfigPath) {
1321
1250
  }
1322
1251
  async function planBuddyDraftInitialization(directory) {
1323
1252
  const rootDirectory = resolve4(directory);
1324
- const agentConfigPath = join8(rootDirectory, BUDDY_AGENT_FILENAME);
1253
+ const agentConfigPath = join8(rootDirectory, BUDDY_PACKAGE_FILENAME);
1325
1254
  const state2 = await pathState(rootDirectory);
1326
1255
  if (state2.kind === "other") {
1327
1256
  throw new ProjectInitializationError(
@@ -1349,7 +1278,7 @@ async function planBuddyDraftInitialization(directory) {
1349
1278
  }
1350
1279
  async function planBuddyProjectInitialization(options) {
1351
1280
  const rootDirectory = resolve4(options.directory);
1352
- const agentConfigPath = resolve4(rootDirectory, BUDDY_AGENT_FILENAME);
1281
+ const agentConfigPath = resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME);
1353
1282
  const state2 = await pathState(rootDirectory);
1354
1283
  if (state2.kind === "other") {
1355
1284
  throw new ProjectInitializationError(
@@ -1395,7 +1324,7 @@ async function publishNewFile(options) {
1395
1324
  let publishedHandle;
1396
1325
  const temporaryPath = join8(
1397
1326
  options.rootDirectory,
1398
- `.${options.temporaryLabel}.${process.pid}.${randomUUID3()}.tmp`
1327
+ `.${options.temporaryLabel}.${process.pid}.${randomUUID4()}.tmp`
1399
1328
  );
1400
1329
  let temporaryIdentity;
1401
1330
  let publishedIdentity;
@@ -1466,7 +1395,7 @@ async function publishNewFile(options) {
1466
1395
  async function replaceExistingFile(options) {
1467
1396
  const temporaryPath = join8(
1468
1397
  options.rootDirectory,
1469
- `.${options.temporaryLabel}.${process.pid}.${randomUUID3()}.tmp`
1398
+ `.${options.temporaryLabel}.${process.pid}.${randomUUID4()}.tmp`
1470
1399
  );
1471
1400
  const handle = await open3(temporaryPath, "wx", 384);
1472
1401
  try {
@@ -1478,7 +1407,7 @@ async function replaceExistingFile(options) {
1478
1407
  try {
1479
1408
  const root = await pathState(options.rootDirectory);
1480
1409
  if (root.kind !== "directory" || root.identity !== options.directoryIdentity || await fileIdentity(options.targetPath) !== options.expectedFileIdentity) throw targetChanged({ rootDirectory: options.rootDirectory });
1481
- await rename5(temporaryPath, options.targetPath);
1410
+ await rename6(temporaryPath, options.targetPath);
1482
1411
  if (await readFile9(options.targetPath, "utf8") !== options.contents) {
1483
1412
  throw targetChanged({ rootDirectory: options.rootDirectory });
1484
1413
  }
@@ -1496,7 +1425,7 @@ async function applyBuddyDraftInitialization(plan, draft) {
1496
1425
  if (current === void 0 || current.buddyId !== draft.buddyId || (await missingBuddyAgentFiles(plan.rootDirectory)).length === 0) {
1497
1426
  throw new ProjectInitializationError(
1498
1427
  "ALREADY_INITIALIZED",
1499
- `\u5DF2\u6709 ${BUDDY_AGENT_FILENAME} \u7ED1\u5B9A\u7684 buddyId \u4E0E\u672C\u6B21\u4E91\u7AEF\u642D\u5B50\u4E0D\u4E00\u81F4\u3002`,
1428
+ `\u5DF2\u6709 ${BUDDY_PACKAGE_FILENAME} \u7ED1\u5B9A\u7684 buddyId \u4E0E\u672C\u6B21\u4E91\u7AEF\u642D\u5B50\u4E0D\u4E00\u81F4\u3002`,
1500
1429
  plan.agentConfigPath
1501
1430
  );
1502
1431
  }
@@ -1520,7 +1449,7 @@ async function applyBuddyDraftInitialization(plan, draft) {
1520
1449
  if (cause.code === "EEXIST") {
1521
1450
  throw new ProjectInitializationError(
1522
1451
  "ALREADY_INITIALIZED",
1523
- `\u9879\u76EE\u5DF2\u7ECF\u5B58\u5728 ${BUDDY_AGENT_FILENAME}\uFF0C\u6CA1\u6709\u8986\u76D6\u4EFB\u4F55\u6587\u4EF6\u3002`,
1452
+ `\u9879\u76EE\u5DF2\u7ECF\u5B58\u5728 ${BUDDY_PACKAGE_FILENAME}\uFF0C\u6CA1\u6709\u8986\u76D6\u4EFB\u4F55\u6587\u4EF6\u3002`,
1524
1453
  plan.agentConfigPath,
1525
1454
  { cause }
1526
1455
  );
@@ -1528,7 +1457,7 @@ async function applyBuddyDraftInitialization(plan, draft) {
1528
1457
  if (cause instanceof ProjectInitializationError) throw cause;
1529
1458
  throw new ProjectInitializationError(
1530
1459
  "WRITE_FAILED",
1531
- `\u65E0\u6CD5\u5199\u5165 ${BUDDY_AGENT_FILENAME}\uFF0C\u9879\u76EE\u8EAB\u4EFD\u6CA1\u6709\u521D\u59CB\u5316\u5B8C\u6210\u3002`,
1460
+ `\u65E0\u6CD5\u5199\u5165 ${BUDDY_PACKAGE_FILENAME}\uFF0C\u9879\u76EE\u8EAB\u4EFD\u6CA1\u6709\u521D\u59CB\u5316\u5B8C\u6210\u3002`,
1532
1461
  plan.agentConfigPath,
1533
1462
  { cause }
1534
1463
  );
@@ -1539,7 +1468,7 @@ async function applyBuddyProjectInitialization(plan, config) {
1539
1468
  if (plan.existingManifest !== void 0 && plan.existingManifest.buddyId !== requestedConfig.buddyId) {
1540
1469
  throw new ProjectInitializationError(
1541
1470
  "ALREADY_INITIALIZED",
1542
- `\u5DF2\u6709 ${BUDDY_AGENT_FILENAME} \u7ED1\u5B9A\u7684\u662F ${plan.existingManifest.buddyId}\uFF0C\u4E0D\u80FD\u6539\u6210 ${requestedConfig.buddyId}\u3002`,
1471
+ `\u5DF2\u6709 ${BUDDY_PACKAGE_FILENAME} \u7ED1\u5B9A\u7684\u662F ${plan.existingManifest.buddyId}\uFF0C\u4E0D\u80FD\u6539\u6210 ${requestedConfig.buddyId}\u3002`,
1543
1472
  plan.agentConfigPath
1544
1473
  );
1545
1474
  }
@@ -1585,7 +1514,7 @@ async function applyBuddyProjectInitialization(plan, config) {
1585
1514
  if (cause.code === "EEXIST") {
1586
1515
  throw new ProjectInitializationError(
1587
1516
  "ALREADY_INITIALIZED",
1588
- `${BUDDY_AGENT_FILENAME} \u5DF2\u88AB\u5176\u4ED6\u64CD\u4F5C\u521B\u5EFA\uFF0C\u6CA1\u6709\u8986\u76D6\u4EFB\u4F55\u6587\u4EF6\u3002`,
1517
+ `${BUDDY_PACKAGE_FILENAME} \u5DF2\u88AB\u5176\u4ED6\u64CD\u4F5C\u521B\u5EFA\uFF0C\u6CA1\u6709\u8986\u76D6\u4EFB\u4F55\u6587\u4EF6\u3002`,
1589
1518
  plan.rootDirectory,
1590
1519
  { cause }
1591
1520
  );
@@ -1593,7 +1522,7 @@ async function applyBuddyProjectInitialization(plan, config) {
1593
1522
  if (cause instanceof ProjectInitializationError) throw cause;
1594
1523
  throw new ProjectInitializationError(
1595
1524
  "WRITE_FAILED",
1596
- `\u65E0\u6CD5\u5199\u5165 ${BUDDY_AGENT_FILENAME}\uFF0C\u9879\u76EE\u521D\u59CB\u5316\u6CA1\u6709\u5B8C\u6210\u3002`,
1525
+ `\u65E0\u6CD5\u5199\u5165 ${BUDDY_PACKAGE_FILENAME}\uFF0C\u9879\u76EE\u521D\u59CB\u5316\u6CA1\u6709\u5B8C\u6210\u3002`,
1597
1526
  plan.rootDirectory,
1598
1527
  { cause }
1599
1528
  );
@@ -1605,11 +1534,11 @@ async function initializeBuddyProject(options) {
1605
1534
  }
1606
1535
  async function readBuddyProjectManifest(projectRoot) {
1607
1536
  const rootDirectory = resolve4(projectRoot);
1608
- return parseBuddyProjectManifest(await readFile9(resolve4(rootDirectory, BUDDY_AGENT_FILENAME), "utf8"));
1537
+ return parseBuddyProjectManifest(await readFile9(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8"));
1609
1538
  }
1610
1539
  async function readBuddyAgentConfig(projectRoot) {
1611
1540
  const rootDirectory = resolve4(projectRoot);
1612
- const source = await readFile9(resolve4(rootDirectory, BUDDY_AGENT_FILENAME), "utf8");
1541
+ const source = await readFile9(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8");
1613
1542
  return parseBuddyAgentConfig(source);
1614
1543
  }
1615
1544
  async function readBuddyConfig(projectRoot) {
@@ -1673,7 +1602,15 @@ async function projectFileState(directory, filename) {
1673
1602
  async function searchUp(startDirectory) {
1674
1603
  let directory = startDirectory;
1675
1604
  while (true) {
1676
- if (await projectFileState(directory, BUDDY_AGENT_FILENAME) === "valid") return directory;
1605
+ if (await projectFileState(directory, BUDDY_PACKAGE_FILENAME) === "valid") {
1606
+ let pkg;
1607
+ try {
1608
+ pkg = JSON.parse(await readFile10(join9(directory, BUDDY_PACKAGE_FILENAME), "utf8"));
1609
+ } catch (cause) {
1610
+ throw new BuddyProjectContextError("PROJECT_CONFIG_INVALID", `\u65E0\u6CD5\u89E3\u6790 ${join9(directory, BUDDY_PACKAGE_FILENAME)}`, directory, { cause });
1611
+ }
1612
+ if (pkg && typeof pkg === "object" && Object.hasOwn(pkg, "buddyId")) return directory;
1613
+ }
1677
1614
  const parent = dirname(directory);
1678
1615
  if (parent === directory) return void 0;
1679
1616
  directory = parent;
@@ -1690,14 +1627,14 @@ async function requireBuddyProjectRoot(startDirectory) {
1690
1627
  "PROJECT_NOT_FOUND",
1691
1628
  [
1692
1629
  "\u5F53\u524D\u76EE\u5F55\u4E0D\u5C5E\u4E8E\u642D\u642D\u9879\u76EE\u3002",
1693
- `\u8BF7\u8FDB\u5165\u5305\u542B ${BUDDY_AGENT_FILENAME} \u7684\u9879\u76EE\u76EE\u5F55\u540E\u91CD\u8BD5\uFF0C\u6216\u8005\u8FD0\u884C buddy-cli init \u521B\u5EFA\u65B0\u9879\u76EE\u3002`
1630
+ `\u8BF7\u8FDB\u5165\u5305\u542B\u9876\u5C42 buddyId \u7684 ${BUDDY_PACKAGE_FILENAME} \u6240\u5728\u9879\u76EE\u76EE\u5F55\u540E\u91CD\u8BD5\uFF0C\u6216\u8005\u8FD0\u884C buddy-cli init \u521B\u5EFA\u65B0\u9879\u76EE\u3002`
1694
1631
  ].join("\n"),
1695
1632
  requested
1696
1633
  );
1697
1634
  }
1698
1635
  async function requireBuddyAgentProjectRoot(startDirectory) {
1699
1636
  const root = await requireBuddyProjectRoot(startDirectory);
1700
- const agentPath = join9(root, BUDDY_AGENT_FILENAME);
1637
+ const agentPath = join9(root, BUDDY_PACKAGE_FILENAME);
1701
1638
  try {
1702
1639
  await readBuddyAgentConfig(root);
1703
1640
  const missing2 = await missingBuddyAgentFiles(root);
@@ -1707,7 +1644,7 @@ async function requireBuddyAgentProjectRoot(startDirectory) {
1707
1644
  throw new BuddyProjectContextError(
1708
1645
  "PROJECT_NOT_FOUND",
1709
1646
  [
1710
- `\u5F53\u524D buddy.agent.json \u6240\u5728\u5DE5\u7A0B\u5C1A\u4E0D\u53EF\u8FD0\u884C\uFF1A${cause instanceof Error ? cause.message : "\u8BF7\u68C0\u67E5 buddy.agent.json \u4E0E\u5DE5\u7A0B\u6587\u4EF6"}`,
1647
+ `\u5F53\u524D package.json \u6240\u5728\u5DE5\u7A0B\u5C1A\u4E0D\u53EF\u8FD0\u884C\uFF1A${cause instanceof Error ? cause.message : "\u8BF7\u68C0\u67E5 package.json \u4E0E\u5DE5\u7A0B\u6587\u4EF6"}`,
1711
1648
  "\u8BF7\u5148\u8FD0\u884C buddy-cli init --mode direct \u8865\u9F50\u5B98\u65B9 Runtime \u5DE5\u7A0B\uFF0C\u518D\u8FD0\u884C dev\u3001preview \u6216 push\u3002"
1712
1649
  ].join("\n"),
1713
1650
  agentPath,
@@ -1768,7 +1705,7 @@ async function assertInitializableBuddyTarget(target) {
1768
1705
  } catch (cause) {
1769
1706
  throw new BuddyProjectContextError(
1770
1707
  "PROJECT_CONFIG_INVALID",
1771
- `${join9(projectRoot, BUDDY_AGENT_FILENAME)} \u4E0D\u662F\u6709\u6548\u7684\u9879\u76EE\u6E05\u5355\u3002`,
1708
+ `${join9(projectRoot, BUDDY_PACKAGE_FILENAME)} \u4E0D\u662F\u6709\u6548\u7684\u9879\u76EE\u6E05\u5355\u3002`,
1772
1709
  requested,
1773
1710
  { cause }
1774
1711
  );
@@ -1799,7 +1736,7 @@ async function runtimeCatalogSource(directory, options = {}) {
1799
1736
  var MODELS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli models [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
1800
1737
  \u59CB\u7EC8\u8054\u7F51\u67E5\u8BE2\u516C\u5171 npm \u6700\u65B0 Runtime\uFF0C\u8BFB\u53D6\u5E76\u7F13\u5B58\u5176\u6A21\u578B\u76EE\u5F55\u3002
1801
1738
  \u65E0\u9700\u767B\u5F55\u642D\u642D\u8D26\u53F7\u3002\u8F93\u51FA\u5305\u542B\u5B9E\u9645 Runtime \u7248\u672C\u548C\u6765\u6E90\u3002
1802
- \u5C06\u6240\u9009 ID \u5199\u5165 buddy.agent.json.model\uFF1B\u6A21\u677F\u5728 initialState.model \u4E2D\u4F7F\u7528\u5B83\u3002`;
1739
+ \u5C06\u6240\u9009 ID \u5199\u5165 src/buddy-options.mjs \u7684 initialState.model\uFF1B\u6A21\u677F\u5728 initialState.model \u4E2D\u4F7F\u7528\u5B83\u3002`;
1803
1740
  async function runModelsCommand(args, io, cwd, options = {}) {
1804
1741
  try {
1805
1742
  if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
@@ -1820,7 +1757,7 @@ ${MODELS_COMMAND_HELP}`);
1820
1757
  else {
1821
1758
  io.write(`npm \u6700\u65B0 Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.models.length} \u4E2A\u6A21\u578B\uFF1A`);
1822
1759
  for (const id of catalog.models) io.write(`- ${id}`);
1823
- io.write("\u5C06\u6240\u9009 ID \u5199\u5165 buddy.agent.json.model\uFF1B\u81EA\u5B9A\u4E49\u4F1A\u8BDD\u5DE5\u5382\u4E5F\u53EF\u6309\u4F1A\u8BDD\u8BBE\u7F6E initialState.model\u3002");
1760
+ io.write("\u5C06\u6240\u9009 ID \u5199\u5165 src/buddy-options.mjs \u7684 initialState.model\uFF1B\u81EA\u5B9A\u4E49\u4F1A\u8BDD\u5DE5\u5382\u4E5F\u53EF\u6309\u4F1A\u8BDD\u8BBE\u7F6E initialState.model\u3002");
1824
1761
  }
1825
1762
  return { exitCode: 0 };
1826
1763
  } catch (cause) {
@@ -1830,13 +1767,13 @@ ${MODELS_COMMAND_HELP}`);
1830
1767
  }
1831
1768
 
1832
1769
  // packages/cli-core/src/index.ts
1833
- import { lstat as lstat13 } from "node:fs/promises";
1770
+ import { lstat as lstat14 } from "node:fs/promises";
1834
1771
 
1835
1772
  // packages/cli-core/src/commands/datasets.ts
1836
1773
  import { resolve as resolve7 } from "node:path";
1837
1774
  var DATASETS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli datasets [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
1838
1775
  \u59CB\u7EC8\u8054\u7F51\u67E5\u8BE2\u516C\u5171 npm \u6700\u65B0 Runtime\uFF0C\u8BFB\u53D6\u5E76\u7F13\u5B58\u5176 DATA_ACCESS_CAPABILITIES\u3002
1839
- \u65E0\u9700\u767B\u5F55\u642D\u642D\u8D26\u53F7\u3002\u5C06\u6240\u9009 id \u4E0E\u7528\u9014 purpose \u5199\u5165 buddy.agent.json.datasets\uFF1B\u76EE\u5F55\u4E0D\u4EE3\u8868\u7528\u6237\u5DF2\u6388\u6743\u3002`;
1776
+ \u65E0\u9700\u767B\u5F55\u642D\u642D\u8D26\u53F7\u3002\u5C06\u6240\u9009 id \u4E0E\u7528\u9014 purpose \u5199\u5165 data-access.json.requirements\uFF1B\u76EE\u5F55\u4E0D\u4EE3\u8868\u7528\u6237\u5DF2\u6388\u6743\u3002`;
1840
1777
  async function runDatasetsCommand(args, io, cwd, options = {}) {
1841
1778
  try {
1842
1779
  if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
@@ -1857,7 +1794,7 @@ ${DATASETS_COMMAND_HELP}`);
1857
1794
  else {
1858
1795
  io.write(`npm \u6700\u65B0 Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.datasets.length} \u9879\u6570\u636E\u80FD\u529B\uFF1A`);
1859
1796
  for (const item of catalog.datasets) io.write(`- ${item.id} \u2014 ${item.title}\uFF08${item.source}\uFF0CSchema ${item.schemaVersion}\uFF09`);
1860
- io.write("\u5C06\u6240\u9009 id \u548C purpose \u5199\u5165 buddy.agent.json.datasets\uFF1B\u7528\u6237\u6388\u6743\u7531\u5E73\u53F0\u5904\u7406\u3002");
1797
+ io.write("\u5C06\u6240\u9009 id \u548C purpose \u5199\u5165 data-access.json.requirements\uFF1B\u7528\u6237\u6388\u6743\u7531\u5E73\u53F0\u5904\u7406\u3002");
1861
1798
  }
1862
1799
  return { exitCode: 0 };
1863
1800
  } catch (cause) {
@@ -1867,8 +1804,8 @@ ${DATASETS_COMMAND_HELP}`);
1867
1804
  }
1868
1805
 
1869
1806
  // packages/cli-core/src/commands/knowledge.ts
1870
- import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
1871
- import { lstat as lstat8, mkdir as mkdir7, readFile as readFile10, rename as rename6, unlink as unlink5, writeFile as writeFile7 } from "node:fs/promises";
1807
+ import { createHash as createHash2, randomUUID as randomUUID5 } from "node:crypto";
1808
+ import { lstat as lstat8, mkdir as mkdir7, readFile as readFile11, rename as rename7, unlink as unlink5, writeFile as writeFile6 } from "node:fs/promises";
1872
1809
  import { dirname as dirname2, join as join10, resolve as resolve8 } from "node:path";
1873
1810
  var MANIFEST = "knowledge-manifest.json";
1874
1811
  var INDEX = "resources/knowledge/index.md";
@@ -1927,7 +1864,7 @@ async function read(root, path) {
1927
1864
  });
1928
1865
  if (!entry2) return void 0;
1929
1866
  if (!entry2.isFile() || entry2.size > MAX_BYTES) throw new Error(`\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\u4E14\u4E0D\u8D85\u8FC7 100 MiB\uFF1A${path}`);
1930
- return readFile10(full);
1867
+ return readFile11(full);
1931
1868
  }
1932
1869
  async function requiredRead(root, path) {
1933
1870
  const bytes = await read(root, path);
@@ -1937,10 +1874,10 @@ async function requiredRead(root, path) {
1937
1874
  async function atomicWrite(root, path, value) {
1938
1875
  const full = await safePath(root, path);
1939
1876
  await mkdir7(dirname2(full), { recursive: true });
1940
- const temporary = `${full}.${randomUUID4()}.tmp`;
1941
- await writeFile7(temporary, value, { flag: "wx", mode: 384 });
1877
+ const temporary = `${full}.${randomUUID5()}.tmp`;
1878
+ await writeFile6(temporary, value, { flag: "wx", mode: 384 });
1942
1879
  try {
1943
- await rename6(temporary, full);
1880
+ await rename7(temporary, full);
1944
1881
  } finally {
1945
1882
  await unlink5(temporary).catch((error2) => {
1946
1883
  if (!missing(error2)) throw error2;
@@ -2113,7 +2050,7 @@ async function syncKnowledge(root, planPath) {
2113
2050
  if (current && hash2(current) !== hash2(content) && hash2(current) !== expected.get(path)) conflicts.push(path);
2114
2051
  }
2115
2052
  if (conflicts.length) {
2116
- const directory = `.buddy/knowledge/conflicts/${randomUUID4()}`;
2053
+ const directory = `.buddy/knowledge/conflicts/${randomUUID5()}`;
2117
2054
  for (const [path, content] of files) await atomicWrite(root, `${directory}/${path}`, content);
2118
2055
  await atomicWrite(root, `${directory}/${MANIFEST}`, json(next));
2119
2056
  return { status: "conflict", conflicts, candidateDirectory: directory, written: [] };
@@ -2180,11 +2117,11 @@ ${KNOWLEDGE_HELP}`);
2180
2117
  }
2181
2118
 
2182
2119
  // packages/cli-core/src/index.ts
2183
- import { join as join20, resolve as resolve18 } from "node:path";
2120
+ import { join as join21, resolve as resolve18 } from "node:path";
2184
2121
 
2185
2122
  // packages/cli-core/src/init/creator.ts
2186
- import { createHash as createHash3, randomUUID as randomUUID5 } from "node:crypto";
2187
- import { link as link2, lstat as lstat9, mkdir as mkdir8, readFile as readFile11, rename as rename7, unlink as unlink6, writeFile as writeFile8 } from "node:fs/promises";
2123
+ import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
2124
+ import { link as link2, lstat as lstat9, mkdir as mkdir8, readFile as readFile12, rename as rename8, unlink as unlink6, writeFile as writeFile7 } from "node:fs/promises";
2188
2125
  import { dirname as dirname3, join as join12 } from "node:path";
2189
2126
 
2190
2127
  // packages/cli-core/src/init/creator-package.ts
@@ -2269,18 +2206,19 @@ ${KNOWLEDGE_GUIDE}
2269
2206
  | \u5FC5\u987B\u9075\u5FAA\u7684\u5904\u7406\u987A\u5E8F\u6216\u9644\u52A0\u5904\u7406 | \u5148\u770B Runtime \u9ED8\u8BA4\u56DE\u5408\u662F\u5426\u6EE1\u8DB3\uFF1B\u5FC5\u987B\u7531\u7A0B\u5E8F\u4FDD\u8BC1\u7684\u987A\u5E8F\u53EF\u7528 Tool\uFF0C\u6216\u5728 \`src/buddy-options.mjs\` \u4F7F\u7528 \`beforeToolCall\`\u3001\`afterToolCall\`\u3001\`shouldStopAfterTurn\` \u7B49\u56DE\u5408\u94A9\u5B50\u3002 |
2270
2207
  | \u4EE5\u540E\u8FD8\u9700\u8981\u8BB0\u4F4F\u7684\u4FE1\u606F | \u901A\u8FC7 \`conversation.memory\` \u843D\u5B9E\u4FDD\u5B58\u3001\u8BFB\u53D6\u3001\u66F4\u65B0\u548C\u9057\u5FD8\uFF0C\u5E76\u6309\u9700\u8981\u5C01\u88C5\u4E3A\u6A21\u578B Tool\u3002\u65B0 Runtime \u4E0D\u4F1A\u81EA\u52A8\u67E5\u8BE2\u6216\u63D0\u70BC\u8BB0\u5FC6\uFF1B\u662F\u5426\u4FDD\u5B58\u3001\u4FDD\u5B58\u4EC0\u4E48\u5FC5\u987B\u7531\u4E1A\u52A1\u4EE3\u7801\u548C\u5DF2\u786E\u8BA4\u7684\u6570\u636E\u8FB9\u754C\u51B3\u5B9A\u3002 |
2271
2208
  | \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 |
2272
- | \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 |
2209
+ | \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\u578B\u76F4\u63A5\u5199\u5165\u4E1A\u52A1\u5DE5\u5382\u8FD4\u56DE\u7684 \`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 |
2273
2210
 
2274
- \`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
2211
+ \`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(createBuddyOptions)\`\uFF1B\u6A21\u578B\u76F4\u63A5\u5199\u5728\u5DE5\u5382\u8FD4\u56DE\u7684 \`initialState.model\`\uFF0C\u6A21\u677F\u4E3A \`kimi-k2.6\`\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.17.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
2275
2212
 
2276
2213
  ### \u6309\u76EE\u5F55\u804C\u8D23\u7EC4\u7EC7\u5B9E\u73B0
2277
2214
 
2278
2215
  | \u4F4D\u7F6E | \u804C\u8D23\u4E0E\u751F\u6210\u65F6\u673A |
2279
2216
  | --- | --- |
2280
- | \`buddy.agent.json\` | \u9ED8\u8BA4\u751F\u6210\uFF0C\u4FDD\u5B58\u5E73\u53F0\u8EAB\u4EFD\u3001\u53EF\u9009\u6A21\u578B\u548C\u6570\u636E\u9700\u6C42 datasets\uFF0C\u4E0D\u653E\u4E1A\u52A1\u51FD\u6570 |
2217
+ | \`package.json\` | \u9ED8\u8BA4\u751F\u6210\uFF0C\u4FDD\u5B58\u9876\u5C42 buddyId\u3001npm \u542F\u52A8\u547D\u4EE4\u548C\u4F9D\u8D56\uFF1B\u4E0D\u4FDD\u5B58 model\u3001datasets \u6216 schemaVersion |
2281
2218
  | \`agent.md\` | \u9ED8\u8BA4\u751F\u6210\uFF0C\u4FDD\u5B58\u7CFB\u7EDF Prompt |
2282
2219
  | \`start.mjs\` | \u9ED8\u8BA4\u751F\u6210\uFF0C\u8BFB\u53D6\u542F\u52A8\u914D\u7F6E\u3001\u542F\u52A8 Runtime \u5E76\u5904\u7406\u9000\u51FA |
2283
- | \`package.json\`\u3001\`package-lock.json\` | \u9ED8\u8BA4\u751F\u6210\uFF0C\u58F0\u660E\u542F\u52A8\u547D\u4EE4\u3001\u51C6\u786E Runtime \u7248\u672C\u5E76\u9501\u5B9A\u4F9D\u8D56 |
2220
+ | \`package-lock.json\` | \u9ED8\u8BA4\u751F\u6210\uFF0C\u9501\u5B9A\u4F9D\u8D56 |
2221
+ | \`data-access.json\` | \u9ED8\u8BA4\u751F\u6210\uFF0Crequirements \u6570\u7EC4\u58F0\u660E\u6570\u636E\u96C6 ID \u548C\u7528\u9014\uFF1B\u65E0\u9700\u6C42\u4E3A\u7A7A\u6570\u7EC4 |
2284
2222
  | \`src/buddy-options.mjs\` | \u9ED8\u8BA4\u751F\u6210\uFF0C\u7EC4\u88C5\u5E76\u6CE8\u518C\u4F1A\u8BDD\u4E2D\u7684\u80FD\u529B |
2285
2223
  | \`src/tools/\` | \u9ED8\u8BA4\u7A7A\u76EE\u5F55\uFF1B\u653E\u6A21\u578B\u53EF\u8C03\u7528\u7684\u5DE5\u5177\u540D\u79F0\u3001\u8BF4\u660E\u3001\u53C2\u6570 Schema \u548C\u6267\u884C\u51FD\u6570 |
2286
2224
  | \`src/hooks/\` | \u9ED8\u8BA4\u7A7A\u76EE\u5F55\uFF1B\u653E\u5DE5\u5177\u8C03\u7528\u524D\u540E\u3001\u505C\u6B62\u7B49\u94A9\u5B50 |
@@ -2301,9 +2239,9 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
2301
2239
 
2302
2240
  \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
2303
2241
 
2304
- \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 npm \u6700\u65B0 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002CLI \u6BCF\u6B21\u67E5\u8BE2 latest\uFF0C\u540C\u7248\u672C\u590D\u7528\u7F13\u5B58\uFF0C\u4E0D\u590D\u5236\u679A\u4E3E\u3002\u76EE\u5F55\u547D\u4EE4\u4F1A\u63D0\u793A\u5DE5\u7A0B\u7248\u672C\u5DEE\u5F02\uFF1B\u4F7F\u7528\u65B0\u7248\u80FD\u529B\u524D\uFF0C\u7531\u4F60\u6216\u5F00\u53D1 Agent \u6309\u63D0\u793A\u5347\u7EA7\u4F9D\u8D56\uFF0C\u68C0\u67E5\u542F\u52A8\u53C2\u6570\u3001\u6A21\u578B\u3001datasets\u3001\u5DE5\u5177\u53CA Hook \u7684\u9002\u914D\u5E76\u9A8C\u8BC1 DEV\u3002CLI \u4E0D\u81EA\u52A8\u4FEE\u6539\u5DE5\u7A0B\u4F9D\u8D56\u6216\u914D\u7F6E\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
2242
+ \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 npm \u6700\u65B0 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002CLI \u6BCF\u6B21\u67E5\u8BE2 latest\uFF0C\u540C\u7248\u672C\u590D\u7528\u7F13\u5B58\uFF0C\u4E0D\u590D\u5236\u679A\u4E3E\u3002\u76EE\u5F55\u547D\u4EE4\u4F1A\u63D0\u793A\u5DE5\u7A0B\u7248\u672C\u5DEE\u5F02\uFF1B\u4F7F\u7528\u65B0\u7248\u80FD\u529B\u524D\uFF0C\u7531\u4F60\u6216\u5F00\u53D1 Agent \u6309\u63D0\u793A\u5347\u7EA7\u4F9D\u8D56\uFF0C\u68C0\u67E5\u542F\u52A8\u53C2\u6570\u3001\u6A21\u578B\u3001datasets\u3001\u5DE5\u5177\u53CA Hook \u7684\u9002\u914D\u5E76\u9A8C\u8BC1 DEV\u3002CLI \u4E0D\u81EA\u52A8\u4FEE\u6539\u5DE5\u7A0B\u4F9D\u8D56\u6216\u914D\u7F6E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`data-access.json.requirements\`\uFF0C\u6700\u591A 32 \u9879\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0CID \u548C\u7528\u9014\u53BB\u9664\u9996\u5C3E\u7A7A\u767D\uFF0C\u7528\u9014\u4E3A 1\uFF5E200 \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
2305
2243
 
2306
- \`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
2244
+ Runtime \u542F\u52A8\u65F6\u8BFB\u53D6\u6839\u76EE\u5F55 \`data-access.json\`\uFF0C\u901A\u8FC7 \`PUT /internal/v1/data-access/requirements\` \u767B\u8BB0\uFF0C\u6210\u529F\u540E\u518D\u8FDE\u63A5\u4E8B\u4EF6\u6D41\uFF1B\u767B\u8BB0\u5931\u8D25\u963B\u6B62\u542F\u52A8\u3002\u6587\u4EF6\u7F3A\u5931\u6216\u7A7A\u6570\u7EC4\u90FD\u4F1A\u4E0A\u4F20\u7A7A\u58F0\u660E\u5E76\u6E05\u9664\u65E7\u58F0\u660E\u3002DEV \u4FDD\u5B58\u8BE5\u6587\u4EF6\u540E\u81EA\u52A8\u91CD\u542F\u5E76\u91CD\u65B0\u767B\u8BB0\u3002\u58F0\u660E\u4E0D\u8868\u793A\u7528\u6237\u5DF2\u6388\u6743\uFF1B\u4F4D\u7F6E\u548C\u65E5\u5386\u4E0D\u653E\u5165\u6B64\u6587\u4EF6\u3002
2307
2245
 
2308
2246
  \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\u67E5\u8BE2\u6216\u9501\u6587\u4EF6\u751F\u6210\u5931\u8D25\u65F6\u505C\u6B62\uFF0C\u4E0D\u56DE\u9000\u5185\u7F6E\u65E7\u7248\u672C\u3002\u5DF2\u6709\u5DE5\u7A0B\u901A\u8FC7\u5305\u7BA1\u7406\u5668\u663E\u5F0F\u5347\u7EA7\u4F9D\u8D56\u3002CLI \u7684 DEV \u542F\u52A8\u3001\u81EA\u52A8\u91CD\u8F7D\u548C push \u5FC5\u987B\u4F7F\u7528\u672C\u6B21 npm \u6700\u65B0\u7A33\u5B9A\u7248\uFF0C\u58F0\u660E\u3001\u5B89\u88C5\u548C npm \u9501\u6587\u4EF6\u7248\u672C\u5FC5\u987B\u4E00\u81F4\uFF0C\u67E5\u8BE2\u5931\u8D25\u4F1A\u963B\u6B62\u64CD\u4F5C\u3002
2309
2247
 
@@ -2360,7 +2298,7 @@ function legacyHandoffMarkdown(context, skillRoot, session, workspacePath) {
2360
2298
  ## \u5DF2\u5B8C\u6210\u7684\u8EAB\u4EFD\u767B\u8BB0
2361
2299
 
2362
2300
  \u9879\u76EE\u6E05\u5355\uFF1A${JSON.stringify(context.manifestPath)}\u3002\u5176\u4E2D\u7684 buddyId \u7ED1\u5B9A\u5DF2\u7ECF\u767B\u8BB0\u7684\u4E91\u7AEF\u642D\u5B50\uFF1B\u540D\u79F0\u3001tagline \u548C intro \u4EE5\u5E73\u53F0 Meta \u4E3A\u51C6\uFF0C\u4E0D\u4FDD\u5B58\u5728\u672C\u5730\u6E05\u5355\u3002
2363
- \u5E73\u53F0 buddyId\uFF1A${JSON.stringify(context.buddyId)}\u3002Skill \u81EA\u5DF1\u7684 buddyId \u53EA\u6807\u8BC6\u672C\u5730\u4F5C\u54C1\uFF0C\u4E0D\u80FD\u66FF\u6362 buddy.agent.json.buddyId\uFF0C\u4E5F\u4E0D\u8981\u91CD\u65B0\u521B\u5EFA\u4E91\u7AEF\u642D\u5B50\u3002
2301
+ \u5E73\u53F0 buddyId\uFF1A${JSON.stringify(context.buddyId)}\u3002Skill \u81EA\u5DF1\u7684 buddyId \u53EA\u6807\u8BC6\u672C\u5730\u4F5C\u54C1\uFF0C\u4E0D\u80FD\u66FF\u6362 package.json.buddyId\uFF0C\u4E5F\u4E0D\u8981\u91CD\u65B0\u521B\u5EFA\u4E91\u7AEF\u642D\u5B50\u3002
2364
2302
 
2365
2303
  \u672C\u6B21\u5F00\u59CB\u521B\u4F5C\u65F6\u7684\u5E73\u53F0\u8D44\u6599\u5982\u4E0B\uFF1B\u5B83\u4EEC\u53EA\u662F\u91C7\u8BBF\u8D77\u70B9\uFF0C\u540E\u7EED\u4FEE\u6539\u4ECD\u4EE5\u5E73\u53F0 Meta \u4E3A\u51C6\uFF1A
2366
2304
 
@@ -2405,7 +2343,7 @@ ${IMPLEMENTATION_GUIDE}
2405
2343
  ${JSON.stringify(directArgs, null, 2)}
2406
2344
  \`\`\`
2407
2345
 
2408
- \u8BE5\u547D\u4EE4\u590D\u7528 buddy.agent.json \u4E2D\u7684 buddyId\uFF0C\u5E76\u4ECE\u5E73\u53F0\u8BFB\u53D6\u6700\u65B0 Meta\u3001\u91CD\u65B0\u9A8C\u8BC1\u5F52\u5C5E\uFF0C\u4E0D\u4F1A\u53E6\u5EFA\u642D\u5B50\u3002\u5DE5\u7A0B\u7EDF\u4E00\u4F7F\u7528\u5B98\u65B9 Runtime\uFF1B\u5168\u90E8\u8BBE\u8BA1\u9A8C\u6536\u53CA\u4EA4\u4ED8\u6821\u9A8C\u5B8C\u6210\u524D\u4E0D\u751F\u6210\u4E1A\u52A1\u4EE3\u7801\uFF0C\u4E5F\u4E0D\u8981\u628A\u9700\u6C42\u624B\u518C\u8BF4\u6210\u5DF2\u5B9E\u73B0\u4EE3\u7801\u3002
2346
+ \u8BE5\u547D\u4EE4\u590D\u7528 package.json \u4E2D\u7684 buddyId\uFF0C\u5E76\u4ECE\u5E73\u53F0\u8BFB\u53D6\u6700\u65B0 Meta\u3001\u91CD\u65B0\u9A8C\u8BC1\u5F52\u5C5E\uFF0C\u4E0D\u4F1A\u53E6\u5EFA\u642D\u5B50\u3002\u5DE5\u7A0B\u7EDF\u4E00\u4F7F\u7528\u5B98\u65B9 Runtime\uFF1B\u5168\u90E8\u8BBE\u8BA1\u9A8C\u6536\u53CA\u4EA4\u4ED8\u6821\u9A8C\u5B8C\u6210\u524D\u4E0D\u751F\u6210\u4E1A\u52A1\u4EE3\u7801\uFF0C\u4E5F\u4E0D\u8981\u628A\u9700\u6C42\u624B\u518C\u8BF4\u6210\u5DF2\u5B9E\u73B0\u4EE3\u7801\u3002
2409
2347
  \u5DF2\u6709\u5B8C\u6574 Agent \u5DE5\u7A0B\u65F6\u4E0D\u91CD\u590D init\uFF0C\u76F4\u63A5\u6309\u624B\u518C\u7EE7\u7EED\u5B9E\u73B0\u3002\u6821\u9A8C\u9879\u76EE\u8EAB\u4EFD\u4E0E Booklet \u6765\u6E90\uFF0C\u4E0D\u7528\u5176\u4ED6\u642D\u5B50\u7684\u624B\u518C\u6216\u76EE\u5F55\u3002
2410
2348
  ${DEVELOPMENT_HANDOFF}
2411
2349
  `;
@@ -2413,7 +2351,6 @@ ${DEVELOPMENT_HANDOFF}
2413
2351
 
2414
2352
  // packages/cli-core/src/init/creator.ts
2415
2353
  var MAX_LOCAL_FILE_BYTES = 1024 * 1024;
2416
- var IMPLEMENTATION_GUIDANCE2 = "\u8BFB\u53D6 completion.manualPath \u6307\u5411\u7684\u771F\u5B9E\u624B\u518C\u548C\u73B0\u6709\u5DE5\u7A0B\uFF0C\u5B8C\u6574\u7406\u89E3\u9700\u6C42\u540E\u6309\u4E0B\u65B9\u6307\u5F15\u843D\u5B9E\u5230\u4EE3\u7801\u3002\u5DF2\u786E\u8BA4\u6216\u80FD\u591F\u636E\u6B64\u786E\u5B9A\u7684\u76F4\u63A5\u5B9E\u73B0\uFF0C\u4E0D\u518D\u56FA\u5B9A\u786E\u8BA4\u4E00\u904D\uFF1B\u53EA\u6709\u5F71\u54CD\u4F53\u9A8C\u3001\u6570\u636E\u4F7F\u7528\u6216\u6388\u6743\u7684\u5173\u952E\u7F3A\u53E3\u624D\u8865\u95EE\u3002\u7EDF\u4E00\u4F7F\u7528\u5B98\u65B9 Runtime\uFF0C\u6309\u9700\u6C42\u914D\u7F6E Prompt\u3001\u4E1A\u52A1 Tool \u548C\u56DE\u5408\u94A9\u5B50\u3002";
2417
2354
  var CreatorPreparationError = class extends Error {
2418
2355
  };
2419
2356
  async function state(path) {
@@ -2436,11 +2373,11 @@ async function safeRead(path) {
2436
2373
  if (!entry2.isFile() || entry2.size > MAX_LOCAL_FILE_BYTES) {
2437
2374
  throw new CreatorPreparationError(`\u521B\u4F5C\u6587\u4EF6\u4E0D\u662F\u666E\u901A\u6587\u4EF6\u6216\u8D85\u51FA\u5927\u5C0F\u9650\u5236\uFF1A${path}`);
2438
2375
  }
2439
- return readFile11(path);
2376
+ return readFile12(path);
2440
2377
  }
2441
2378
  async function writeOnce(path, bytes) {
2442
- const temporary = `${path}.${randomUUID5()}.tmp`;
2443
- await writeFile8(temporary, bytes, { flag: "wx", mode: 384 });
2379
+ const temporary = `${path}.${randomUUID6()}.tmp`;
2380
+ await writeFile7(temporary, bytes, { flag: "wx", mode: 384 });
2444
2381
  try {
2445
2382
  await link2(temporary, path).catch((cause) => {
2446
2383
  if (cause.code !== "EEXIST") throw cause;
@@ -2450,10 +2387,10 @@ async function writeOnce(path, bytes) {
2450
2387
  }
2451
2388
  }
2452
2389
  async function replaceFile(path, content) {
2453
- const temporary = `${path}.${randomUUID5()}.tmp`;
2390
+ const temporary = `${path}.${randomUUID6()}.tmp`;
2454
2391
  try {
2455
- await writeFile8(temporary, content, { flag: "wx", mode: 384 });
2456
- await rename7(temporary, path);
2392
+ await writeFile7(temporary, content, { flag: "wx", mode: 384 });
2393
+ await rename8(temporary, path);
2457
2394
  } finally {
2458
2395
  await unlink6(temporary).catch((error2) => {
2459
2396
  if (error2.code !== "ENOENT") throw error2;
@@ -2476,7 +2413,10 @@ function handoffMarkdown(context, skillRoot, session, workspacePath) {
2476
2413
  ];
2477
2414
  return `# Buddy \u521B\u5EFA\u63A5\u7EED\u8BF4\u660E
2478
2415
 
2479
- <!-- buddy-cli creator-handoff:2 -->
2416
+ <!-- buddy-cli creator-handoff:3 -->
2417
+
2418
+ \u5148\u6267\u884C \`buddy-cli guide\` \u5E76\u5B8C\u6574\u9605\u8BFB\u5F53\u524D\u5F00\u53D1\u6307\u5F15\uFF1BCLI \u4F1A\u5148\u81EA\u68C0\u5E76\u5728\u9700\u8981\u65F6\u81EA\u52A8\u66F4\u65B0\uFF0C\u7B49\u5F85\u547D\u4EE4\u5B8C\u6210\uFF0C\u4E0D\u91CD\u590D\u53D1\u8D77\u3002
2419
+ \u672C\u6587\u4EF6\u53EA\u63D0\u4F9B\u672C\u6B21\u5DE5\u7A0B\u4E0E Skill \u7684\u63A5\u7EED\u4FE1\u606F\uFF1B\u901A\u7528\u5F00\u53D1\u548C\u4EA4\u4ED8\u89C4\u5219\u4EE5 guide \u4E3A\u51C6\u3002
2480
2420
 
2481
2421
  \u9879\u76EE\u6E05\u5355\uFF1A${JSON.stringify(context.manifestPath)}\u3002
2482
2422
  \u5E73\u53F0 buddyId\uFF1A${JSON.stringify(context.buddyId)}\u3002\u6B64\u8EAB\u4EFD\u5DF2\u767B\u8BB0\uFF0C\u4E0D\u53E6\u5EFA\u4E91\u7AEF\u642D\u5B50\uFF1BSkill \u7684\u4F5C\u54C1 ID \u4E0D\u66FF\u6362\u5E73\u53F0\u8EAB\u4EFD\u3002
@@ -2497,8 +2437,7 @@ ${JSON.stringify(openArgs, null, 2)}
2497
2437
 
2498
2438
  \u4EC5 directive=creator_complete \u4E14 completion.status=ready\u3001manualPath \u5B58\u5728\u4E14\u4EA4\u4ED8\u6709\u6548\u65F6\u8FDB\u5165\u5F00\u53D1\u3002directive=finalize_required \u65F6\u5148\u4FEE\u590D\u4EA4\u4ED8\u3002\u5DF2\u5B8C\u6210\u4F5C\u54C1\u76F4\u63A5\u63A5\u56DE\u5F00\u53D1\uFF1B\u7528\u6237\u660E\u786E\u4EC5\u505A\u8BBE\u8BA1\u6216\u6682\u505C\u65F6\u9075\u5B88\u8BE5\u8303\u56F4\u3002
2499
2439
 
2500
- ${IMPLEMENTATION_GUIDANCE2}
2501
- ${IMPLEMENTATION_GUIDE}
2440
+ \u91CD\u65B0\u6267\u884C \`buddy-cli guide\` \u83B7\u53D6\u5F53\u524D\u89C4\u5219\uFF0C\u8BFB\u53D6 completion.manualPath \u6307\u5411\u7684\u771F\u5B9E\u624B\u518C\u4E0E\u73B0\u6709\u5DE5\u7A0B\uFF0C\u518D\u6309\u5F00\u53D1\u6307\u5F15\u7EE7\u7EED\u5B9E\u73B0\u3002
2502
2441
 
2503
2442
  \u4F7F\u7528\u5B98\u65B9 Runtime \u521D\u59CB\u5316\u5DE5\u7A0B\uFF0C\u8C03\u7528 buddy-cli\uFF0Cargv \u4E3A\uFF1A
2504
2443
 
@@ -2506,8 +2445,7 @@ ${IMPLEMENTATION_GUIDE}
2506
2445
  ${JSON.stringify(["init", "--mode", "direct", "--directory", context.projectRoot], null, 2)}
2507
2446
  \`\`\`
2508
2447
 
2509
- \u5DF2\u6709\u5B8C\u6574\u5DE5\u7A0B\u4E0D\u91CD\u590D\u521D\u59CB\u5316\u3002\u590D\u7528\u5F53\u524D\u8EAB\u4EFD\uFF0C\u8BFB\u53D6\u771F\u5B9E\u4EA4\u4ED8\u3001\u6765\u6E90\u4E0E\u73B0\u6709\u4EE3\u7801\uFF0C\u5B8C\u6210\u540E\u6309\u4E0B\u65B9\u6D41\u7A0B\u9A8C\u8BC1\u3002
2510
- ${DEVELOPMENT_HANDOFF}
2448
+ \u5DF2\u6709\u5B8C\u6574\u5DE5\u7A0B\u4E0D\u91CD\u590D\u521D\u59CB\u5316\u3002\u590D\u7528\u5F53\u524D\u8EAB\u4EFD\uFF0C\u8BFB\u53D6\u771F\u5B9E\u4EA4\u4ED8\u3001\u6765\u6E90\u4E0E\u73B0\u6709\u4EE3\u7801\uFF0C\u6309 guide \u5B8C\u6210\u9A8C\u8BC1\u548C\u5F00\u53D1\u8005\u9884\u89C8\u4EA4\u63A5\u3002
2511
2449
  `;
2512
2450
  }
2513
2451
  async function prepareCreatorSkill(context, io, options = {}) {
@@ -2519,7 +2457,7 @@ async function prepareCreatorSkill(context, io, options = {}) {
2519
2457
  await writeOnce(sessionPath, JSON.stringify({
2520
2458
  schemaVersion: 1,
2521
2459
  platformBuddyId: context.buddyId,
2522
- creationKey: randomUUID5()
2460
+ creationKey: randomUUID6()
2523
2461
  }, null, 2) + "\n");
2524
2462
  const session = JSON.parse((await safeRead(sessionPath)).toString("utf8"));
2525
2463
  if (session.schemaVersion !== 1 || session.platformBuddyId !== context.buddyId || !/^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/u.test(session.creationKey)) {
@@ -2589,7 +2527,7 @@ async function prepareCreatorSkill(context, io, options = {}) {
2589
2527
  } catch (cause) {
2590
2528
  const message = cause instanceof Error ? cause.message : "Creator \u4E0B\u8F7D\u6216\u672C\u5730\u5199\u5165\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u548C\u76EE\u5F55\u6743\u9650\u3002";
2591
2529
  io.writeError(`Creator Skill \u51C6\u5907\u5931\u8D25\uFF1A${message}`);
2592
- io.writeError(`buddy.agent.json \u548C\u5DF2\u6709\u521B\u4F5C\u8D44\u6599\u5DF2\u4FDD\u7559\u3002\u91CD\u8BD5 buddy-cli init --mode create --directory ${JSON.stringify(context.projectRoot)}\uFF0C\u4E0D\u4F1A\u53E6\u5EFA\u4E91\u7AEF\u642D\u5B50\u3002`);
2530
+ io.writeError(`package.json \u548C\u5DF2\u6709\u521B\u4F5C\u8D44\u6599\u5DF2\u4FDD\u7559\u3002\u91CD\u8BD5 buddy-cli init --mode create --directory ${JSON.stringify(context.projectRoot)}\uFF0C\u4E0D\u4F1A\u53E6\u5EFA\u4E91\u7AEF\u642D\u5B50\u3002`);
2593
2531
  return { exitCode: 1 };
2594
2532
  }
2595
2533
  }
@@ -2667,6 +2605,7 @@ var CLI_HELP = `\u642D\u642D Developer Platform CLI
2667
2605
  --version \u67E5\u770B\u5F53\u524D CLI \u7248\u672C
2668
2606
 
2669
2607
  \u76F4\u63A5\u8FD0\u884C buddy-cli \u53EF\u8BC6\u522B\u5F53\u524D\u5DE5\u7A0B\u6216\u5F15\u5BFC\u521B\u5EFA\u3002
2608
+ \u6B63\u5E38\u547D\u4EE4\u5148\u8054\u7F51\u81EA\u68C0\uFF0C\u65E7\u7248\u81EA\u52A8\u66F4\u65B0\u540E\u7EE7\u7EED\u6267\u884C\uFF1B\u5931\u8D25\u65F6\u505C\u6B62\u3002\u5E2E\u52A9\u548C --version \u79BB\u7EBF\u53EF\u7528\u3002
2670
2609
  \u53C2\u6570\u4E0E\u793A\u4F8B: buddy-cli <\u547D\u4EE4> --help\uFF0C\u4F8B\u5982 buddy-cli init --help\u3002
2671
2610
  Coding Agent \u5F00\u59CB\u5DE5\u4F5C\u524D\u8BF7\u8BFB\u53D6 buddy-cli guide\u3002`;
2672
2611
  var INIT_HELP = `\u7528\u6CD5: buddy-cli init [\u53C2\u6570]
@@ -2694,12 +2633,20 @@ var INIT_HELP = `\u7528\u6CD5: buddy-cli init [\u53C2\u6570]
2694
2633
  Coding Agent \u7684\u786E\u8BA4\u4E0E\u63A5\u7EED\u89C4\u5219\u89C1 buddy-cli guide\u3002`;
2695
2634
  var GUIDE_HELP = `\u7528\u6CD5: buddy-cli guide
2696
2635
  \u8F93\u51FA Coding Agent \u7684\u5B8C\u6574\u5F00\u53D1\u6307\u5F15\uFF0C\u5305\u62EC\u8D44\u6599\u786E\u8BA4\u3001Skill \u63A5\u7EED\u3001\u5B9E\u73B0\u4E0E\u4EA4\u4ED8\u89C4\u5219\u3002
2697
- \u65E0\u9700\u5DE5\u7A0B\u3001\u767B\u5F55\u6216\u8054\u7F51\uFF1B\u53EA\u8F93\u51FA\u6587\u5B57\uFF0C\u4E0D\u751F\u6210\u6587\u4EF6\u6216\u6267\u884C\u5F00\u53D1\u3002`;
2636
+ \u65E0\u9700\u5DE5\u7A0B\u6216\u767B\u5F55\uFF1B\u5148\u8054\u7F51\u68C0\u67E5 CLI \u5E76\u6309\u9700\u81EA\u52A8\u66F4\u65B0\uFF0C\u518D\u8F93\u51FA\u65B0\u7248\u6307\u5357\uFF0C\u4E0D\u4FEE\u6539\u5DE5\u7A0B\u6216\u6267\u884C\u5F00\u53D1\u3002`;
2698
2637
  var AGENT_GUIDE = `# Coding Agent \u5F00\u53D1\u6307\u5F15
2699
2638
 
2700
2639
  \u901A\u7528\u89C4\u5219\u5728\u6B64\u8BFB\u53D6\uFF1B\u53C2\u6570\u89C1 buddy-cli <\u547D\u4EE4> --help\uFF0C\u5DE5\u7A0B\u72B6\u6001\u4E0E\u5177\u4F53\u63A5\u7EED\u6B65\u9AA4\u4EE5 CLI \u8FD4\u56DE\u7684 HANDOFF.md \u4E3A\u51C6\u3002
2701
2640
  Skill \u7684\u5177\u4F53\u6D41\u7A0B\u8BFB\u53D6 HANDOFF.md \u4E2D\u7684\u6587\u4EF6\u8DEF\u5F84\uFF1B\u65E0\u9700\u5728 CLI \u5E2E\u52A9\u4E2D\u7EF4\u62A4\u4E00\u4EFD\u526F\u672C\u3002
2702
2641
 
2642
+ ## CLI \u7248\u672C\u4E0E\u6267\u884C\u89C4\u5219
2643
+
2644
+ \u4F7F\u7528\u5B98\u65B9 buddy-cli \u5165\u53E3\u3002\u6BCF\u6761\u6B63\u5E38\u547D\u4EE4\uFF08\u5305\u62EC guide\uFF09\u6267\u884C\u524D\u90FD\u4F1A\u67E5\u8BE2\u516C\u5171 npm latest\uFF1B\u7248\u672C\u8FC7\u65E7\u65F6\u81EA\u52A8\u66F4\u65B0\uFF0C\u518D\u7531\u65B0\u7248\u6267\u884C\u540C\u4E00\u547D\u4EE4\u3002\u7B49\u5F85\u5F53\u524D\u547D\u4EE4\u5B8C\u6210\uFF0C\u4E0D\u91CD\u590D\u53D1\u8D77\uFF0C\u4E0D\u53E6\u5F00\u8FDB\u7A0B\u540C\u65F6\u91CD\u8DD1\u3002
2645
+ \u5168\u5C40\u5B89\u88C5\u66F4\u65B0\u5BF9\u5E94 npm \u73AF\u5883\u7684\u5B89\u88C5\uFF1B\u6E90\u7801\u3001npm link\u3001\u9879\u76EE\u5185\u5B89\u88C5\u548C npx \u901A\u8FC7\u7F13\u5B58\u7684\u65B0\u7248\u7EE7\u7EED\u6267\u884C\uFF0C\u4E0D\u6539\u5199\u6E90\u7801\u6216\u9879\u76EE\u4F9D\u8D56\u3002\u53C2\u6570\u3001\u5DE5\u4F5C\u76EE\u5F55\u3001\u7EC8\u7AEF\u8F93\u5165\u8F93\u51FA\u548C\u9000\u51FA\u72B6\u6001\u4FDD\u7559\u3002\u4E00\u6B21\u8C03\u7528\u6700\u591A\u81EA\u52A8\u5207\u6362\u4E00\u6B21\uFF1B\u5F53\u524D\u7248\u672C\u9AD8\u4E8E latest \u65F6\u4E0D\u964D\u7EA7\uFF0C\u5DF2\u8FD0\u884C\u7684 DEV \u4E0D\u4F1A\u56E0\u53D1\u5E03\u65B0 CLI \u81EA\u52A8\u91CD\u542F\u3002
2646
+ \u5E2E\u52A9\u3001\u5404\u547D\u4EE4 --help \u548C --version \u79BB\u7EBF\u53EF\u7528\uFF1Bupdate \u662F\u5355\u72EC\u68C0\u67E5\u6216\u66F4\u65B0\u5165\u53E3\u3002\u67E5\u8BE2\u6216\u66F4\u65B0\u5931\u8D25\u65F6\u539F\u4E1A\u52A1\u64CD\u4F5C\u4E0D\u4F1A\u5F00\u59CB\uFF0C\u6839\u636E\u9519\u8BEF\u5904\u7406\u540E\u91CD\u8BD5\uFF0C\u4E0D\u8C03\u7528\u65E7\u7248\u6E90\u7801\u7ED5\u8FC7\u68C0\u67E5\u3002\u65E7 CLI \u9700\u5148\u901A\u8FC7\u5B98\u65B9 npm \u5B89\u88C5\u547D\u4EE4\u5347\u7EA7\u4E00\u6B21\uFF0C\u624D\u80FD\u83B7\u5F97\u6B64\u673A\u5236\u3002
2647
+ CLI \u81EA\u52A8\u66F4\u65B0\u4E0D\u7B49\u4E8E\u5DE5\u7A0B Runtime \u5DF2\u9002\u914D\u3002\u4ECD\u987B\u6839\u636E Runtime \u68C0\u67E5\u7ED3\u679C\u66F4\u65B0\u5DE5\u7A0B\u4F9D\u8D56\u3001\u9501\u6587\u4EF6\u548C\u5FC5\u8981\u7684\u4E1A\u52A1\u4EE3\u7801\uFF0C\u5B8C\u6210\u9A8C\u8BC1\u540E\u518D\u542F\u52A8\u6216\u4E0A\u4F20\uFF1B\u4E0D\u8981\u53EA\u4FEE\u6539\u7248\u672C\u53F7\u5C31\u5BA3\u79F0\u9002\u914D\u5B8C\u6210\u3002
2648
+ \u901A\u7528\u89C4\u5219\u4EE5\u672C\u547D\u4EE4\u7684\u5F53\u524D\u8F93\u51FA\u4E3A\u51C6\u3002HANDOFF.md \u53EA\u63D0\u4F9B\u5F53\u524D\u5DE5\u7A0B\u3001Skill \u8DEF\u5F84\u53CA\u5177\u4F53\u63A5\u7EED\u65B9\u5F0F\uFF0C\u4E0D\u5305\u542B\u6574\u4EFD\u5F00\u53D1\u6307\u5357\u3002
2649
+
2703
2650
  ## \u8D44\u6599\u786E\u8BA4\u4E0E\u521D\u59CB\u5316
2704
2651
 
2705
2652
  init \u5148\u6536\u96C6\u540D\u79F0\u3001\u4E00\u53E5\u8BDD\u4ECB\u7ECD\u548C\u5B8C\u6574\u4ECB\u7ECD\uFF0C\u51C6\u5907\u5934\u50CF\uFF1B\u5F00\u53D1\u8005\u786E\u8BA4\u8D44\u6599\u548C\u5934\u50CF\u540E\uFF0C\u518D\u767B\u8BB0\u4E91\u7AEF Meta\u3002\u672A\u786E\u8BA4\u65F6\u4EC5\u4FDD\u5B58 .buddy/meta/ \u672C\u5730\u8349\u7A3F\u3002
@@ -2714,7 +2661,7 @@ Coding Agent \u5E94\u76F4\u63A5\u6CBF\u7528\u7528\u6237\u660E\u786E\u63D0\u4F9B\
2714
2661
  \u975E\u4EA4\u4E92\u8C03\u7528\u987B\u5728\u5F00\u53D1\u8005\u660E\u786E\u786E\u8BA4\u5B9E\u9645\u5934\u50CF\u548C\u8D44\u6599\u540E\u4F20 --avatar <\u5DF2\u786E\u8BA4\u56FE\u7247> --confirm-meta\u3002\u672A\u786E\u8BA4\u4E0D\u5F97\u4F20\u8BE5\u6807\u5FD7\uFF1B\u7F3A\u5C11\u56FE\u7247\u6216\u786E\u8BA4\u65F6\u9000\u51FA\u7801\u4E3A 2\uFF0C\u8349\u7A3F\u4FDD\u7559\uFF0C\u53EF\u4EE5\u5728\u539F\u76EE\u5F55\u7EE7\u7EED\u3002
2715
2662
  --mode create \u5B8C\u6210\u8D44\u6599\u548C\u5934\u50CF\u767B\u8BB0\u540E\uFF0C\u52A8\u6001\u83B7\u53D6\u72EC\u7ACB Creator Skill \u5E76\u751F\u6210\u63A5\u7EED\u8BF4\u660E\uFF0C\u9879\u76EE .buddy/creator/ \u4FDD\u5B58\u521B\u4F5C\u8D44\u6599\u4E0E skill-lock.json \u7248\u672C\u8BB0\u5F55\u3002\u4F7F\u7528 --creator-version <\u51C6\u786E\u7248\u672C> \u663E\u5F0F\u5347\u7EA7\uFF0C\u5DF2\u6709\u9879\u76EE\u9ED8\u8BA4\u590D\u7528\u56FA\u5B9A\u7248\u672C\uFF1B\u672C\u5730\u8054\u8C03\u53EF\u8BBE\u7F6E BUDDY_CREATOR_SKILL_PATH \u7EDD\u5BF9\u8DEF\u5F84\u3002
2716
2663
  \u7531\u5F53\u524D Coding Agent \u8BFB\u53D6 .buddy/creator/HANDOFF.md \u5E76\u6267\u884C\u5176\u4E2D\u6307\u5411\u7684 Skill\uFF1B\u9700\u8981 Python 3.9+\uFF0C\u4E0D\u542F\u52A8\u65E7\u91C7\u8BBF Web \u6216\u72EC\u7ACB\u6A21\u578B\u3002
2717
- \u56DB\u518C\u786E\u8BA4\u540E\u7EE7\u7EED\u5C0F\u6302\u4EF6\u6E05\u5355\u3001\u539F\u578B\u548C\u8BBE\u8BA1\u9A8C\u6536\uFF1B\u5168\u90E8\u786E\u8BA4\u5E76\u901A\u8FC7\u4EA4\u4ED8\u6821\u9A8C\u540E\uFF0C\u7531 Coding Agent \u81EA\u52A8\u8854\u63A5\u5F00\u53D1\uFF0C\u9700\u8981\u521D\u59CB\u5316\u65F6\u6267\u884C init --mode direct \u751F\u6210\u5B98\u65B9 Runtime \u5DE5\u7A0B\u3002\u540C\u76EE\u5F55\u6062\u590D\u65F6\u4ECE buddy.agent.json \u8BFB\u53D6 buddyId\uFF0C\u5E76\u4F7F\u7528\u5E73\u53F0\u6700\u65B0 Meta\u3002
2664
+ \u56DB\u518C\u786E\u8BA4\u540E\u7EE7\u7EED\u5C0F\u6302\u4EF6\u6E05\u5355\u3001\u539F\u578B\u548C\u8BBE\u8BA1\u9A8C\u6536\uFF1B\u5168\u90E8\u786E\u8BA4\u5E76\u901A\u8FC7\u4EA4\u4ED8\u6821\u9A8C\u540E\uFF0C\u7531 Coding Agent \u81EA\u52A8\u8854\u63A5\u5F00\u53D1\uFF0C\u9700\u8981\u521D\u59CB\u5316\u65F6\u6267\u884C init --mode direct \u751F\u6210\u5B98\u65B9 Runtime \u5DE5\u7A0B\u3002\u540C\u76EE\u5F55\u6062\u590D\u65F6\u4ECE package.json \u8BFB\u53D6 buddyId\uFF0C\u5E76\u4F7F\u7528\u5E73\u53F0\u6700\u65B0 Meta\u3002
2718
2665
  Coding Agent \u5E94\u4F20\u5165\u6309\u4E0A\u8FF0\u89C4\u5219\u786E\u5B9A\u7684\u8D44\u6599\uFF0C\u811A\u672C\u4F7F\u7528\u5F00\u53D1\u8005\u63D0\u4F9B\u7684\u53C2\u6570\uFF0C\u907F\u514D\u7B49\u5F85\u7EC8\u7AEF\u8F93\u5165\u3002CLI \u6821\u9A8C\u53C2\u6570\uFF0C\u4E0D\u5224\u65AD\u5BF9\u8BDD\u4E2D\u662F\u5426\u5DF2\u7ECF\u786E\u8BA4\uFF1B\u53C2\u6570\u9F50\u5168\u4E0D\u7B49\u4E8E\u7528\u6237\u786E\u8BA4\u3002
2719
2666
  Coding Agent \u6839\u636E\u5DF2\u786E\u8BA4\u624B\u518C\u6216\u9700\u6C42\u63A8\u8FDB\u5B9E\u73B0\uFF1B\u53EA\u4E3A\u5173\u952E\u7F3A\u53E3\u8BE2\u95EE\uFF0C\u4E0D\u56FA\u5B9A\u8FFD\u52A0\u7B56\u7565\u786E\u8BA4\u3002
2720
2667
  \u6240\u6709\u642D\u5B50\u7EDF\u4E00\u4F7F\u7528\u5B98\u65B9 Runtime\uFF1B\u9700\u6C42\u660E\u786E\u65F6\u4F7F\u7528 --mode direct\uFF0C\u9700\u8981\u68B3\u7406\u9700\u6C42\u65F6\u4F7F\u7528 --mode create\u3002
@@ -2748,8 +2695,8 @@ function resolvePlatformUrl(options = {}) {
2748
2695
 
2749
2696
  // packages/cli-core/src/dev/project-env.ts
2750
2697
  import { constants } from "node:fs";
2751
- import { open as open4, rename as rename8, unlink as unlink7 } from "node:fs/promises";
2752
- import { randomUUID as randomUUID6 } from "node:crypto";
2698
+ import { open as open4, rename as rename9, unlink as unlink7 } from "node:fs/promises";
2699
+ import { randomUUID as randomUUID7 } from "node:crypto";
2753
2700
  import { join as join13 } from "node:path";
2754
2701
  import { parseEnv } from "node:util";
2755
2702
 
@@ -2808,7 +2755,7 @@ async function readProjectEnvironment(projectRoot, buddyId) {
2808
2755
  } catch {
2809
2756
  throw invalid("\u5DE5\u7A0B .env \u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002");
2810
2757
  }
2811
- 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");
2758
+ if (values.BUDDY_ID && values.BUDDY_ID !== buddyId) throw invalid(".env \u7684 BUDDY_ID \u4E0E package.json \u4E0D\u4E00\u81F4\uFF0C\u8BF7\u5148\u4FEE\u6B63\u5DE5\u7A0B\u8EAB\u4EFD\u3002");
2812
2759
  return values;
2813
2760
  }
2814
2761
  async function projectBuddyToken(projectRoot, buddyId, gatewayUrl) {
@@ -2871,7 +2818,7 @@ function updateValues(source, values) {
2871
2818
  return output;
2872
2819
  }
2873
2820
  async function replaceFile2(path, contents, mode) {
2874
- const temporary = `${path}.${randomUUID6()}.tmp`;
2821
+ const temporary = `${path}.${randomUUID7()}.tmp`;
2875
2822
  let file;
2876
2823
  try {
2877
2824
  file = await open4(temporary, "wx", mode);
@@ -2879,7 +2826,7 @@ async function replaceFile2(path, contents, mode) {
2879
2826
  await file.sync();
2880
2827
  await file.close();
2881
2828
  file = void 0;
2882
- await rename8(temporary, path);
2829
+ await rename9(temporary, path);
2883
2830
  } finally {
2884
2831
  await file?.close();
2885
2832
  await unlink7(temporary).catch((cause) => {
@@ -3035,7 +2982,7 @@ var MlbDevRegistrationClient = class {
3035
2982
  throw new BuddyDevError({
3036
2983
  code: "DEV_AGENT_ID_INVALID",
3037
2984
  phase: "registration",
3038
- message: "buddy.agent.json \u4E2D\u7684 buddyId \u65E0\u6548\u3002"
2985
+ message: "package.json \u4E2D\u7684 buddyId \u65E0\u6548\u3002"
3039
2986
  });
3040
2987
  }
3041
2988
  options.signal.throwIfAborted();
@@ -3167,13 +3114,13 @@ function buildAgentEnvironment(options) {
3167
3114
 
3168
3115
  // packages/cli-core/src/dev/orchestrator.ts
3169
3116
  import { createHash as createHash6 } from "node:crypto";
3170
- import { readFile as readFile14 } from "node:fs/promises";
3171
- import { join as join16, resolve as resolve12 } from "node:path";
3117
+ import { readFile as readFile16 } from "node:fs/promises";
3118
+ import { join as join17, resolve as resolve12 } from "node:path";
3172
3119
 
3173
3120
  // packages/cli-core/src/dev/reload.ts
3174
3121
  import { watch } from "node:fs";
3175
3122
  import { createHash as createHash5 } from "node:crypto";
3176
- import { readFile as readFile12, readdir as readdir4 } from "node:fs/promises";
3123
+ import { readFile as readFile13, readdir as readdir4 } from "node:fs/promises";
3177
3124
  import { join as join15, resolve as resolve9 } from "node:path";
3178
3125
  import { setTimeout as sleep } from "node:timers/promises";
3179
3126
 
@@ -3202,7 +3149,7 @@ async function snapshot(root, prefix = "", result = /* @__PURE__ */ new Map()) {
3202
3149
  if (!relevant(path)) continue;
3203
3150
  try {
3204
3151
  if (entry2.isDirectory()) await snapshot(root, path, result);
3205
- else if (entry2.isFile()) result.set(path, digest2(await readFile12(join15(root, path))));
3152
+ else if (entry2.isFile()) result.set(path, digest2(await readFile13(join15(root, path))));
3206
3153
  } catch (cause) {
3207
3154
  if (cause.code !== "ENOENT") throw cause;
3208
3155
  }
@@ -3292,7 +3239,7 @@ var ReloadingDevSession = class {
3292
3239
  const path = String(name);
3293
3240
  if (!relevant(path)) return;
3294
3241
  if (path === ".env") {
3295
- void readFile12(join15(this.projectRoot, path), "utf8").then((contents) => {
3242
+ void readFile13(join15(this.projectRoot, path), "utf8").then((contents) => {
3296
3243
  if (contents !== this.#environment) {
3297
3244
  this.#environment = contents;
3298
3245
  this.#changed();
@@ -3470,7 +3417,7 @@ function startReloadingDev(options, startProcess) {
3470
3417
  }
3471
3418
 
3472
3419
  // packages/cli-core/src/config/runtime-policy.ts
3473
- import { readFile as readFile13, realpath as realpath4 } from "node:fs/promises";
3420
+ import { readFile as readFile14, realpath as realpath4 } from "node:fs/promises";
3474
3421
  import { createRequire as createRequire2 } from "node:module";
3475
3422
  import { resolve as resolve10 } from "node:path";
3476
3423
  var RuntimeRequirementError = class extends Error {
@@ -3510,11 +3457,11 @@ async function requireLatestRuntime(root, options = {}) {
3510
3457
  const installedPath = await realpath4(resolve10(root, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"));
3511
3458
  const fromProject = createRequire2(resolve10(root, "package.json")).resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`);
3512
3459
  if (await realpath4(fromProject) !== installedPath) throw new Error("Runtime \u5FC5\u987B\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D");
3513
- const installed2 = JSON.parse(await readFile13(installedPath, "utf8"));
3460
+ const installed2 = JSON.parse(await readFile14(installedPath, "utf8"));
3514
3461
  if (installed2.version !== latest) throw new Error(`Runtime \u5B9E\u9645\u5B89\u88C5 ${installed2.version}\uFF0C\u8981\u6C42 ${latest}`);
3515
3462
  let lock;
3516
3463
  try {
3517
- lock = await readFile13(resolve10(root, "package-lock.json"), "utf8");
3464
+ lock = await readFile14(resolve10(root, "package-lock.json"), "utf8");
3518
3465
  } catch (cause) {
3519
3466
  if (cause.code !== "ENOENT") throw cause;
3520
3467
  }
@@ -3532,6 +3479,48 @@ async function requireLatestRuntime(root, options = {}) {
3532
3479
  import { lstatSync, readFileSync } from "node:fs";
3533
3480
  import { createRequire as createRequire3 } from "node:module";
3534
3481
  import { dirname as dirname4, resolve as resolve11 } from "node:path";
3482
+
3483
+ // packages/cli-core/src/config/data-access.ts
3484
+ import { lstat as lstat10, readFile as readFile15 } from "node:fs/promises";
3485
+ import { join as join16 } from "node:path";
3486
+ var DATA_ACCESS_FILENAME = "data-access.json";
3487
+ function parseDataAccessRequirements(source) {
3488
+ if (source === void 0) return [];
3489
+ const invalid3 = (reason) => {
3490
+ throw new Error(`${DATA_ACCESS_FILENAME}\uFF1A${reason}`);
3491
+ };
3492
+ let value;
3493
+ try {
3494
+ value = JSON.parse(source);
3495
+ } catch {
3496
+ return invalid3("\u4E0D\u662F\u6709\u6548 JSON");
3497
+ }
3498
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).some((key) => key !== "requirements") || !Array.isArray(value.requirements) || value.requirements.length > 32) {
3499
+ return invalid3("\u5FC5\u987B\u662F\u4EC5\u5305\u542B requirements \u6570\u7EC4\u7684\u5BF9\u8C61\uFF0C\u6700\u591A\u58F0\u660E 32 \u9879");
3500
+ }
3501
+ const seen = /* @__PURE__ */ new Set();
3502
+ return value.requirements.map((item, index) => {
3503
+ 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) {
3504
+ return invalid3(`requirements[${index}] \u5FC5\u987B\u5305\u542B\u975E\u7A7A id \u548C 1\u2013200 \u5B57\u7684 purpose`);
3505
+ }
3506
+ const id = item.id.trim(), purpose = item.purpose.trim();
3507
+ if (seen.has(id)) return invalid3(`\u6570\u636E\u96C6\u4E0D\u80FD\u91CD\u590D\u58F0\u660E\uFF1A${id}`);
3508
+ seen.add(id);
3509
+ return { id, purpose };
3510
+ });
3511
+ }
3512
+ async function readDataAccessRequirements(projectRoot) {
3513
+ const path = join16(projectRoot, DATA_ACCESS_FILENAME);
3514
+ try {
3515
+ if (!(await lstat10(path)).isFile()) throw new Error(`${DATA_ACCESS_FILENAME} \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6`);
3516
+ return parseDataAccessRequirements(await readFile15(path, "utf8"));
3517
+ } catch (cause) {
3518
+ if (cause.code === "ENOENT") return [];
3519
+ throw cause;
3520
+ }
3521
+ }
3522
+
3523
+ // packages/cli-core/src/dev/launch.ts
3535
3524
  async function officialAgentLaunchPlan(input) {
3536
3525
  const entry2 = resolve11(input.projectRoot, BUDDY_PLATFORM_START_ENTRY);
3537
3526
  for (const [filename, kind] of [
@@ -3562,8 +3551,7 @@ async function officialAgentLaunchPlan(input) {
3562
3551
  const runtimePath = createRequire3(packagePath).resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`);
3563
3552
  const installed2 = JSON.parse(readFileSync(runtimePath, "utf8")).version;
3564
3553
  if (installed2 !== expected) throw new Error(`Runtime \u5DF2\u5B89\u88C5 ${installed2}\uFF0C\u5DE5\u7A0B\u8981\u6C42 ${expected}`);
3565
- await validateRuntimeDatasets(input.projectRoot, input.datasets);
3566
- await validateRuntimeModel(input.projectRoot, input.model);
3554
+ await validateRuntimeDatasets(input.projectRoot, await readDataAccessRequirements(input.projectRoot));
3567
3555
  } catch (cause) {
3568
3556
  throw new BuddyDevError({
3569
3557
  code: cause instanceof RuntimeRequirementError ? `DEV_${cause.code}` : "DEV_CONFIG_INVALID",
@@ -3572,7 +3560,6 @@ async function officialAgentLaunchPlan(input) {
3572
3560
  cause
3573
3561
  });
3574
3562
  }
3575
- await migrateRuntimeStartup(input.projectRoot);
3576
3563
  return Object.freeze({
3577
3564
  command: process.execPath,
3578
3565
  args: Object.freeze(["--env-file-if-exists=.env", entry2])
@@ -3818,8 +3805,6 @@ function validateLaunchPlan(value) {
3818
3805
  async function launchPlanFor(config, options, projectRoot, signal) {
3819
3806
  const provider = options.platformLaunchPlan ?? ((context) => officialAgentLaunchPlan({
3820
3807
  runtimeUpdate: { ...options.runtimeUpdate, signal },
3821
- datasets: config.datasets,
3822
- model: config.model,
3823
3808
  projectRoot: context.projectRoot
3824
3809
  }));
3825
3810
  try {
@@ -4047,13 +4032,13 @@ async function startBuddyDevProcess(options, hooks) {
4047
4032
  let config;
4048
4033
  let configSource;
4049
4034
  try {
4050
- configSource = await readFile14(join16(projectRoot, BUDDY_AGENT_FILENAME), "utf8");
4035
+ configSource = await readFile16(join17(projectRoot, BUDDY_PACKAGE_FILENAME), "utf8");
4051
4036
  config = combineBuddyProject(parseBuddyAgentConfig(configSource));
4052
4037
  } catch (cause) {
4053
4038
  throw new BuddyDevError({
4054
4039
  code: "DEV_CONFIG_INVALID",
4055
4040
  phase: "config",
4056
- message: `\u65E0\u6CD5\u8BFB\u53D6\u6216\u6821\u9A8C buddy.agent.json\uFF1A${cause instanceof Error ? cause.message : "\u642D\u5B50\u5DE5\u7A0B\u5C1A\u672A\u5B8C\u6210"}`,
4041
+ message: `\u65E0\u6CD5\u8BFB\u53D6\u6216\u6821\u9A8C package.json\uFF1A${cause instanceof Error ? cause.message : "\u642D\u5B50\u5DE5\u7A0B\u5C1A\u672A\u5B8C\u6210"}`,
4057
4042
  cause
4058
4043
  });
4059
4044
  }
@@ -4531,7 +4516,7 @@ var PushPreflightError = class extends Error {
4531
4516
  import { resolve as resolve15 } from "node:path";
4532
4517
 
4533
4518
  // packages/cli-core/src/cloud/auth.ts
4534
- import { randomUUID as randomUUID7 } from "node:crypto";
4519
+ import { randomUUID as randomUUID8 } from "node:crypto";
4535
4520
 
4536
4521
  // packages/cli-core/src/cloud/validation.ts
4537
4522
  function record(value, path = "request") {
@@ -4599,7 +4584,7 @@ var CloudAuthenticator = class {
4599
4584
  this.#adapter = adapter;
4600
4585
  this.#store = store;
4601
4586
  this.#now = options.now ?? Date.now;
4602
- this.#createState = options.createState ?? randomUUID7;
4587
+ this.#createState = options.createState ?? randomUUID8;
4603
4588
  this.#minimumValidityMs = options.minimumValidityMs ?? 3e4;
4604
4589
  if (!Number.isSafeInteger(this.#minimumValidityMs) || this.#minimumValidityMs < 0) {
4605
4590
  throw new TypeError("minimumValidityMs must be a non-negative safe integer");
@@ -5545,8 +5530,8 @@ async function runCloudCommand(command, args, io, options = {}) {
5545
5530
  var CLOUD_COMMAND_HELP = HELP;
5546
5531
 
5547
5532
  // packages/cli-core/src/migration/index.ts
5548
- import { lstat as lstat10, open as open5, readdir as readdir5, realpath as realpath5, stat } from "node:fs/promises";
5549
- import { extname, isAbsolute as isAbsolute3, join as join17, relative, resolve as resolve16, sep, win32 as win322 } from "node:path";
5533
+ import { lstat as lstat11, open as open5, readdir as readdir5, realpath as realpath5, stat } from "node:fs/promises";
5534
+ import { extname, isAbsolute as isAbsolute3, join as join18, relative, resolve as resolve16, sep, win32 as win322 } from "node:path";
5550
5535
  var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
5551
5536
  maxFiles: 128,
5552
5537
  maxFileBytes: 256 * 1024,
@@ -5715,9 +5700,9 @@ async function existingProjectRoot(value) {
5715
5700
  }
5716
5701
  }
5717
5702
  async function existingSkillRoot(projectRoot, skillPath) {
5718
- const candidate = skillPath === "." ? projectRoot : join17(projectRoot, ...skillPath.split("/"));
5703
+ const candidate = skillPath === "." ? projectRoot : join18(projectRoot, ...skillPath.split("/"));
5719
5704
  try {
5720
- await lstat10(candidate);
5705
+ await lstat11(candidate);
5721
5706
  } catch (cause) {
5722
5707
  if (filesystemCode(cause) === "ENOENT") {
5723
5708
  return rejectScan("SKILL_ROOT_NOT_FOUND", skillPath, "\u627E\u4E0D\u5230\u6307\u5B9A\u7684 Skill \u76EE\u5F55\u3002");
@@ -5752,9 +5737,9 @@ async function existingSkillRoot(projectRoot, skillPath) {
5752
5737
  }
5753
5738
  async function assertEntrypoint(context) {
5754
5739
  const entryPath = reportChild(context.skillPath, "SKILL.md");
5755
- const candidate = join17(context.skillRoot, "SKILL.md");
5740
+ const candidate = join18(context.skillRoot, "SKILL.md");
5756
5741
  try {
5757
- await lstat10(candidate);
5742
+ await lstat11(candidate);
5758
5743
  const target = await realpath5(candidate);
5759
5744
  if (!isWithin(context.projectRoot, target) || !isWithin(context.skillRoot, target)) {
5760
5745
  rejectScan(
@@ -5856,7 +5841,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
5856
5841
  }
5857
5842
  for (const entry2 of entries) {
5858
5843
  const childReportPath = reportChild(reportDirectory, entry2.name);
5859
- const childPath = join17(directory, entry2.name);
5844
+ const childPath = join18(directory, entry2.name);
5860
5845
  let target;
5861
5846
  try {
5862
5847
  target = await realpath5(childPath);
@@ -6311,8 +6296,8 @@ async function scanExternalSkillPortability(options) {
6311
6296
 
6312
6297
  // packages/cli-core/src/push/preflight.ts
6313
6298
  import { createHash as createHash10 } from "node:crypto";
6314
- import { lstat as lstat11, open as open6, readdir as readdir6, realpath as realpath6 } from "node:fs/promises";
6315
- import { isAbsolute as isAbsolute4, join as join18, relative as relative2, resolve as resolve17, sep as sep2, win32 as win323 } from "node:path";
6299
+ import { lstat as lstat12, open as open6, readdir as readdir6, realpath as realpath6 } from "node:fs/promises";
6300
+ import { isAbsolute as isAbsolute4, join as join19, relative as relative2, resolve as resolve17, sep as sep2, win32 as win323 } from "node:path";
6316
6301
  var MEBIBYTE = 1024 * 1024;
6317
6302
  var DEFAULT_PUSH_MANIFEST_LIMITS = Object.freeze({
6318
6303
  maxFiles: 1e4,
@@ -6489,7 +6474,7 @@ async function canonicalProjectRoot(projectRoot) {
6489
6474
  const absolute = resolve17(projectRoot);
6490
6475
  let entry2;
6491
6476
  try {
6492
- entry2 = await lstat11(absolute);
6477
+ entry2 = await lstat12(absolute);
6493
6478
  } catch (cause) {
6494
6479
  error({
6495
6480
  code: "PUSH_PROJECT_INVALID",
@@ -6517,10 +6502,10 @@ async function canonicalProjectRoot(projectRoot) {
6517
6502
  }
6518
6503
  }
6519
6504
  async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
6520
- const path = join18(projectRoot, filename);
6505
+ const path = join19(projectRoot, filename);
6521
6506
  let entry2;
6522
6507
  try {
6523
- entry2 = await lstat11(path);
6508
+ entry2 = await lstat12(path);
6524
6509
  } catch (cause) {
6525
6510
  error({
6526
6511
  code: "PUSH_CONFIG_INVALID",
@@ -6579,7 +6564,7 @@ function parseCapturedProject(agentFile) {
6579
6564
  } catch (cause) {
6580
6565
  error({
6581
6566
  code: "PUSH_CONFIG_INVALID",
6582
- message: `${BUDDY_AGENT_FILENAME} \u65E0\u6548\u3001Agent \u5DE5\u7A0B\u5C1A\u672A\u5B8C\u6210\u3002`,
6567
+ message: `${BUDDY_PACKAGE_FILENAME} \u65E0\u6548\u3001Agent \u5DE5\u7A0B\u5C1A\u672A\u5B8C\u6210\u3002`,
6583
6568
  cause
6584
6569
  });
6585
6570
  }
@@ -6615,11 +6600,11 @@ async function selectLockfile(projectRoot) {
6615
6600
  }
6616
6601
  function assertBookletIsNotRequiredInput(bookletPath, lockfile) {
6617
6602
  if (bookletPath === void 0) return;
6618
- if (bookletPath === BUDDY_AGENT_FILENAME || bookletPath === lockfile.path || OFFICIAL_RUNTIME_INPUTS.some((path) => path === bookletPath)) {
6603
+ if (bookletPath === BUDDY_PACKAGE_FILENAME || bookletPath === DATA_ACCESS_FILENAME || bookletPath === lockfile.path || OFFICIAL_RUNTIME_INPUTS.some((path) => path === bookletPath)) {
6619
6604
  error({
6620
6605
  code: "PUSH_BOOKLET_INVALID",
6621
6606
  path: bookletPath,
6622
- message: `Booklet \u4E0D\u80FD\u4F2A\u88C5\u6210 ${BUDDY_AGENT_FILENAME}\u3001\u4F9D\u8D56\u9501\u6587\u4EF6\u3001Runtime \u542F\u52A8\u8F93\u5165\u3002`
6607
+ message: `Booklet \u4E0D\u80FD\u4F2A\u88C5\u6210 ${BUDDY_PACKAGE_FILENAME}\u3001\u4F9D\u8D56\u9501\u6587\u4EF6\u3001Runtime \u542F\u52A8\u8F93\u5165\u3002`
6623
6608
  });
6624
6609
  }
6625
6610
  }
@@ -6720,10 +6705,10 @@ async function createManifest(options) {
6720
6705
  sensitiveEntriesExcluded += 1;
6721
6706
  continue;
6722
6707
  }
6723
- const absolutePath = join18(directory, name);
6708
+ const absolutePath = join19(directory, name);
6724
6709
  let entry2;
6725
6710
  try {
6726
- entry2 = await lstat11(absolutePath);
6711
+ entry2 = await lstat12(absolutePath);
6727
6712
  } catch (cause) {
6728
6713
  error({
6729
6714
  code: "PUSH_FILE_CHANGED",
@@ -6974,8 +6959,8 @@ async function assertCapturedConfigStable(options) {
6974
6959
  }
6975
6960
  let current;
6976
6961
  try {
6977
- const path = join18(options.projectRoot, options.filename);
6978
- const entry2 = await lstat11(path);
6962
+ const path = join19(options.projectRoot, options.filename);
6963
+ const entry2 = await lstat12(path);
6979
6964
  if (!entry2.isFile() || entry2.isSymbolicLink()) {
6980
6965
  error({
6981
6966
  code: "PUSH_FILE_CHANGED",
@@ -7015,15 +7000,22 @@ async function createPushPreflight(options) {
7015
7000
  const initialAgentEntry = await captureConfigWithinLimit(
7016
7001
  projectRoot,
7017
7002
  limits.maxFileBytes,
7018
- BUDDY_AGENT_FILENAME
7003
+ BUDDY_PACKAGE_FILENAME
7019
7004
  );
7020
7005
  parseCapturedProject(initialAgentEntry);
7006
+ let initialDataEntry;
7007
+ try {
7008
+ await lstat12(join19(projectRoot, DATA_ACCESS_FILENAME));
7009
+ initialDataEntry = await captureConfigWithinLimit(projectRoot, limits.maxFileBytes, DATA_ACCESS_FILENAME);
7010
+ } catch (cause) {
7011
+ if (cause.code !== "ENOENT") throw cause;
7012
+ }
7021
7013
  const lockfile = await selectLockfile(projectRoot);
7022
7014
  assertBookletIsNotRequiredInput(bookletPath, lockfile);
7023
7015
  const manifest = await createManifest({
7024
7016
  projectRoot,
7025
7017
  limits,
7026
- capturePaths: /* @__PURE__ */ new Set([BUDDY_AGENT_FILENAME, lockfile.path, BUDDY_PLATFORM_PACKAGE_JSON, BUDDY_PLATFORM_AGENT_ENTRY, BUDDY_PLATFORM_FACTORY_ENTRY]),
7018
+ capturePaths: /* @__PURE__ */ new Set([DATA_ACCESS_FILENAME, BUDDY_PACKAGE_FILENAME, lockfile.path, BUDDY_PLATFORM_AGENT_ENTRY, BUDDY_PLATFORM_FACTORY_ENTRY]),
7027
7019
  ...bookletPath === void 0 ? {} : { bookletPath }
7028
7020
  });
7029
7021
  const lockEntry = manifest.files.find((file) => file.path === lockfile.path);
@@ -7048,24 +7040,32 @@ async function createPushPreflight(options) {
7048
7040
  }
7049
7041
  const agentEntry = await assertCapturedConfigStable({
7050
7042
  projectRoot,
7051
- filename: BUDDY_AGENT_FILENAME,
7043
+ filename: BUDDY_PACKAGE_FILENAME,
7052
7044
  initial: initialAgentEntry,
7053
7045
  manifestFiles: manifest.files,
7054
7046
  maxFileBytes: limits.maxFileBytes
7055
7047
  });
7056
- const config = parseCapturedProject(agentEntry);
7057
- if (config.datasets?.length || config.model !== void 0) {
7058
- try {
7059
- if (config.datasets?.length) await validateRuntimeDatasets(projectRoot, config.datasets);
7060
- await validateRuntimeModel(projectRoot, config.model);
7061
- } catch (cause) {
7062
- error({
7063
- code: "PUSH_CONFIG_INVALID",
7064
- path: BUDDY_AGENT_FILENAME,
7065
- message: `\u65E0\u6CD5\u6309\u5DE5\u7A0B Runtime \u6821\u9A8C\u6A21\u578B\u6216\u6570\u636E\u58F0\u660E\uFF1A${cause instanceof Error ? cause.message : String(cause)}`,
7066
- cause
7067
- });
7068
- }
7048
+ parseCapturedProject(agentEntry);
7049
+ if (initialDataEntry) {
7050
+ await assertCapturedConfigStable({
7051
+ projectRoot,
7052
+ filename: DATA_ACCESS_FILENAME,
7053
+ initial: initialDataEntry,
7054
+ manifestFiles: manifest.files,
7055
+ maxFileBytes: limits.maxFileBytes
7056
+ });
7057
+ }
7058
+ try {
7059
+ const dataEntry = manifest.files.find((file) => file.path === DATA_ACCESS_FILENAME);
7060
+ const requirements = parseDataAccessRequirements(dataEntry ? decodeCapturedConfig(dataEntry) : void 0);
7061
+ if (requirements.length) await validateRuntimeDatasets(projectRoot, requirements);
7062
+ } catch (cause) {
7063
+ error({
7064
+ code: "PUSH_CONFIG_INVALID",
7065
+ path: DATA_ACCESS_FILENAME,
7066
+ message: `\u65E0\u6CD5\u6309\u5DE5\u7A0B Runtime \u6821\u9A8C\u6570\u636E\u58F0\u660E\uFF1A${cause instanceof Error ? cause.message : String(cause)}`,
7067
+ cause
7068
+ });
7069
7069
  }
7070
7070
  const files = Object.freeze(manifest.files.map((file) => Object.freeze({
7071
7071
  path: file.path,
@@ -7107,8 +7107,8 @@ async function createPushPreflight(options) {
7107
7107
 
7108
7108
  // packages/cli-core/src/push/bundle.ts
7109
7109
  import { createHash as createHash11 } from "node:crypto";
7110
- import { lstat as lstat12, readFile as readFile15, realpath as realpath7 } from "node:fs/promises";
7111
- import { join as join19, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
7110
+ import { lstat as lstat13, readFile as readFile17, realpath as realpath7 } from "node:fs/promises";
7111
+ import { join as join20, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
7112
7112
  import { Writable } from "node:stream";
7113
7113
  import { pipeline } from "node:stream/promises";
7114
7114
  import { createGzip } from "node:zlib";
@@ -7130,15 +7130,15 @@ function inside(root, target) {
7130
7130
  return path === "" || path !== ".." && !path.startsWith(`..${sep3}`) && !path.startsWith("/") && !win324.isAbsolute(path);
7131
7131
  }
7132
7132
  async function capture(root, file) {
7133
- const absolute = join19(root, ...file.path.split("/"));
7133
+ const absolute = join20(root, ...file.path.split("/"));
7134
7134
  try {
7135
- const entry2 = await lstat12(absolute);
7135
+ const entry2 = await lstat13(absolute);
7136
7136
  if (!entry2.isFile() || entry2.isSymbolicLink() || entry2.size !== file.bytes) {
7137
7137
  changed(file.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${file.path}`);
7138
7138
  }
7139
7139
  const canonical = await realpath7(absolute);
7140
7140
  if (!inside(root, canonical)) changed(file.path, `\u63D0\u4EA4\u6587\u4EF6\u8D8A\u8FC7\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${file.path}`);
7141
- const contents = await readFile15(absolute);
7141
+ const contents = await readFile17(absolute);
7142
7142
  if (contents.byteLength !== file.bytes || digest3(contents) !== file.digest) {
7143
7143
  changed(file.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u5185\u5BB9\u53D1\u751F\u53D8\u5316\uFF1A${file.path}`);
7144
7144
  }
@@ -7439,7 +7439,7 @@ async function initializeProjectRoute(route, args, io, options, application) {
7439
7439
  const existingBuddyId = initializationPlan?.existingManifest?.buddyId;
7440
7440
  if (existingBuddyId !== void 0 && args.buddyId !== void 0 && existingBuddyId !== args.buddyId) {
7441
7441
  throw new CliUsageError(
7442
- `\u5DF2\u6709 buddy.agent.json \u7ED1\u5B9A\u7684\u662F ${existingBuddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
7442
+ `\u5DF2\u6709 package.json \u7ED1\u5B9A\u7684\u662F ${existingBuddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
7443
7443
  );
7444
7444
  }
7445
7445
  const requestedBuddyId = existingBuddyId ?? args.buddyId;
@@ -7511,7 +7511,7 @@ async function runRoute(route, args, io, options) {
7511
7511
  const existingBuddyId = plan.existingManifest?.buddyId;
7512
7512
  if (existingBuddyId !== void 0 && args.buddyId !== void 0 && existingBuddyId !== args.buddyId) {
7513
7513
  throw new CliUsageError(
7514
- `\u5DF2\u6709 buddy.agent.json \u7ED1\u5B9A\u7684\u662F ${existingBuddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
7514
+ `\u5DF2\u6709 package.json \u7ED1\u5B9A\u7684\u662F ${existingBuddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
7515
7515
  );
7516
7516
  }
7517
7517
  const requestedBuddyId = existingBuddyId ?? args.buddyId;
@@ -7521,7 +7521,7 @@ async function runRoute(route, args, io, options) {
7521
7521
  let draft;
7522
7522
  try {
7523
7523
  plan = await planBuddyDraftInitialization(rootDirectory);
7524
- draft = await applyBuddyDraftInitialization(plan, { schemaVersion: 1, buddyId });
7524
+ draft = await applyBuddyDraftInitialization(plan, { buddyId });
7525
7525
  } catch (cause) {
7526
7526
  io.writeError(
7527
7527
  `\u4E91\u7AEF\u642D\u5B50\u8EAB\u4EFD ${buddyId} \u5DF2\u51C6\u5907\u597D\uFF0C\u4F46\u672C\u5730 ${plan.agentConfigPath} \u5199\u5165\u5931\u8D25\u3002\u8BF7\u4F7F\u7528 --buddy-id ${buddyId} \u91CD\u8BD5\u3002`
@@ -7545,7 +7545,7 @@ async function resumeProjectArguments(args, cwd, options, io) {
7545
7545
  await assertInitializableBuddyTarget(root);
7546
7546
  let entry2;
7547
7547
  try {
7548
- entry2 = await lstat13(join20(root, "buddy.agent.json"));
7548
+ entry2 = await lstat14(join21(root, "package.json"));
7549
7549
  } catch (cause) {
7550
7550
  if (cause.code === "ENOENT") {
7551
7551
  const draft = await readMetaDraft(root);
@@ -7562,13 +7562,13 @@ async function resumeProjectArguments(args, cwd, options, io) {
7562
7562
  throw cause;
7563
7563
  }
7564
7564
  if (!entry2.isFile() || entry2.isSymbolicLink()) {
7565
- throw new CliUsageError("buddy.agent.json \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u7B26\u53F7\u94FE\u63A5");
7565
+ throw new CliUsageError("package.json \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u7B26\u53F7\u94FE\u63A5");
7566
7566
  }
7567
7567
  const manifest = await readBuddyProjectManifest(root);
7568
7568
  await checkRuntimeUpdate(root, (message) => io.writeError(message), options.runtimeCatalog);
7569
7569
  if (args.buddyId !== void 0 && args.buddyId !== manifest.buddyId) {
7570
7570
  throw new CliUsageError(
7571
- `\u5DF2\u6709 buddy.agent.json \u7ED1\u5B9A\u7684\u662F ${manifest.buddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
7571
+ `\u5DF2\u6709 package.json \u7ED1\u5B9A\u7684\u662F ${manifest.buddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
7572
7572
  );
7573
7573
  }
7574
7574
  const { client } = platformDependencies(options);
@@ -7754,8 +7754,8 @@ async function* parseServerSentEvents(body, options = {}) {
7754
7754
  }
7755
7755
  export {
7756
7756
  AGENT_INHERITED_ENV_ALLOWLIST,
7757
- BUDDY_AGENT_FILENAME,
7758
- BUDDY_AGENT_SCHEMA,
7757
+ BUDDY_PACKAGE_FILENAME,
7758
+ BUDDY_PACKAGE_SCHEMA,
7759
7759
  BUDDY_PLATFORM_AGENT_ENTRY,
7760
7760
  BUDDY_PLATFORM_FACTORY_ENTRY,
7761
7761
  BUDDY_PLATFORM_PACKAGE_JSON,
@@ -7810,7 +7810,6 @@ export {
7810
7810
  isSafeProjectRelativePath,
7811
7811
  isWindowsReservedPathSegment,
7812
7812
  latestRuntimeTemplate,
7813
- migrateRuntimeStartup,
7814
7813
  normalizePlatformUrl,
7815
7814
  openExternalUrl,
7816
7815
  parseBuddyAgentConfig,