@my-life-buddies/cli 0.8.0 → 0.10.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
@@ -1,53 +1,106 @@
1
- // packages/cli-core/src/config/models.ts
2
- var MODEL_IDS = Object.freeze([
3
- "kimi-k2.6",
4
- "kimi-k3",
5
- "deepseek-v4-flash",
6
- "deepseek-v4-pro"
7
- ]);
8
- var DEFAULT_MODEL_ID = MODEL_IDS[0];
9
-
10
1
  // packages/cli-core/src/commands/models.ts
11
- var MODELS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli models [--json]
12
- \u67E5\u770B CLI \u5185\u7F6E\u7684\u6A21\u578B ID\uFF0C\u65E0\u9700\u767B\u5F55\u3001\u8054\u7F51\u6216 Agent \u5DE5\u7A0B\u3002
13
- \u5C06\u6240\u9009 ID \u5199\u5165 buddy.agent.json.model\uFF1B\u6A21\u677F\u5728 initialState.model \u4E2D\u4F7F\u7528\u5B83\u3002`;
14
- function runModelsCommand(args, io) {
15
- if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
16
- io.write(MODELS_COMMAND_HELP);
17
- } else if (args.length === 1 && args[0] === "--json") {
18
- io.write(JSON.stringify({ models: MODEL_IDS }, null, 2));
19
- } else if (args.length === 0) {
20
- io.write("CLI \u5185\u7F6E\u6A21\u578B\u76EE\u5F55\uFF08Runtime 0.12.0\uFF09\uFF1A");
21
- for (const id of MODEL_IDS) io.write(`- ${id}`);
22
- io.write("\u5C06\u6240\u9009 ID \u5199\u5165 buddy.agent.json.model\uFF1B\u672A\u8BBE\u7F6E\u65F6\u6A21\u677F\u4F7F\u7528 kimi-k2.6\u3002\u81EA\u5B9A\u4E49\u4F1A\u8BDD\u5DE5\u5382\u4E5F\u53EF\u6309\u4F1A\u8BDD\u8BBE\u7F6E initialState.model\u3002");
23
- } else {
24
- io.writeError(`models \u53C2\u6570\u65E0\u6548\u3002
25
- ${MODELS_COMMAND_HELP}`);
26
- return { exitCode: 2 };
27
- }
28
- return { exitCode: 0 };
2
+ import { resolve as resolve5 } from "node:path";
3
+
4
+ // packages/cli-core/src/config/runtime-catalog.ts
5
+ import { readFile, realpath } from "node:fs/promises";
6
+ import { createRequire } from "node:module";
7
+ import { resolve } from "node:path";
8
+ import { pathToFileURL } from "node:url";
9
+
10
+ // packages/cli-core/src/config/runtime-dependency.ts
11
+ var BUDDY_RUNTIME_PACKAGE = "@my-life-buddies/buddy-runtime";
12
+ function runtimeDependencyVersion(pkg) {
13
+ if (typeof pkg !== "object" || pkg === null || !("dependencies" in pkg)) return void 0;
14
+ const dependencies2 = pkg.dependencies;
15
+ if (typeof dependencies2 !== "object" || dependencies2 === null || !(BUDDY_RUNTIME_PACKAGE in dependencies2)) return void 0;
16
+ const version = dependencies2[BUDDY_RUNTIME_PACKAGE];
17
+ return typeof version === "string" && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(version) ? version : void 0;
29
18
  }
30
19
 
31
- // packages/cli-core/src/commands/widgets.ts
32
- import { resolve as resolve5 } from "node:path";
20
+ // packages/cli-core/src/config/runtime-catalog.ts
21
+ async function loadRuntime(projectRoot) {
22
+ const packagePath = resolve(projectRoot, "package.json");
23
+ const expected = runtimeDependencyVersion(JSON.parse(await readFile(packagePath, "utf8")));
24
+ if (!expected) throw new Error(`package.json \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C`);
25
+ const projectRequire = createRequire(packagePath);
26
+ let runtimePath;
27
+ try {
28
+ const installedPath = await realpath(resolve(projectRoot, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"));
29
+ if (await realpath(projectRequire.resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`)) !== installedPath) {
30
+ throw new Error("Runtime \u5FC5\u987B\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D");
31
+ }
32
+ const installed = JSON.parse(await readFile(installedPath, "utf8"));
33
+ if (installed.version !== expected) throw new Error(`\u5DF2\u5B89\u88C5 ${installed.version}\uFF0C\u5DE5\u7A0B\u8981\u6C42 ${expected}`);
34
+ runtimePath = projectRequire.resolve(BUDDY_RUNTIME_PACKAGE);
35
+ } catch (cause) {
36
+ throw new Error(`\u5DE5\u7A0B\u7684 Runtime \u4F9D\u8D56\u672A\u6B63\u786E\u5B89\u88C5\uFF0C\u8BF7\u6309\u9501\u6587\u4EF6\u5B89\u88C5\u4F9D\u8D56\uFF1A${cause instanceof Error ? cause.message : String(cause)}`);
37
+ }
38
+ const runtime = await import(pathToFileURL(runtimePath).href);
39
+ return { runtime, runtimeVersion: expected, runtimePath };
40
+ }
41
+ async function readRuntimeDataCatalog(projectRoot) {
42
+ const { runtime, runtimeVersion: expected } = await loadRuntime(projectRoot);
43
+ const catalog = runtime.DATA_ACCESS_CAPABILITIES;
44
+ if (!Array.isArray(catalog)) {
45
+ throw new Error(`\u5DE5\u7A0B\u7684 Runtime ${expected} \u672A\u5BFC\u51FA DATA_ACCESS_CAPABILITIES\uFF0C\u8BF7\u4F7F\u7528\u5305\u542B\u6570\u636E\u76EE\u5F55\u7684\u65B0 Runtime \u5305\u3002`);
46
+ }
47
+ const seen = /* @__PURE__ */ new Set();
48
+ const datasets = catalog.map((value) => {
49
+ if (!value || typeof value !== "object") throw new Error("Runtime \u6570\u636E\u76EE\u5F55\u683C\u5F0F\u65E0\u6548");
50
+ const item = value;
51
+ if (typeof item.id !== "string" || !item.id.trim() || seen.has(item.id) || typeof item.title !== "string" || !item.title.trim() || typeof item.source !== "string" || !item.source.trim() || !Number.isSafeInteger(item.schemaVersion) || item.schemaVersion < 1) {
52
+ throw new Error("Runtime \u6570\u636E\u76EE\u5F55\u683C\u5F0F\u65E0\u6548\u6216\u5305\u542B\u91CD\u590D ID");
53
+ }
54
+ seen.add(item.id);
55
+ return Object.freeze({ id: item.id, title: item.title, source: item.source, schemaVersion: item.schemaVersion });
56
+ });
57
+ return Object.freeze({ runtimeVersion: expected, datasets: Object.freeze(datasets) });
58
+ }
59
+ async function readRuntimeModelCatalog(projectRoot) {
60
+ const { runtime, runtimeVersion, runtimePath } = await loadRuntime(projectRoot);
61
+ let models = runtime.MODEL_IDS;
62
+ if (models === void 0) {
63
+ try {
64
+ models = (await import(new URL("./model.js", pathToFileURL(runtimePath)).href)).MODEL_IDS;
65
+ } catch (cause) {
66
+ throw new Error(`Runtime ${runtimeVersion} \u7684\u6A21\u578B\u76EE\u5F55\u4E0D\u53EF\u8BFB\u53D6\uFF1A${cause instanceof Error ? cause.message : String(cause)}`);
67
+ }
68
+ }
69
+ if (!Array.isArray(models) || models.length === 0 || models.some((id) => typeof id !== "string" || !id.trim()) || new Set(models).size !== models.length) {
70
+ throw new Error(`Runtime ${runtimeVersion} \u7684 MODEL_IDS \u7F3A\u5931\u6216\u683C\u5F0F\u65E0\u6548`);
71
+ }
72
+ return Object.freeze({ runtimeVersion, models: Object.freeze([...models]) });
73
+ }
74
+ async function validateRuntimeModel(projectRoot, model) {
75
+ if (model === void 0) return;
76
+ const catalog = await readRuntimeModelCatalog(projectRoot);
77
+ 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")}`);
78
+ }
79
+ async function validateRuntimeDatasets(projectRoot, requirements = []) {
80
+ const catalog = await readRuntimeDataCatalog(projectRoot);
81
+ const ids = new Set(catalog.datasets.map((item) => item.id));
82
+ for (const [index, item] of requirements.entries()) {
83
+ if (!ids.has(item.id)) throw new Error(`/datasets/${index}/id\uFF1A\u5DE5\u7A0B Runtime ${catalog.runtimeVersion} \u4E0D\u652F\u6301 ${item.id}`);
84
+ }
85
+ }
33
86
 
34
87
  // packages/cli-core/src/project-context.ts
35
- import { lstat as lstat4, realpath } from "node:fs/promises";
36
- import { dirname, join as join3, resolve as resolve3 } from "node:path";
88
+ import { lstat as lstat5, realpath as realpath2 } from "node:fs/promises";
89
+ import { dirname, join as join5, resolve as resolve4 } from "node:path";
37
90
 
38
91
  // packages/cli-core/src/config/index.ts
39
92
  import {
40
93
  link,
41
- lstat as lstat3,
42
- mkdir as mkdir2,
94
+ lstat as lstat4,
95
+ mkdir as mkdir3,
43
96
  open as open2,
44
- readFile as readFile2,
97
+ readFile as readFile5,
45
98
  readdir,
46
- rename,
99
+ rename as rename2,
47
100
  unlink as unlink2
48
101
  } from "node:fs/promises";
49
102
  import { randomUUID } from "node:crypto";
50
- import { isAbsolute, join as join2, resolve as resolve2, win32 } from "node:path";
103
+ import { isAbsolute, join as join4, resolve as resolve3, win32 } from "node:path";
51
104
  import { isDeepStrictEqual } from "node:util";
52
105
  import { Ajv2020 } from "ajv/dist/2020.js";
53
106
 
@@ -78,7 +131,7 @@ var buddy_agent_schema_default = {
78
131
  minLength: 1,
79
132
  maxLength: 128,
80
133
  pattern: "^[^\\s\\u0000-\\u001f\\u007f]+$",
81
- description: "\u4ECE buddy-cli models \u79BB\u7EBF\u67E5\u770B CLI \u5185\u7F6E\u6A21\u578B ID\uFF1B\u6A21\u677F\u5C06\u9009\u62E9\u4F20\u7ED9 initialState.model"
134
+ 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"
82
135
  },
83
136
  datasets: {
84
137
  type: "array",
@@ -110,12 +163,177 @@ var buddy_agent_schema_default = {
110
163
  };
111
164
 
112
165
  // packages/cli-core/src/project-files.ts
113
- import { lstat as lstat2 } from "node:fs/promises";
166
+ import { lstat as lstat3 } from "node:fs/promises";
167
+ import { join as join3 } from "node:path";
168
+
169
+ // packages/cli-core/src/init/scaffold.ts
170
+ import { lstat as lstat2, mkdir as mkdir2, open, readFile as readFile4, rmdir, unlink } from "node:fs/promises";
171
+ import { resolve as resolve2 } from "node:path";
172
+
173
+ // packages/cli-core/src/config/models.ts
174
+ var MODEL_IDS = Object.freeze([
175
+ "kimi-k2.6",
176
+ "kimi-k3",
177
+ "deepseek-v4-flash",
178
+ "deepseek-v4-pro"
179
+ ]);
180
+ var DEFAULT_MODEL_ID = "kimi-k2.6";
181
+
182
+ // packages/cli-core/src/init/runtime-template.ts
183
+ import { execFile as execFile2 } from "node:child_process";
184
+ import { mkdtemp as mkdtemp2, readFile as readFile3, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
185
+ import { tmpdir } from "node:os";
186
+ import { join as join2 } from "node:path";
187
+ import { promisify as promisify2 } from "node:util";
188
+
189
+ // packages/cli-core/src/config/runtime-package.ts
190
+ import { execFile } from "node:child_process";
191
+ import { lstat, mkdir, mkdtemp, readFile as readFile2, rename, rm, writeFile } from "node:fs/promises";
192
+ import { homedir } from "node:os";
114
193
  import { join } from "node:path";
194
+ import { promisify } from "node:util";
195
+ var RUNTIME_REGISTRY = "https://registry.npmjs.org/";
196
+ var execute = promisify(execFile);
197
+ async function latestRuntimeVersion(options = {}) {
198
+ options.signal?.throwIfAborted();
199
+ const timeout = AbortSignal.timeout(1e4);
200
+ const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
201
+ const response = await (options.fetch ?? globalThis.fetch)(`${RUNTIME_REGISTRY}${encodeURIComponent(BUDDY_RUNTIME_PACKAGE)}/latest`, {
202
+ signal,
203
+ headers: { Accept: "application/json" },
204
+ redirect: "error"
205
+ });
206
+ if (!response.ok) throw new Error(`npm \u8FD4\u56DE HTTP ${response.status}`);
207
+ const metadata = await response.json();
208
+ if (metadata?.name !== BUDDY_RUNTIME_PACKAGE || typeof metadata.version !== "string" || !/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u.test(metadata.version)) {
209
+ throw new Error("npm latest \u672A\u8FD4\u56DE\u6B64 Runtime \u7684\u51C6\u786E\u7A33\u5B9A\u7248\u672C");
210
+ }
211
+ return metadata.version;
212
+ }
213
+ async function cachedLatestRuntimeRoot(options = {}) {
214
+ options.report?.("\u6B63\u5728\u67E5\u8BE2\u516C\u5171 npm \u7684\u6700\u65B0 Runtime\u2026");
215
+ const version = await latestRuntimeVersion(options);
216
+ const cache = options.cacheDirectory ?? join(homedir(), ".cache", "buddy-cli", "runtimes");
217
+ const destination = join(cache, version);
218
+ let cacheExists = false;
219
+ try {
220
+ await lstat(destination);
221
+ cacheExists = true;
222
+ } catch (cause) {
223
+ if (cause.code !== "ENOENT") throw cause;
224
+ }
225
+ if (cacheExists) {
226
+ try {
227
+ const pkg = JSON.parse(await readFile2(join(destination, "package.json"), "utf8"));
228
+ const installed = JSON.parse(await readFile2(join(destination, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"), "utf8"));
229
+ if (runtimeDependencyVersion(pkg) === version && installed.version === version) return destination;
230
+ throw new Error("\u7F13\u5B58\u7248\u672C\u4E0D\u5339\u914D");
231
+ } catch (cause) {
232
+ throw new Error(`Runtime ${version} \u7684\u7F13\u5B58\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u5220\u9664 ${destination} \u540E\u91CD\u8BD5`, { cause });
233
+ }
234
+ }
235
+ await mkdir(cache, { recursive: true });
236
+ const temporaryRoot = await mkdtemp(join(cache, `.install-${version}-`));
237
+ try {
238
+ await writeFile(join(temporaryRoot, "package.json"), JSON.stringify({
239
+ name: "buddy-runtime-catalog",
240
+ private: true,
241
+ type: "module",
242
+ dependencies: { [BUDDY_RUNTIME_PACKAGE]: version }
243
+ }));
244
+ const userConfig = join(temporaryRoot, ".npmrc");
245
+ await writeFile(userConfig, `registry=${RUNTIME_REGISTRY}
246
+ `);
247
+ options.report?.(`\u6B63\u5728\u7F13\u5B58 Runtime ${version} \u7684\u80FD\u529B\u76EE\u5F55\uFF0C\u9996\u6B21\u4F7F\u7528\u9700\u8981\u4E0B\u8F7D\u4F9D\u8D56\u2026`);
248
+ const runNpm = options.runNpm ?? ((args, settings) => execute("npm", args, { ...settings, encoding: "utf8", maxBuffer: 4 * 1024 * 1024 }));
249
+ await runNpm([
250
+ "install",
251
+ "--ignore-scripts",
252
+ "--no-audit",
253
+ "--no-fund",
254
+ "--engine-strict",
255
+ `--registry=${RUNTIME_REGISTRY}`,
256
+ `--@my-life-buddies:registry=${RUNTIME_REGISTRY}`,
257
+ `--userconfig=${userConfig}`,
258
+ "--prefer-online",
259
+ "--fetch-retries=0",
260
+ "--fetch-timeout=20000"
261
+ ], { cwd: temporaryRoot, signal: options.signal, timeout: 18e4 });
262
+ const installed = JSON.parse(await readFile2(join(temporaryRoot, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"), "utf8"));
263
+ if (installed.version !== version) throw new Error(`\u7F13\u5B58\u7684 Runtime \u7248\u672C\u4E0E npm latest ${version} \u4E0D\u4E00\u81F4`);
264
+ options.signal?.throwIfAborted();
265
+ try {
266
+ await rename(temporaryRoot, destination);
267
+ } catch (cause) {
268
+ if (!["EEXIST", "ENOTEMPTY"].includes(cause.code ?? "")) throw cause;
269
+ }
270
+ return destination;
271
+ } finally {
272
+ await rm(temporaryRoot, { recursive: true, force: true });
273
+ }
274
+ }
275
+
276
+ // packages/cli-core/src/init/runtime-template.ts
277
+ var execute2 = promisify2(execFile2);
278
+ async function latestRuntimeTemplate(template, options) {
279
+ const bundledVersion = runtimeDependencyVersion(JSON.parse(template.packageJson));
280
+ if (!bundledVersion) throw new Error("CLI \u5DE5\u7A0B\u6A21\u677F\u7F3A\u5C11 Runtime \u7684\u51C6\u786E\u7248\u672C");
281
+ let temporaryRoot;
282
+ try {
283
+ options.signal?.throwIfAborted();
284
+ options.report("\u6B63\u5728\u67E5\u8BE2\u516C\u5171 npm \u7684\u6700\u65B0 Runtime\u2026");
285
+ const version = await latestRuntimeVersion(options);
286
+ let result = template;
287
+ if (version !== bundledVersion) {
288
+ temporaryRoot = await mkdtemp2(join2(tmpdir(), "buddy-runtime-template-"));
289
+ await writeFile2(join2(temporaryRoot, "package.json"), template.packageJson);
290
+ await writeFile2(join2(temporaryRoot, "package-lock.json"), template.packageLock);
291
+ const userConfig = join2(temporaryRoot, ".npmrc");
292
+ await writeFile2(userConfig, `registry=${RUNTIME_REGISTRY}
293
+ `);
294
+ options.report(`\u6B63\u5728\u4E3A Runtime ${version} \u751F\u6210\u4F9D\u8D56\u9501\u6587\u4EF6\u2026`);
295
+ const runNpm = options.runNpm ?? ((args, settings) => execute2("npm", args, { ...settings, encoding: "utf8", maxBuffer: 4 * 1024 * 1024 }));
296
+ await runNpm([
297
+ "install",
298
+ "--package-lock-only",
299
+ "--save-exact",
300
+ `${BUDDY_RUNTIME_PACKAGE}@${version}`,
301
+ "--ignore-scripts",
302
+ "--no-audit",
303
+ "--no-fund",
304
+ "--engine-strict",
305
+ `--registry=${RUNTIME_REGISTRY}`,
306
+ `--@my-life-buddies:registry=${RUNTIME_REGISTRY}`,
307
+ `--userconfig=${userConfig}`,
308
+ "--prefer-online",
309
+ "--fetch-retries=0",
310
+ "--fetch-timeout=20000"
311
+ ], { cwd: temporaryRoot, signal: options.signal, timeout: 6e4 });
312
+ result = {
313
+ packageJson: await readFile3(join2(temporaryRoot, "package.json"), "utf8"),
314
+ packageLock: await readFile3(join2(temporaryRoot, "package-lock.json"), "utf8")
315
+ };
316
+ }
317
+ const pkg = JSON.parse(result.packageJson);
318
+ const lock = JSON.parse(result.packageLock);
319
+ const locked = lock.packages?.[`node_modules/${BUDDY_RUNTIME_PACKAGE}`];
320
+ if (runtimeDependencyVersion(pkg) !== version || runtimeDependencyVersion(lock.packages?.[""]) !== version || locked?.version !== version || typeof locked.integrity !== "string" || !locked.integrity || typeof locked.resolved !== "string" || !locked.resolved.startsWith(RUNTIME_REGISTRY)) {
321
+ throw new Error("\u751F\u6210\u7684 Runtime \u7248\u672C\u4E0E\u4F9D\u8D56\u9501\u6587\u4EF6\u4E0D\u4E00\u81F4");
322
+ }
323
+ options.signal?.throwIfAborted();
324
+ options.report(`\u5DF2\u4ECE\u516C\u5171 npm latest \u9501\u5B9A Runtime ${version}\uFF08package.json \u4E0E package-lock.json\uFF09\u3002`);
325
+ return result;
326
+ } catch (cause) {
327
+ if (options.signal?.aborted) throw new Error("Runtime \u7248\u672C\u9009\u62E9\u5DF2\u53D6\u6D88");
328
+ const reason = cause instanceof Error && !cause.message.includes("Command failed") ? cause.message : "npm \u672A\u5B8C\u6210\u9501\u6587\u4EF6\u751F\u6210";
329
+ options.report(`\u672A\u80FD\u9501\u5B9A\u6700\u65B0 Runtime\uFF1A${reason}\u3002\u672C\u6B21\u4F7F\u7528 CLI \u968F\u9644\u7684 Runtime ${bundledVersion} \u53CA\u5176\u9501\u6587\u4EF6\uFF1B\u5B89\u88C5\u540E\u53EF\u663E\u5F0F\u5347\u7EA7\u5DE5\u7A0B\u4F9D\u8D56\u3002`);
330
+ return template;
331
+ } finally {
332
+ if (temporaryRoot) await rm2(temporaryRoot, { recursive: true, force: true });
333
+ }
334
+ }
115
335
 
116
336
  // packages/cli-core/src/init/scaffold.ts
117
- import { lstat, mkdir, open, readFile, rmdir, unlink } from "node:fs/promises";
118
- import { resolve } from "node:path";
119
337
  var BUDDY_PLATFORM_AGENT_ENTRY = "agent.md";
120
338
  var BUDDY_PLATFORM_FACTORY_ENTRY = "src/buddy-options.mjs";
121
339
  var BUDDY_PLATFORM_PACKAGE_JSON = "package.json";
@@ -206,11 +424,11 @@ try {
206
424
  }
207
425
  `;
208
426
  }
209
- async function scaffoldPlatformAgent(projectRoot, name) {
210
- const path = resolve(projectRoot, BUDDY_PLATFORM_AGENT_ENTRY);
427
+ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
428
+ const path = resolve2(projectRoot, BUDDY_PLATFORM_AGENT_ENTRY);
211
429
  const hasAlternateLockfile = (await Promise.all(["pnpm-lock.yaml", "yarn.lock"].map(async (name2) => {
212
430
  try {
213
- if (!(await lstat(resolve(projectRoot, name2))).isFile()) {
431
+ if (!(await lstat2(resolve2(projectRoot, name2))).isFile()) {
214
432
  throw new TypeError(`\u4F9D\u8D56\u9501\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF1A${name2}`);
215
433
  }
216
434
  return true;
@@ -221,39 +439,55 @@ async function scaffoldPlatformAgent(projectRoot, name) {
221
439
  }))).some(Boolean);
222
440
  const files = [
223
441
  { path, content: platformAgentTemplate(name) },
224
- { path: resolve(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate() },
225
- { path: resolve(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
226
- ...hasAlternateLockfile ? [] : [{ path: resolve(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK), content: await readFile(new URL("../../resources/agent-template/package-lock.json", import.meta.url), "utf8") }],
227
- { path: resolve(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() }
442
+ { path: resolve2(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate() },
443
+ { path: resolve2(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile4(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
444
+ ...hasAlternateLockfile ? [] : [{ path: resolve2(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK), content: await readFile4(new URL("../../resources/agent-template/package-lock.json", import.meta.url), "utf8") }],
445
+ { path: resolve2(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() }
228
446
  ];
229
447
  const handles = [];
230
448
  const createdDirectories = [];
231
449
  try {
232
450
  for (const directory of PLATFORM_DIRECTORIES) {
233
- const directoryPath = resolve(projectRoot, directory);
451
+ const directoryPath = resolve2(projectRoot, directory);
234
452
  try {
235
- await mkdir(directoryPath, { mode: 448 });
453
+ await mkdir2(directoryPath, { mode: 448 });
236
454
  createdDirectories.push(directoryPath);
237
455
  } catch (cause) {
238
456
  if (cause.code !== "EEXIST") throw cause;
239
457
  }
240
- if (!(await lstat(directoryPath)).isDirectory()) {
458
+ if (!(await lstat2(directoryPath)).isDirectory()) {
241
459
  throw new TypeError(`\u5B98\u65B9\u5DE5\u7A0B\u76EE\u5F55\u5FC5\u987B\u662F\u666E\u901A\u76EE\u5F55\uFF0C\u4E0D\u80FD\u4F7F\u7528\u6587\u4EF6\u6216\u7B26\u53F7\u94FE\u63A5\uFF1A${directoryPath}`);
242
460
  }
243
461
  }
244
- for (const file2 of files) {
462
+ for (const file of files) {
245
463
  try {
246
- handles.push({ path: file2.path, handle: await open(file2.path, "wx", 384) });
464
+ handles.push({ path: file.path, handle: await open(file.path, "wx", 384) });
247
465
  } catch (cause) {
248
466
  if (cause.code !== "EEXIST") throw cause;
249
- if (!(await lstat(file2.path)).isFile()) {
250
- throw new TypeError(`\u5B98\u65B9\u5DE5\u7A0B\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u76EE\u5F55\u6216\u7B26\u53F7\u94FE\u63A5\uFF1A${file2.path}`);
467
+ if (!(await lstat2(file.path)).isFile()) {
468
+ throw new TypeError(`\u5B98\u65B9\u5DE5\u7A0B\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u76EE\u5F55\u6216\u7B26\u53F7\u94FE\u63A5\uFF1A${file.path}`);
251
469
  }
252
470
  }
253
471
  }
472
+ const packageFile = files.find((file) => file.path === resolve2(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON));
473
+ const lockFile = files.find((file) => file.path === resolve2(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK));
474
+ if (options.resolveDependencies && lockFile && handles.some((file) => file.path === packageFile.path) && handles.some((file) => file.path === lockFile.path)) {
475
+ const template = await options.resolveDependencies({ packageJson: packageFile.content, packageLock: lockFile.content });
476
+ packageFile.content = template.packageJson;
477
+ lockFile.content = template.packageLock;
478
+ }
479
+ if (lockFile && (handles.some((file) => file.path === packageFile.path) || handles.some((file) => file.path === lockFile.path))) {
480
+ const packageContents = handles.some((file) => file.path === packageFile.path) ? packageFile.content : await readFile4(packageFile.path, "utf8");
481
+ const lockContents = handles.some((file) => file.path === lockFile.path) ? lockFile.content : await readFile4(lockFile.path, "utf8");
482
+ const declared = JSON.parse(packageContents).dependencies ?? {};
483
+ const locked = JSON.parse(lockContents).packages?.[""]?.dependencies ?? {};
484
+ if (JSON.stringify(Object.entries(declared).sort()) !== JSON.stringify(Object.entries(locked).sort())) {
485
+ 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");
486
+ }
487
+ }
254
488
  for (const { path: filePath, handle } of handles) {
255
- const file2 = files.find((candidate) => candidate.path === filePath);
256
- await handle.writeFile(file2.content, "utf8");
489
+ const file = files.find((candidate) => candidate.path === filePath);
490
+ await handle.writeFile(file.content, "utf8");
257
491
  await handle.sync();
258
492
  }
259
493
  return Object.freeze({ path, created: handles.length > 0 || createdDirectories.length > 0 });
@@ -280,7 +514,7 @@ async function missingBuddyAgentFiles(projectRoot) {
280
514
  ];
281
515
  const missing = await Promise.all(entries.map(async ([path, kind]) => {
282
516
  try {
283
- const entry = await lstat2(join(projectRoot, path));
517
+ const entry = await lstat3(join3(projectRoot, path));
284
518
  return (kind === "directory" ? entry.isDirectory() : entry.isFile()) ? void 0 : path;
285
519
  } catch (cause) {
286
520
  if (["ENOENT", "ENOTDIR"].includes(cause.code ?? "")) return path;
@@ -349,9 +583,6 @@ function validateBuddyProjectManifest(value) {
349
583
  return { ok: false, issues: schemaIssues(validateAgentSchema.errors) };
350
584
  }
351
585
  const manifest = value;
352
- if (manifest.model !== void 0 && !MODEL_IDS.includes(manifest.model)) {
353
- return { ok: false, issues: [{ path: "/model", message: `\u4E0D\u652F\u6301\u7684\u6A21\u578B ID\uFF1B\u53EF\u9009 ${MODEL_IDS.join("\u3001")}\uFF08buddy-cli models\uFF09` }] };
354
- }
355
586
  const seen = /* @__PURE__ */ new Set();
356
587
  for (const [index, dataset] of (manifest.datasets ?? []).entries()) {
357
588
  if (seen.has(dataset.id)) {
@@ -410,7 +641,7 @@ var ProjectInitializationError = class extends Error {
410
641
  };
411
642
  async function pathState(targetPath) {
412
643
  try {
413
- const entry = await lstat3(targetPath);
644
+ const entry = await lstat4(targetPath);
414
645
  if (!entry.isDirectory() || entry.isSymbolicLink()) return { kind: "other" };
415
646
  return { kind: "directory", identity: `${entry.dev}:${entry.ino}` };
416
647
  } catch (cause) {
@@ -430,7 +661,7 @@ function entryIdentity(entry) {
430
661
  }
431
662
  async function fileIdentity(targetPath) {
432
663
  try {
433
- const entry = await lstat3(targetPath);
664
+ const entry = await lstat4(targetPath);
434
665
  return entry.isFile() && !entry.isSymbolicLink() ? entryIdentity(entry) : void 0;
435
666
  } catch (cause) {
436
667
  if (cause.code === "ENOENT") return void 0;
@@ -439,7 +670,7 @@ async function fileIdentity(targetPath) {
439
670
  }
440
671
  async function unlinkMatchingFile(targetPath, expectedIdentity) {
441
672
  try {
442
- const entry = await lstat3(targetPath);
673
+ const entry = await lstat4(targetPath);
443
674
  if (!entry.isFile() || entry.isSymbolicLink() || entryIdentity(entry) !== expectedIdentity) {
444
675
  return false;
445
676
  }
@@ -477,7 +708,7 @@ async function readExistingManifest(agentConfigPath) {
477
708
  agentConfigPath
478
709
  );
479
710
  }
480
- const entry = await lstat3(agentConfigPath);
711
+ const entry = await lstat4(agentConfigPath);
481
712
  if (!entry.isFile() || entry.isSymbolicLink()) {
482
713
  throw new ProjectInitializationError(
483
714
  "TARGET_CHANGED",
@@ -486,7 +717,7 @@ async function readExistingManifest(agentConfigPath) {
486
717
  );
487
718
  }
488
719
  try {
489
- return parseBuddyProjectManifest(await readFile2(agentConfigPath, "utf8"));
720
+ return parseBuddyProjectManifest(await readFile5(agentConfigPath, "utf8"));
490
721
  } catch (cause) {
491
722
  throw new ProjectInitializationError(
492
723
  "TARGET_CHANGED",
@@ -497,8 +728,8 @@ async function readExistingManifest(agentConfigPath) {
497
728
  }
498
729
  }
499
730
  async function planBuddyDraftInitialization(directory) {
500
- const rootDirectory = resolve2(directory);
501
- const agentConfigPath = join2(rootDirectory, BUDDY_AGENT_FILENAME);
731
+ const rootDirectory = resolve3(directory);
732
+ const agentConfigPath = join4(rootDirectory, BUDDY_AGENT_FILENAME);
502
733
  const state2 = await pathState(rootDirectory);
503
734
  if (state2.kind === "other") {
504
735
  throw new ProjectInitializationError(
@@ -525,8 +756,8 @@ async function planBuddyDraftInitialization(directory) {
525
756
  };
526
757
  }
527
758
  async function planBuddyProjectInitialization(options) {
528
- const rootDirectory = resolve2(options.directory);
529
- const agentConfigPath = resolve2(rootDirectory, BUDDY_AGENT_FILENAME);
759
+ const rootDirectory = resolve3(options.directory);
760
+ const agentConfigPath = resolve3(rootDirectory, BUDDY_AGENT_FILENAME);
530
761
  const state2 = await pathState(rootDirectory);
531
762
  if (state2.kind === "other") {
532
763
  throw new ProjectInitializationError(
@@ -555,7 +786,7 @@ async function planBuddyProjectInitialization(options) {
555
786
  async function prepareInitializationDirectory(plan) {
556
787
  if (plan.createRootDirectory) {
557
788
  if ((await pathState(plan.rootDirectory)).kind !== "missing") throw targetChanged(plan);
558
- const firstCreatedDirectory = await mkdir2(plan.rootDirectory, { recursive: true });
789
+ const firstCreatedDirectory = await mkdir3(plan.rootDirectory, { recursive: true });
559
790
  if (firstCreatedDirectory === void 0) throw targetChanged(plan);
560
791
  const created = await pathState(plan.rootDirectory);
561
792
  if (created.kind !== "directory") throw targetChanged(plan);
@@ -570,7 +801,7 @@ async function prepareInitializationDirectory(plan) {
570
801
  async function publishNewFile(options) {
571
802
  let temporaryHandle;
572
803
  let publishedHandle;
573
- const temporaryPath = join2(
804
+ const temporaryPath = join4(
574
805
  options.rootDirectory,
575
806
  `.${options.temporaryLabel}.${process.pid}.${randomUUID()}.tmp`
576
807
  );
@@ -614,7 +845,7 @@ async function publishNewFile(options) {
614
845
  const afterPublish = await pathState(options.rootDirectory);
615
846
  const publishedFileIdentity = await fileIdentity(options.targetPath);
616
847
  const temporaryFileIdentity = await fileIdentity(temporaryPath);
617
- const publishedContents = publishedFileIdentity ? await readFile2(options.targetPath, "utf8") : void 0;
848
+ const publishedContents = publishedFileIdentity ? await readFile5(options.targetPath, "utf8") : void 0;
618
849
  if (afterPublish.kind !== "directory" || afterPublish.identity !== options.directoryIdentity || !publishedIdentity || publishedFileIdentity !== publishedIdentity || temporaryFileIdentity !== temporaryIdentity || publishedContents !== options.contents) {
619
850
  if (afterPublish.kind === "directory" && afterPublish.identity === options.directoryIdentity && publishedIdentity) {
620
851
  await unlinkMatchingFile(options.targetPath, publishedIdentity);
@@ -641,7 +872,7 @@ async function publishNewFile(options) {
641
872
  }
642
873
  }
643
874
  async function replaceExistingFile(options) {
644
- const temporaryPath = join2(
875
+ const temporaryPath = join4(
645
876
  options.rootDirectory,
646
877
  `.${options.temporaryLabel}.${process.pid}.${randomUUID()}.tmp`
647
878
  );
@@ -655,8 +886,8 @@ async function replaceExistingFile(options) {
655
886
  try {
656
887
  const root = await pathState(options.rootDirectory);
657
888
  if (root.kind !== "directory" || root.identity !== options.directoryIdentity || await fileIdentity(options.targetPath) !== options.expectedFileIdentity) throw targetChanged({ rootDirectory: options.rootDirectory });
658
- await rename(temporaryPath, options.targetPath);
659
- if (await readFile2(options.targetPath, "utf8") !== options.contents) {
889
+ await rename2(temporaryPath, options.targetPath);
890
+ if (await readFile5(options.targetPath, "utf8") !== options.contents) {
660
891
  throw targetChanged({ rootDirectory: options.rootDirectory });
661
892
  }
662
893
  } finally {
@@ -781,16 +1012,16 @@ async function initializeBuddyProject(options) {
781
1012
  return applyBuddyProjectInitialization(plan, options.config);
782
1013
  }
783
1014
  async function readBuddyProjectManifest(projectRoot) {
784
- const rootDirectory = resolve2(projectRoot);
785
- return parseBuddyProjectManifest(await readFile2(resolve2(rootDirectory, BUDDY_AGENT_FILENAME), "utf8"));
1015
+ const rootDirectory = resolve3(projectRoot);
1016
+ return parseBuddyProjectManifest(await readFile5(resolve3(rootDirectory, BUDDY_AGENT_FILENAME), "utf8"));
786
1017
  }
787
1018
  async function readBuddyAgentConfig(projectRoot) {
788
- const rootDirectory = resolve2(projectRoot);
789
- const source = await readFile2(resolve2(rootDirectory, BUDDY_AGENT_FILENAME), "utf8");
1019
+ const rootDirectory = resolve3(projectRoot);
1020
+ const source = await readFile5(resolve3(rootDirectory, BUDDY_AGENT_FILENAME), "utf8");
790
1021
  return parseBuddyAgentConfig(source);
791
1022
  }
792
1023
  async function readBuddyConfig(projectRoot) {
793
- const rootDirectory = resolve2(projectRoot);
1024
+ const rootDirectory = resolve3(projectRoot);
794
1025
  return combineBuddyProject(await readBuddyAgentConfig(rootDirectory));
795
1026
  }
796
1027
 
@@ -806,10 +1037,10 @@ var BuddyProjectContextError = class extends Error {
806
1037
  targetPath;
807
1038
  };
808
1039
  async function existingDirectory(target) {
809
- const requested = resolve3(target);
1040
+ const requested = resolve4(target);
810
1041
  let entry;
811
1042
  try {
812
- entry = await lstat4(requested);
1043
+ entry = await lstat5(requested);
813
1044
  } catch (cause) {
814
1045
  if (cause.code === "ENOENT") {
815
1046
  throw new BuddyProjectContextError(
@@ -828,12 +1059,12 @@ async function existingDirectory(target) {
828
1059
  requested
829
1060
  );
830
1061
  }
831
- return realpath(requested);
1062
+ return realpath2(requested);
832
1063
  }
833
1064
  async function projectFileState(directory, filename) {
834
- const configPath = join3(directory, filename);
1065
+ const configPath = join5(directory, filename);
835
1066
  try {
836
- const entry = await lstat4(configPath);
1067
+ const entry = await lstat5(configPath);
837
1068
  if (!entry.isFile() || entry.isSymbolicLink()) {
838
1069
  throw new BuddyProjectContextError(
839
1070
  "PROJECT_CONFIG_INVALID",
@@ -860,7 +1091,7 @@ async function findBuddyProjectRoot(startDirectory) {
860
1091
  return searchUp(await existingDirectory(startDirectory));
861
1092
  }
862
1093
  async function requireBuddyProjectRoot(startDirectory) {
863
- const requested = resolve3(startDirectory);
1094
+ const requested = resolve4(startDirectory);
864
1095
  const root = await findBuddyProjectRoot(requested);
865
1096
  if (root !== void 0) return root;
866
1097
  throw new BuddyProjectContextError(
@@ -874,7 +1105,7 @@ async function requireBuddyProjectRoot(startDirectory) {
874
1105
  }
875
1106
  async function requireBuddyAgentProjectRoot(startDirectory) {
876
1107
  const root = await requireBuddyProjectRoot(startDirectory);
877
- const agentPath = join3(root, BUDDY_AGENT_FILENAME);
1108
+ const agentPath = join5(root, BUDDY_AGENT_FILENAME);
878
1109
  try {
879
1110
  await readBuddyAgentConfig(root);
880
1111
  const missing = await missingBuddyAgentFiles(root);
@@ -893,10 +1124,10 @@ async function requireBuddyAgentProjectRoot(startDirectory) {
893
1124
  }
894
1125
  }
895
1126
  async function nearestExistingDirectory(target) {
896
- let candidate = resolve3(target);
1127
+ let candidate = resolve4(target);
897
1128
  while (true) {
898
1129
  try {
899
- const entry = await lstat4(candidate);
1130
+ const entry = await lstat5(candidate);
900
1131
  if (!entry.isDirectory()) {
901
1132
  throw new BuddyProjectContextError(
902
1133
  "PROJECT_DIRECTORY_INVALID",
@@ -904,7 +1135,7 @@ async function nearestExistingDirectory(target) {
904
1135
  candidate
905
1136
  );
906
1137
  }
907
- return realpath(candidate);
1138
+ return realpath2(candidate);
908
1139
  } catch (cause) {
909
1140
  if (cause.code !== "ENOENT") throw cause;
910
1141
  const parent = dirname(candidate);
@@ -914,7 +1145,7 @@ async function nearestExistingDirectory(target) {
914
1145
  }
915
1146
  }
916
1147
  async function assertOutsideBuddyProject(target) {
917
- const requested = resolve3(target);
1148
+ const requested = resolve4(target);
918
1149
  const container = await nearestExistingDirectory(requested);
919
1150
  const projectRoot = await searchUp(container);
920
1151
  if (projectRoot === void 0) return;
@@ -928,13 +1159,13 @@ async function assertOutsideBuddyProject(target) {
928
1159
  );
929
1160
  }
930
1161
  async function assertInitializableBuddyTarget(target) {
931
- const requested = resolve3(target);
1162
+ const requested = resolve4(target);
932
1163
  const container = await nearestExistingDirectory(requested);
933
1164
  const projectRoot = await searchUp(container);
934
1165
  if (projectRoot === void 0) return;
935
1166
  let requestedRoot = requested;
936
1167
  try {
937
- requestedRoot = await realpath(requested);
1168
+ requestedRoot = await realpath2(requested);
938
1169
  } catch (cause) {
939
1170
  if (cause.code !== "ENOENT") throw cause;
940
1171
  }
@@ -945,7 +1176,7 @@ async function assertInitializableBuddyTarget(target) {
945
1176
  } catch (cause) {
946
1177
  throw new BuddyProjectContextError(
947
1178
  "PROJECT_CONFIG_INVALID",
948
- `${join3(projectRoot, BUDDY_AGENT_FILENAME)} \u4E0D\u662F\u6709\u6548\u7684\u9879\u76EE\u6E05\u5355\u3002`,
1179
+ `${join5(projectRoot, BUDDY_AGENT_FILENAME)} \u4E0D\u662F\u6709\u6548\u7684\u9879\u76EE\u6E05\u5355\u3002`,
949
1180
  requested,
950
1181
  { cause }
951
1182
  );
@@ -961,322 +1192,44 @@ async function assertInitializableBuddyTarget(target) {
961
1192
  );
962
1193
  }
963
1194
 
964
- // packages/cli-core/src/widget-delivery.ts
965
- import { createHash } from "node:crypto";
966
- import { lstat as lstat5, readFile as readFile3, realpath as realpath2, readdir as readdir2, mkdir as mkdir3, writeFile, rename as rename2 } from "node:fs/promises";
967
- import { join as join4, resolve as resolve4 } from "node:path";
968
- var LOCK = "widget-design.lock.json";
969
- var IMPLEMENTATION = "widget-implementation.json";
970
- var RECEIPTS = ".buddy/widget-verification.json";
971
- var idPattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
972
- var hashPattern = /^[a-f0-9]{64}$/u;
973
- var sha = (raw) => createHash("sha256").update(raw).digest("hex");
974
- var object = (value) => value && typeof value === "object" && !Array.isArray(value);
975
- var text = (value) => typeof value === "string" && value.trim().length > 0;
976
- var WIDGET_REVIEW_CHECKS = ["visual", "interactions", "data-update", "trigger", "read-only"];
977
- var WIDGET_REVIEW_STATES = ["initial", "partial", "updated"];
978
- var NOTICE = "\u7ED3\u6784\u68C0\u67E5\u4E0E\u9884\u89C8\u6838\u5BF9\u8BB0\u5F55\u5206\u522B\u5C55\u793A\uFF1B\u6838\u5BF9\u8BB0\u5F55\u7531\u6267\u884C\u6838\u5BF9\u8005\u63D0\u4F9B\uFF0C\u5DE5\u5177\u4E0D\u81EA\u52A8\u5224\u65AD\u89C6\u89C9\u4E00\u81F4\uFF0C\u4E5F\u4E0D\u4EE3\u8868\u5F00\u53D1\u8005\u4F53\u9A8C\u9A8C\u6536\u6216\u53D1\u5E03\u6210\u529F\u3002";
979
- function portable(path) {
980
- if (!text(path) || path.startsWith("/") || path.includes("\\") || /[\x00-\x1f:]/u.test(path) || path.split("/").some((p) => !p || p === "." || p === "..")) throw new Error("\u5C0F\u6302\u4EF6\u8DEF\u5F84\u5FC5\u987B\u662F\u9879\u76EE\u5185\u76F8\u5BF9\u8DEF\u5F84");
981
- return path;
982
- }
983
- async function file(root, path, optional = false) {
984
- portable(path);
985
- const base = await realpath2(root);
986
- let cursor = base;
987
- const parts = path.split("/");
988
- for (const [index, part] of parts.entries()) {
989
- cursor = join4(cursor, part);
990
- const stat2 = await lstat5(cursor).catch((e) => {
991
- if (e.code === "ENOENT") return void 0;
992
- throw e;
993
- });
994
- if (!stat2) {
995
- if (optional) return void 0;
996
- throw new Error(`\u7F3A\u5C11\u6587\u4EF6\uFF1A${path}`);
997
- }
998
- if (stat2.isSymbolicLink() || (index < parts.length - 1 ? !stat2.isDirectory() : !stat2.isFile())) throw new Error(`\u4E0D\u63A5\u53D7\u7B26\u53F7\u94FE\u63A5\u6216\u7279\u6B8A\u6587\u4EF6\uFF1A${path}`);
999
- if (index === parts.length - 1 && stat2.size > 8 * 1024 * 1024) throw new Error(`\u6587\u4EF6\u8D85\u8FC7 8 MB\uFF1A${path}`);
1000
- }
1001
- return readFile3(cursor);
1002
- }
1003
- async function jsonFile(root, path, optional = false) {
1004
- const bytes = await file(root, path, optional);
1005
- if (!bytes) return void 0;
1006
- try {
1007
- return JSON.parse(bytes.toString("utf8"));
1008
- } catch {
1009
- throw new Error(`JSON \u65E0\u6548\uFF1A${path}`);
1010
- }
1011
- }
1012
- async function save(root, path, value) {
1013
- portable(path);
1014
- let cursor = resolve4(root);
1015
- for (const segment of path.split("/").slice(0, -1)) {
1016
- cursor = join4(cursor, segment);
1017
- await mkdir3(cursor).catch((e) => {
1018
- if (e.code !== "EEXIST") throw e;
1019
- });
1020
- const stat2 = await lstat5(cursor);
1021
- if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw new Error("\u5199\u5165\u76EE\u5F55\u4E0D\u5B89\u5168");
1022
- }
1023
- await file(root, path, true);
1024
- const target = join4(root, path), temp = `${target}.${process.pid}.${Date.now()}.tmp`;
1025
- await writeFile(temp, JSON.stringify(value, null, 2) + "\n", { flag: "wx", mode: 384 });
1026
- await rename2(temp, target);
1027
- }
1028
- function validateLock(value) {
1029
- if (!object(value) || value.schemaVersion !== 1 || !text(value.buddyId) || !text(value.revision) || !hashPattern.test(value.catalogHash) || !Array.isArray(value.items) || value.items.length > 100) throw new Error("\u8BBE\u8BA1\u7ED1\u5B9A\u6587\u4EF6\u65E0\u6548\uFF0C\u8BF7\u8FD0\u884C buddy-cli widgets sync");
1030
- const seen = /* @__PURE__ */ new Set();
1031
- for (const item of value.items) {
1032
- if (!object(item) || typeof item.id !== "string" || item.id.length > 64 || !idPattern.test(item.id) || seen.has(item.id) || !text(item.name) || !hashPattern.test(item.prototypeHash) || !Array.isArray(item.fields) || !item.fields.every(text) || new Set(item.fields).size !== item.fields.length) throw new Error("\u8BBE\u8BA1\u6E05\u5355\u5305\u542B\u65E0\u6548\u6216\u91CD\u590D\u7684\u5C0F\u6302\u4EF6");
1033
- seen.add(item.id);
1034
- }
1035
- }
1036
- async function creatorDesign(root) {
1037
- const session = await jsonFile(root, ".buddy/creator/session.json", true);
1038
- if (!session) return void 0;
1039
- if (session.schemaVersion !== 1 || !text(session.platformBuddyId) || !/^[a-f0-9-]{36}$/u.test(session.creationKey)) throw new Error("Creator \u9879\u76EE\u8EAB\u4EFD\u65E0\u6548");
1040
- const workspace = `.buddy/creator/workspaces/${session.creationKey}`;
1041
- const state2 = await jsonFile(root, `${workspace}/state.json`);
1042
- if (!state2.artifacts?.["widget.catalog"]) return void 0;
1043
- const completion = await jsonFile(root, `${workspace}/completion.json`);
1044
- if (completion.status !== "ready" || completion.revision !== state2.revision || state2.paused || state2.pendingTurnId || !/^[a-zA-Z0-9_-]+$/u.test(state2.revision)) throw new Error("\u5C0F\u6302\u4EF6\u8BBE\u8BA1\u4EA4\u4ED8\u672A\u5B8C\u6210\u6216\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u5148\u6062\u590D Creator \u5F53\u524D\u8BBE\u8BA1\u9A8C\u6536");
1045
- const directory = `${workspace}/deliverables/${state2.revision}`;
1046
- const manifest = await jsonFile(root, `${directory}/MANIFEST.json`);
1047
- if (state2.buddyId !== session.creationKey || manifest.buddyId !== state2.buddyId) throw new Error("Creator \u4F5C\u54C1\u4E0E\u4EA4\u4ED8\u8EAB\u4EFD\u4E0D\u4E00\u81F4");
1048
- if (manifest.complete !== true || manifest.revision !== state2.revision || !Array.isArray(manifest.files)) throw new Error("\u8BBE\u8BA1\u4EA4\u4ED8\u6E05\u5355\u65E0\u6548");
1049
- const artifact = async (path) => {
1050
- const bytes = await file(root, `${directory}/${path}`);
1051
- const entry = manifest.files.find((e) => e.path === path);
1052
- if (!entry || entry.sha256 !== sha(bytes) || entry.bytes !== bytes.length) throw new Error(`\u8BBE\u8BA1\u6210\u679C\u88AB\u4FEE\u6539\uFF1A${path}\uFF1B\u5148\u6062\u590D\u4EA4\u4ED8`);
1053
- return bytes;
1054
- };
1055
- const confirmed = (id, hash) => state2.artifacts?.[id]?.hash === hash && state2.confirmations?.some((c) => c.objectId === id && c.hash === hash && c.decision === "confirmed" && !c.invalidatedBy);
1056
- const catalog = JSON.parse((await artifact("widgets/catalog.json")).toString());
1057
- if (!confirmed("widget.catalog", catalog.hash) || !Array.isArray(catalog.data?.widgets)) throw new Error("\u5C0F\u6302\u4EF6\u6E05\u5355\u4E0D\u662F\u5F53\u524D\u5DF2\u786E\u8BA4\u7248\u672C");
1058
- const items = [];
1059
- for (const item of catalog.data.widgets) {
1060
- if (!text(item.id) || item.id.length > 64 || !idPattern.test(item.id)) throw new Error("\u8BBE\u8BA1\u7C7B\u578B ID \u65E0\u6548");
1061
- const prefix = `widgets/${item.id}`;
1062
- const prototype = JSON.parse((await artifact(`${prefix}/prototype.json`)).toString());
1063
- const acceptance = JSON.parse((await artifact(`${prefix}/acceptance.json`)).toString()).artifact;
1064
- if (!confirmed(`widget.${item.id}.prototype`, prototype.hash) || !confirmed(`widget.${item.id}.acceptance`, acceptance.hash) || acceptance.data?.prototypeHash !== prototype.hash) throw new Error(`\u8BBE\u8BA1\u5C1A\u672A\u6709\u6548\u9A8C\u6536\uFF1A${item.id}`);
1065
- for (const asset of ["index.html", "style.css", "app.js"]) await artifact(`${prefix}/${asset}`);
1066
- items.push({ id: item.id, name: item.name, prototypeHash: prototype.hash, fields: item.fields.map((f) => f.key) });
1067
- }
1068
- const result = { schemaVersion: 1, buddyId: session.platformBuddyId, revision: state2.revision, catalogHash: catalog.hash, items };
1069
- validateLock(result);
1070
- return result;
1071
- }
1072
- async function syncWidgetDesign(root) {
1073
- const design = await creatorDesign(root);
1074
- if (!design) throw new Error("\u5F53\u524D\u9879\u76EE\u6CA1\u6709\u5DF2\u9A8C\u6536\u7684\u5C0F\u6302\u4EF6\u8BBE\u8BA1\uFF1B\u76F4\u63A5\u5F00\u53D1\u9879\u76EE\u53EF\u7EE7\u7EED\u4F7F\u7528\u539F\u6D41\u7A0B");
1075
- const config = await jsonFile(root, "buddy.agent.json");
1076
- if (config.buddyId !== design.buddyId) throw new Error("\u8BBE\u8BA1\u4E0E\u642D\u5B50\u8EAB\u4EFD\u4E0D\u4E00\u81F4");
1077
- const old = await jsonFile(root, IMPLEMENTATION, true);
1078
- if (old && (!object(old) || old.schemaVersion !== 1 || !Array.isArray(old.widgets))) throw new Error("\u5DF2\u6709\u5B9E\u73B0\u6620\u5C04\u635F\u574F\uFF0C\u4FDD\u7559\u539F\u6587\u4EF6\uFF0C\u8BF7\u4FEE\u590D\u540E\u518D\u540C\u6B65");
1079
- const mappings = design.items.map((item) => old?.widgets.find((w) => w.designId === item.id) ?? {
1080
- designId: item.id,
1081
- typeId: item.id,
1082
- prototypeHash: item.prototypeHash,
1083
- fields: Object.fromEntries(item.fields.map((key) => [key, ""])),
1084
- lifecycle: { create: [], update: [], present: [] }
1085
- });
1086
- const next = { schemaVersion: 1, widgets: mappings };
1087
- if (JSON.stringify(old) !== JSON.stringify(next)) await save(root, IMPLEMENTATION, next);
1088
- await save(root, LOCK, design);
1089
- }
1090
- async function sourceSnapshot(root) {
1091
- const result = [];
1092
- const visit = async (path, depth = 0) => {
1093
- if (depth > 32 || result.length > 1e4) throw new Error("\u5B9E\u73B0\u6E90\u7801\u8D85\u51FA\u68C0\u67E5\u8303\u56F4");
1094
- const stat2 = await lstat5(join4(root, path)).catch((e) => {
1095
- if (e.code === "ENOENT") return void 0;
1096
- throw e;
1097
- });
1098
- if (!stat2) return;
1099
- if (stat2.isSymbolicLink()) throw new Error(`\u5B9E\u73B0\u4E0D\u80FD\u4F7F\u7528\u7B26\u53F7\u94FE\u63A5\uFF1A${path}`);
1100
- if (stat2.isDirectory()) {
1101
- for (const name of (await readdir2(join4(root, path))).sort()) await visit(`${path}/${name}`, depth + 1);
1102
- } else result.push([path, sha(await file(root, path))]);
1103
- };
1104
- for (const name of ["src", "resources", "widgets", "start.mjs", "agent.md", "buddy.agent.json", "package.json", "package-lock.json", "pnpm-lock.yaml", "yarn.lock"]) await visit(name);
1105
- return result;
1106
- }
1107
- async function checkWidgetDelivery(root) {
1108
- const report = { status: "not-configured", items: [], issues: [], notice: NOTICE };
1109
- try {
1110
- const current = await creatorDesign(root);
1111
- const lockBytes = await file(root, LOCK, true);
1112
- let lock = lockBytes ? JSON.parse(lockBytes.toString()) : void 0;
1113
- if (!current && !lock) {
1114
- if (await file(root, IMPLEMENTATION, true)) throw new Error("\u5B9E\u73B0\u6620\u5C04\u5B58\u5728\uFF0C\u4F46\u8BBE\u8BA1\u7ED1\u5B9A\u7F3A\u5931\uFF0C\u8BF7\u6062\u590D widget-design.lock.json");
1115
- return report;
1116
- }
1117
- report.status = "incomplete";
1118
- if (!lock) {
1119
- report.issues.push("\u5DF2\u9A8C\u6536\u8BBE\u8BA1\u5C1A\u672A\u7ED1\u5B9A\u5230\u5DE5\u7A0B\uFF0C\u8BF7\u8FD0\u884C buddy-cli widgets sync");
1120
- lock = current;
1121
- }
1122
- validateLock(lock);
1123
- report.designRevision = lock.revision;
1124
- const config = await jsonFile(root, "buddy.agent.json");
1125
- if (config.buddyId !== lock.buddyId) throw new Error("\u8BBE\u8BA1\u4E0E\u642D\u5B50\u8EAB\u4EFD\u4E0D\u4E00\u81F4");
1126
- if (current && JSON.stringify(current) !== JSON.stringify(lock)) report.issues.push("\u8BBE\u8BA1\u5DF2\u53D8\u5316\uFF0C\u8BF7\u8FD0\u884C buddy-cli widgets sync\uFF1B\u65E7\u5B9E\u73B0\u548C\u6838\u5BF9\u8BB0\u5F55\u4E0D\u80FD\u6CBF\u7528\u4E3A\u65B0\u7248\u9A8C\u6536");
1127
- const implementationBytes = await file(root, IMPLEMENTATION, true);
1128
- const implementation = implementationBytes ? JSON.parse(implementationBytes.toString()) : void 0;
1129
- const mappings = implementation?.schemaVersion === 1 && Array.isArray(implementation.widgets) ? implementation.widgets : [];
1130
- if (!implementation || mappings.length !== lock.items.length) report.issues.push("\u5B9E\u73B0\u6620\u5C04\u4E0E\u5DF2\u9A8C\u6536\u6E05\u5355\u6570\u91CF\u4E0D\u7B26");
1131
- const receipts = await jsonFile(root, RECEIPTS, true);
1132
- const snapshot = await sourceSnapshot(root);
1133
- report.files = snapshot.map(([path, digest2]) => ({ path, digest: `sha256:${digest2}` }));
1134
- if (lockBytes) report.files.push({ path: LOCK, digest: `sha256:${sha(lockBytes)}` });
1135
- if (implementationBytes) report.files.push({ path: IMPLEMENTATION, digest: `sha256:${sha(implementationBytes)}` });
1136
- const usedTypes = /* @__PURE__ */ new Set();
1137
- for (const mapping of mappings) if (!lock.items.some((item) => item.id === mapping.designId)) report.issues.push("\u5B58\u5728\u4E0D\u5C5E\u4E8E\u5F53\u524D\u8BBE\u8BA1\u7684\u5B9E\u73B0\u6620\u5C04\uFF0C\u8BF7\u8FD0\u884C widgets sync");
1138
- for (const item of lock.items) {
1139
- const row = { id: item.id, name: item.name, status: "missing", issues: [] };
1140
- report.items.push(row);
1141
- try {
1142
- const matches = mappings.filter((w) => w.designId === item.id);
1143
- if (matches.length !== 1) throw new Error("\u7F3A\u5C11\u6216\u91CD\u590D\u7684\u5B9E\u73B0\u6620\u5C04");
1144
- const m = matches[0];
1145
- if (!text(m.typeId) || m.typeId.length > 64 || !/^[\p{L}\p{N}][\p{L}\p{N}_-]*$/u.test(m.typeId) || usedTypes.has(m.typeId)) throw new Error("\u6BCF\u4E2A\u5DF2\u9A8C\u6536\u8BBE\u8BA1\u5FC5\u987B\u5BF9\u5E94\u4E00\u4E2A\u72EC\u7ACB\u3001\u6709\u6548\u7684\u7C7B\u578B ID\uFF0C\u4E0D\u80FD\u5408\u5E76\u6210\u540C\u4E00\u4E2A\u5DE5\u4F5C\u53F0");
1146
- usedTypes.add(m.typeId);
1147
- row.typeId = m.typeId;
1148
- if (m.prototypeHash !== item.prototypeHash) row.issues.push("\u5B9E\u73B0\u7ED1\u5B9A\u7684\u539F\u578B\u7248\u672C\u5DF2\u8FC7\u671F");
1149
- const html = (await file(root, `widgets/${m.typeId}/index.html`)).toString();
1150
- if (!html.trim()) throw new Error("\u9875\u9762\u4E3A\u7A7A");
1151
- const schema = await jsonFile(root, `widgets/${m.typeId}/schema.json`);
1152
- if (!object(schema.modules) || !Object.keys(schema.modules).length) throw new Error("\u7F3A\u5C11\u6709\u6548\u7684\u6570\u636E\u6A21\u5757");
1153
- for (const key of item.fields) {
1154
- const binding = m.fields?.[key];
1155
- if (!text(binding) || !object(schema.modules[binding.split(".")[0]]?.record)) row.issues.push(`\u5B57\u6BB5 ${key} \u672A\u6620\u5C04\u5230\u5B9E\u9645\u6570\u636E\u6A21\u5757`);
1156
- }
1157
- for (const phase of ["create", "update", "present"]) {
1158
- const paths = m.lifecycle?.[phase];
1159
- if (!Array.isArray(paths) || !paths.length || paths.length > 50 || !paths.every(text)) {
1160
- row.issues.push(`\u7F3A\u5C11${phase}\u4EE3\u7801\u8DEF\u5F84`);
1161
- continue;
1162
- }
1163
- for (const path of paths) {
1164
- if (!path.startsWith("src/") || !/\.(?:mjs|js|ts|cjs)$/u.test(path)) throw new Error("\u521B\u5EFA\u3001\u66F4\u65B0\u548C\u5C55\u793A\u5FC5\u987B\u6620\u5C04\u5230 src/ \u4E0B\u7684\u4EE3\u7801");
1165
- if (!(await file(root, path)).toString().trim()) throw new Error(`\u4EE3\u7801\u4E3A\u7A7A\uFF1A${path}`);
1166
- }
1167
- }
1168
- if (row.issues.length) continue;
1169
- row.status = "implemented";
1170
- row.implementationDigest = sha(JSON.stringify({ design: lock, mapping: m, snapshot }));
1171
- const receipt = receipts?.items?.[item.id];
1172
- if (receipt?.implementationDigest === row.implementationDigest) {
1173
- validateEvidence(receipt.evidence);
1174
- if (!Array.isArray(receipt.artifacts) || receipt.artifacts.length !== 3) throw new Error("\u6838\u5BF9\u8BC1\u636E\u8BB0\u5F55\u65E0\u6548");
1175
- for (const [index, artifact] of receipt.artifacts.entries()) {
1176
- if (artifact.path !== receipt.evidence.states[WIDGET_REVIEW_STATES[index]].artifact) throw new Error("\u6838\u5BF9\u8BC1\u636E\u8DEF\u5F84\u4E0D\u5339\u914D");
1177
- if (sha(await file(root, artifact.path)) !== artifact.digest) throw new Error("\u9884\u89C8\u6838\u5BF9\u8BC1\u636E\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6838\u5BF9");
1178
- }
1179
- if (!receipt.artifacts.length) throw new Error("\u7F3A\u5C11\u9884\u89C8\u6838\u5BF9\u8BC1\u636E");
1180
- row.status = "verified";
1181
- } else row.issues.push("\u5C1A\u672A\u8BB0\u5F55\u5F53\u524D\u5B9E\u73B0\u7248\u672C\u7684\u771F\u5B9E\u9884\u89C8\u6838\u5BF9\uFF1B\u6587\u4EF6\u5B58\u5728\u4E0D\u7B49\u4E8E\u6837\u5F0F\u4E0E\u884C\u4E3A\u5DF2\u9A8C\u8BC1");
1182
- } catch (cause) {
1183
- row.issues.push(cause instanceof Error ? cause.message : String(cause));
1184
- }
1185
- }
1186
- if (!report.issues.length && report.items.every((item) => item.status === "verified" && !item.issues.length)) report.status = "ready";
1187
- } catch (cause) {
1188
- report.status = "incomplete";
1189
- report.issues.push(cause instanceof Error ? cause.message : String(cause));
1190
- }
1191
- return report;
1192
- }
1193
- function validateEvidence(value) {
1194
- if (!object(value) || !text(value.previewUrl) || !text(value.observedAt) || !Number.isFinite(Date.parse(value.observedAt)) || !text(value.reviewer) || !object(value.states) || !object(value.checks)) throw new Error("\u6838\u5BF9\u8BB0\u5F55\u9700\u5305\u542B previewUrl\u3001observedAt\u3001reviewer\u3001states \u548C checks");
1195
- const url = new URL(value.previewUrl);
1196
- if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || url.pathname.includes("bootstrap") || url.search || url.hash) throw new Error("\u9884\u89C8\u5730\u5740\u9700\u4F7F\u7528\u4E0D\u542B\u767B\u5F55\u51ED\u636E\u7684\u9875\u9762\u5730\u5740");
1197
- for (const state2 of WIDGET_REVIEW_STATES) {
1198
- if (!text(value.states[state2]?.notes) || !text(value.states[state2]?.artifact)) throw new Error(`\u7F3A\u5C11 ${state2} \u7684\u89C2\u5BDF\u8BF4\u660E\u4E0E\u8BC1\u636E\u6587\u4EF6`);
1199
- portable(value.states[state2].artifact);
1200
- }
1201
- for (const check of WIDGET_REVIEW_CHECKS) if (!text(value.checks[check])) throw new Error(`\u7F3A\u5C11 ${check} \u7684\u5B9E\u9645\u89C2\u5BDF\u8BF4\u660E`);
1202
- }
1203
- async function recordWidgetVerification(root, designId, evidencePath) {
1204
- const report = await checkWidgetDelivery(root);
1205
- const row = report.items.find((item) => item.id === designId);
1206
- if (report.issues.length || !row?.implementationDigest) throw new Error("\u5148\u5B8C\u6210\u5F53\u524D\u8BBE\u8BA1\u4E0E\u5B9E\u73B0\u7684\u7ED3\u6784\u68C0\u67E5\uFF0C\u518D\u8BB0\u5F55\u9884\u89C8\u6838\u5BF9");
1207
- const evidence = await jsonFile(root, evidencePath);
1208
- validateEvidence(evidence);
1209
- if (evidence.implementationDigest !== row.implementationDigest) throw new Error("\u6838\u5BF9\u8BB0\u5F55\u7684 implementationDigest \u4E0E\u5F53\u524D\u4EE3\u7801\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u5148\u6838\u5BF9\u5F53\u524D\u5B9E\u73B0");
1210
- const artifacts = [];
1211
- for (const state2 of WIDGET_REVIEW_STATES) {
1212
- const path = evidence.states[state2].artifact;
1213
- artifacts.push({ path, digest: sha(await file(root, path)) });
1214
- }
1215
- const old = await jsonFile(root, RECEIPTS, true);
1216
- if (old && (old.schemaVersion !== 1 || !object(old.items))) throw new Error("\u5DF2\u6709\u6838\u5BF9\u8BB0\u5F55\u635F\u574F\uFF0C\u4FDD\u7559\u6587\u4EF6\u8BF7\u5148\u4FEE\u590D");
1217
- await save(root, RECEIPTS, { schemaVersion: 1, items: { ...old?.items, [designId]: {
1218
- implementationDigest: row.implementationDigest,
1219
- evidence,
1220
- artifacts
1221
- } } });
1222
- }
1223
- function widgetDeliverySummary(report) {
1224
- if (report.status === "not-configured") return "\u5F53\u524D\u5DE5\u7A0B\u6CA1\u6709\u7ED1\u5B9A\u7684 Creator \u5C0F\u6302\u4EF6\u8BBE\u8BA1\uFF1B\u672A\u6267\u884C\u8BBE\u8BA1\u4E00\u81F4\u6027\u68C0\u67E5\u3002";
1225
- return [
1226
- report.status === "ready" ? "\u5C0F\u6302\u4EF6\u7ED3\u6784\u68C0\u67E5\u4E0E\u5F53\u524D\u7248\u672C\u9884\u89C8\u6838\u5BF9\u8BB0\u5F55\u9F50\u5168\u3002" : "\u5C0F\u6302\u4EF6\u4EA4\u4ED8\u672A\u5B8C\u6210\uFF1A",
1227
- ...report.issues,
1228
- ...report.items.map((item) => `${item.name}\uFF08${item.id}\uFF09\uFF1A${item.status === "verified" ? "\u6838\u5BF9\u5DF2\u8BB0\u5F55" : item.status === "implemented" ? "\u5DF2\u5B9E\u73B0\uFF0C\u5F85\u6838\u5BF9" : "\u5F85\u8865\u9F50\u5B9E\u73B0"}${item.issues.length ? "\uFF1B" + item.issues.join("\uFF1B") : ""}`),
1229
- report.notice
1230
- ].join("\n");
1195
+ // packages/cli-core/src/commands/runtime-source.ts
1196
+ async function runtimeCatalogSource(directory, options = {}) {
1197
+ const project = await findBuddyProjectRoot(directory);
1198
+ if (project) return { root: project, source: "project" };
1199
+ return { root: await (options.latestRuntimeRoot?.() ?? cachedLatestRuntimeRoot(options)), source: "npm" };
1231
1200
  }
1232
1201
 
1233
- // packages/cli-core/src/commands/widgets.ts
1234
- var WIDGET_COMMAND_HELP = `\u5C0F\u6302\u4EF6\u8BBE\u8BA1\u843D\u5730\u68C0\u67E5\uFF08\u672C\u5730\uFF0C\u4E0D\u4E0A\u4F20\u3001\u4E0D\u53D1\u5E03\uFF09
1235
- buddy-cli widgets sync [--directory <\u9879\u76EE\u76EE\u5F55>]
1236
- buddy-cli widgets check [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
1237
- buddy-cli widgets verify --id <\u8BBE\u8BA1ID> --evidence <\u9879\u76EE\u5185\u8BB0\u5F55.json> [--directory <\u9879\u76EE\u76EE\u5F55>]
1238
- sync \u4ECE\u5F53\u524D\u5DF2\u9A8C\u6536 Creator \u4EA4\u4ED8\u7ED1\u5B9A\u8BBE\u8BA1\uFF0C\u751F\u6210\u5B9E\u73B0\u6620\u5C04\uFF1B\u4FDD\u7559\u5DF2\u6709\u6620\u5C04\uFF0C\u8BBE\u8BA1\u53D8\u5316\u540E\u91CD\u65B0\u6838\u5BF9\u3002
1239
- check \u9010\u9879\u5217\u51FA\u9057\u6F0F\u3001\u8FC7\u671F\u7248\u672C\u548C\u5F85\u6838\u5BF9\u9879\uFF1B\u9000\u51FA\u7801 1 \u8868\u793A\u672A\u5B8C\u6210\u3002DEV \u53EF\u7EE7\u7EED\u8C03\u8BD5\uFF0Cpush \u4F1A\u62E6\u622A\u3002
1240
- verify \u8BB0\u5F55\u771F\u5B9E\u9884\u89C8\u7684\u4E09\u6001\u8BC1\u636E\u4E0E\u4E94\u9879\u89C2\u5BDF\uFF0C\u5E76\u7ED1\u5B9A\u5F53\u524D\u4EE3\u7801\u6458\u8981\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u5224\u65AD\u89C6\u89C9\u4E00\u81F4\u3002`;
1241
- async function runWidgetsCommand(args, io, cwd) {
1202
+ // packages/cli-core/src/commands/models.ts
1203
+ var MODELS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli models [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
1204
+ \u5DE5\u7A0B\u5185\u8BFB\u53D6\u5DF2\u5B89\u88C5 Runtime \u7684\u6A21\u578B\u76EE\u5F55\uFF1B\u5DE5\u7A0B\u5916\u8054\u7F51\u8BFB\u53D6\u5E76\u7F13\u5B58\u516C\u5171 npm \u6700\u65B0 Runtime\u3002
1205
+ \u65E0\u9700\u767B\u5F55\u642D\u642D\u8D26\u53F7\u3002\u8F93\u51FA\u5305\u542B\u5B9E\u9645 Runtime \u7248\u672C\u548C\u6765\u6E90\u3002
1206
+ \u5C06\u6240\u9009 ID \u5199\u5165 buddy.agent.json.model\uFF1B\u6A21\u677F\u5728 initialState.model \u4E2D\u4F7F\u7528\u5B83\u3002`;
1207
+ async function runModelsCommand(args, io, cwd, options = {}) {
1242
1208
  try {
1243
- const [action, ...rest] = args;
1244
- if (!action || action === "--help" || action === "help") {
1245
- io.write(WIDGET_COMMAND_HELP);
1209
+ if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
1210
+ io.write(MODELS_COMMAND_HELP);
1246
1211
  return { exitCode: 0 };
1247
1212
  }
1248
- if (!["sync", "check", "verify"].includes(action)) throw new Error(WIDGET_COMMAND_HELP);
1249
- const flags = /* @__PURE__ */ new Map();
1250
- for (let i = 0; i < rest.length; i++) {
1251
- const key = rest[i];
1252
- if (!["--directory", "--id", "--evidence", "--json"].includes(key) || flags.has(key)) throw new Error(`\u4E0D\u652F\u6301\u6216\u91CD\u590D\u7684\u53C2\u6570\uFF1A${key}`);
1253
- if (key === "--json") flags.set(key, "true");
1254
- else {
1255
- const value = rest[++i];
1256
- if (!value || value.startsWith("--")) throw new Error(`\u7F3A\u5C11\u53C2\u6570\uFF1A${key}`);
1257
- flags.set(key, value);
1258
- }
1259
- }
1260
- if (action !== "verify" && (flags.has("--id") || flags.has("--evidence"))) throw new Error("--id / --evidence \u4EC5\u7528\u4E8E verify");
1261
- if (action !== "check" && flags.has("--json")) throw new Error("--json \u4EC5\u7528\u4E8E check");
1262
- const root = await findBuddyProjectRoot(resolve5(cwd, flags.get("--directory") ?? "."));
1263
- if (!root) throw new Error("\u8BF7\u5728\u642D\u5B50\u5DE5\u7A0B\u4E2D\u8FD0\u884C\uFF0C\u6216\u6307\u5B9A --directory");
1264
- if (action === "sync") {
1265
- await syncWidgetDesign(root);
1266
- io.write("\u5DF2\u540C\u6B65\u5F53\u524D\u9A8C\u6536\u8BBE\u8BA1\u5230 widget-design.lock.json\uFF0C\u5E76\u751F\u6210 widget-implementation.json\uFF1B\u8BF7\u9010\u9879\u586B\u5199\u5B57\u6BB5\u4E0E\u5B9E\u73B0\u8DEF\u5F84\uFF0C\u968F\u540E\u8FD0\u884C widgets check\u3002");
1267
- return { exitCode: 0 };
1213
+ let directory;
1214
+ let json = false;
1215
+ for (let i = 0; i < args.length; i++) {
1216
+ if (args[i] === "--json" && !json) json = true;
1217
+ else if (args[i] === "--directory" && directory === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) directory = args[++i];
1218
+ else throw new Error(`models \u53C2\u6570\u65E0\u6548\uFF1A${args[i]}
1219
+ ${MODELS_COMMAND_HELP}`);
1268
1220
  }
1269
- if (action === "verify") {
1270
- if (!flags.get("--id") || !flags.get("--evidence")) throw new Error("verify \u9700\u8981 --id \u4E0E --evidence");
1271
- await recordWidgetVerification(root, flags.get("--id"), flags.get("--evidence"));
1272
- io.write("\u5DF2\u4FDD\u5B58\u4E0E\u5F53\u524D\u4EE3\u7801\u7ED1\u5B9A\u7684\u9884\u89C8\u6838\u5BF9\u8BB0\u5F55\uFF1B\u8FD9\u4E0D\u4EE3\u8868\u5F00\u53D1\u8005\u4F53\u9A8C\u9A8C\u6536\u6216\u53D1\u5E03\u6210\u529F\u3002");
1221
+ const { root, source } = await runtimeCatalogSource(resolve5(cwd, directory ?? "."), { report: (message) => io.writeError(message), ...options });
1222
+ const catalog = await readRuntimeModelCatalog(root);
1223
+ if (json) io.write(JSON.stringify({ source, ...catalog }, null, 2));
1224
+ else {
1225
+ io.write(`${source === "project" ? "\u5DE5\u7A0B" : "npm \u6700\u65B0"} Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.models.length} \u4E2A\u6A21\u578B\uFF1A`);
1226
+ for (const id of catalog.models) io.write(`- ${id}`);
1227
+ 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");
1273
1228
  }
1274
- const report = await checkWidgetDelivery(root);
1275
- io.write(flags.has("--json") ? JSON.stringify(report, null, 2) : widgetDeliverySummary(report));
1276
- return { exitCode: report.status === "incomplete" ? 1 : 0 };
1229
+ return { exitCode: 0 };
1277
1230
  } catch (cause) {
1278
1231
  io.writeError(cause instanceof Error ? cause.message : String(cause));
1279
- return { exitCode: 1 };
1232
+ return { exitCode: 2 };
1280
1233
  }
1281
1234
  }
1282
1235
 
@@ -1284,72 +1237,11 @@ async function runWidgetsCommand(args, io, cwd) {
1284
1237
  import { lstat as lstat10 } from "node:fs/promises";
1285
1238
 
1286
1239
  // packages/cli-core/src/commands/datasets.ts
1287
- import { resolve as resolve7 } from "node:path";
1288
-
1289
- // packages/cli-core/src/config/runtime-catalog.ts
1290
- import { readFile as readFile4, realpath as realpath3 } from "node:fs/promises";
1291
- import { createRequire } from "node:module";
1292
1240
  import { resolve as resolve6 } from "node:path";
1293
- import { pathToFileURL } from "node:url";
1294
-
1295
- // packages/cli-core/src/config/runtime-dependency.ts
1296
- var BUDDY_RUNTIME_PACKAGE = "@my-life-buddies/buddy-runtime";
1297
- function runtimeDependencyVersion(pkg) {
1298
- if (typeof pkg !== "object" || pkg === null || !("dependencies" in pkg)) return void 0;
1299
- const dependencies2 = pkg.dependencies;
1300
- if (typeof dependencies2 !== "object" || dependencies2 === null || !(BUDDY_RUNTIME_PACKAGE in dependencies2)) return void 0;
1301
- const version = dependencies2[BUDDY_RUNTIME_PACKAGE];
1302
- return typeof version === "string" && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(version) ? version : void 0;
1303
- }
1304
-
1305
- // packages/cli-core/src/config/runtime-catalog.ts
1306
- async function readRuntimeDataCatalog(projectRoot) {
1307
- const packagePath = resolve6(projectRoot, "package.json");
1308
- const expected = runtimeDependencyVersion(JSON.parse(await readFile4(packagePath, "utf8")));
1309
- if (!expected) throw new Error(`package.json \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C`);
1310
- const projectRequire = createRequire(packagePath);
1311
- let runtimePath;
1312
- try {
1313
- const installedPath = await realpath3(resolve6(projectRoot, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"));
1314
- if (await realpath3(projectRequire.resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`)) !== installedPath) {
1315
- throw new Error("Runtime \u5FC5\u987B\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D");
1316
- }
1317
- const installed = JSON.parse(await readFile4(installedPath, "utf8"));
1318
- if (installed.version !== expected) throw new Error(`\u5DF2\u5B89\u88C5 ${installed.version}\uFF0C\u5DE5\u7A0B\u8981\u6C42 ${expected}`);
1319
- runtimePath = projectRequire.resolve(BUDDY_RUNTIME_PACKAGE);
1320
- } catch (cause) {
1321
- throw new Error(`\u5DE5\u7A0B\u7684 Runtime \u4F9D\u8D56\u672A\u6B63\u786E\u5B89\u88C5\uFF0C\u8BF7\u6309\u9501\u6587\u4EF6\u5B89\u88C5\u4F9D\u8D56\uFF1A${cause instanceof Error ? cause.message : String(cause)}`);
1322
- }
1323
- const runtime = await import(pathToFileURL(runtimePath).href);
1324
- const catalog = runtime.DATA_ACCESS_CAPABILITIES;
1325
- if (!Array.isArray(catalog)) {
1326
- throw new Error(`\u5DE5\u7A0B\u7684 Runtime ${expected} \u672A\u5BFC\u51FA DATA_ACCESS_CAPABILITIES\uFF0C\u8BF7\u4F7F\u7528\u5305\u542B\u6570\u636E\u76EE\u5F55\u7684\u65B0 Runtime \u5305\u3002`);
1327
- }
1328
- const seen = /* @__PURE__ */ new Set();
1329
- const datasets = catalog.map((value) => {
1330
- if (!value || typeof value !== "object") throw new Error("Runtime \u6570\u636E\u76EE\u5F55\u683C\u5F0F\u65E0\u6548");
1331
- const item = value;
1332
- if (typeof item.id !== "string" || !item.id.trim() || seen.has(item.id) || typeof item.title !== "string" || !item.title.trim() || typeof item.source !== "string" || !item.source.trim() || !Number.isSafeInteger(item.schemaVersion) || item.schemaVersion < 1) {
1333
- throw new Error("Runtime \u6570\u636E\u76EE\u5F55\u683C\u5F0F\u65E0\u6548\u6216\u5305\u542B\u91CD\u590D ID");
1334
- }
1335
- seen.add(item.id);
1336
- return Object.freeze({ id: item.id, title: item.title, source: item.source, schemaVersion: item.schemaVersion });
1337
- });
1338
- return Object.freeze({ runtimeVersion: expected, datasets: Object.freeze(datasets) });
1339
- }
1340
- async function validateRuntimeDatasets(projectRoot, requirements = []) {
1341
- const catalog = await readRuntimeDataCatalog(projectRoot);
1342
- const ids = new Set(catalog.datasets.map((item) => item.id));
1343
- for (const [index, item] of requirements.entries()) {
1344
- if (!ids.has(item.id)) throw new Error(`/datasets/${index}/id\uFF1A\u5DE5\u7A0B Runtime ${catalog.runtimeVersion} \u4E0D\u652F\u6301 ${item.id}`);
1345
- }
1346
- }
1347
-
1348
- // packages/cli-core/src/commands/datasets.ts
1349
1241
  var DATASETS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli datasets [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
1350
- \u8BFB\u53D6\u5DE5\u7A0B\u6240\u5B89\u88C5 Runtime \u7684 DATA_ACCESS_CAPABILITIES\uFF0C\u65E0\u9700\u767B\u5F55\u6216\u8BF7\u6C42\u5E73\u53F0\u76EE\u5F55\u3002
1351
- \u5148\u6309\u5DE5\u7A0B\u9501\u6587\u4EF6\u5B89\u88C5\u4F9D\u8D56\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`;
1352
- async function runDatasetsCommand(args, io, cwd) {
1242
+ \u5DE5\u7A0B\u5185\u8BFB\u53D6\u5DF2\u5B89\u88C5 Runtime \u7684 DATA_ACCESS_CAPABILITIES\uFF1B\u5DE5\u7A0B\u5916\u8054\u7F51\u8BFB\u53D6\u5E76\u7F13\u5B58\u516C\u5171 npm \u6700\u65B0 Runtime\u3002
1243
+ \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`;
1244
+ async function runDatasetsCommand(args, io, cwd, options = {}) {
1353
1245
  try {
1354
1246
  if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
1355
1247
  io.write(DATASETS_COMMAND_HELP);
@@ -1363,13 +1255,14 @@ async function runDatasetsCommand(args, io, cwd) {
1363
1255
  else throw new Error(`datasets \u53C2\u6570\u65E0\u6548\uFF1A${args[i]}
1364
1256
  ${DATASETS_COMMAND_HELP}`);
1365
1257
  }
1366
- const root = await requireBuddyProjectRoot(resolve7(cwd, directory ?? "."));
1258
+ const { root, source } = await runtimeCatalogSource(resolve6(cwd, directory ?? "."), { report: (message) => io.writeError(message), ...options });
1367
1259
  const catalog = await readRuntimeDataCatalog(root);
1368
- if (json) io.write(JSON.stringify(catalog, null, 2));
1260
+ if (json) io.write(JSON.stringify({ source, ...catalog }, null, 2));
1369
1261
  else {
1370
- io.write(`\u5DE5\u7A0B Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.datasets.length} \u9879\u6570\u636E\u80FD\u529B\uFF1A`);
1262
+ io.write(`${source === "project" ? "\u5DE5\u7A0B" : "npm \u6700\u65B0"} Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.datasets.length} \u9879\u6570\u636E\u80FD\u529B\uFF1A`);
1371
1263
  for (const item of catalog.datasets) io.write(`- ${item.id} \u2014 ${item.title}\uFF08${item.source}\uFF0CSchema ${item.schemaVersion}\uFF09`);
1372
1264
  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");
1265
+ if (source === "project") io.write(`\u66F4\u65B0 CLI \u4E0D\u4F1A\u66F4\u65B0\u5DE5\u7A0B Runtime\u3002\u5982\u9700\u5347\u7EA7\u5230\u516C\u5171 npm \u6700\u65B0\u7248\uFF0C\u5728\u5DE5\u7A0B\u6839\u76EE\u5F55\u8FD0\u884C\uFF1Anpm install --save-exact ${BUDDY_RUNTIME_PACKAGE}@latest --registry=https://registry.npmjs.org/ --@my-life-buddies:registry=https://registry.npmjs.org/`);
1373
1266
  }
1374
1267
  return { exitCode: 0 };
1375
1268
  } catch (cause) {
@@ -1379,12 +1272,12 @@ ${DATASETS_COMMAND_HELP}`);
1379
1272
  }
1380
1273
 
1381
1274
  // packages/cli-core/src/index.ts
1382
- import { join as join11, resolve as resolve15 } from "node:path";
1275
+ import { join as join12, resolve as resolve14 } from "node:path";
1383
1276
 
1384
1277
  // packages/cli-core/src/init/creator.ts
1385
1278
  import { randomUUID as randomUUID2 } from "node:crypto";
1386
- import { link as link2, lstat as lstat6, mkdir as mkdir4, readFile as readFile5, unlink as unlink3, writeFile as writeFile2 } from "node:fs/promises";
1387
- import { join as join5 } from "node:path";
1279
+ import { link as link2, lstat as lstat6, mkdir as mkdir4, readFile as readFile6, unlink as unlink3, writeFile as writeFile3 } from "node:fs/promises";
1280
+ import { join as join6 } from "node:path";
1388
1281
  import { fileURLToPath } from "node:url";
1389
1282
 
1390
1283
  // packages/cli-core/src/init/development-handoff.ts
@@ -1394,7 +1287,7 @@ var DEVELOPMENT_HANDOFF = `## \u5F00\u53D1\u5B8C\u6210\u540E\u4EA4\u7ED9\u5F00\u
1394
1287
  ${DEVELOPMENT_HANDOFF_SUMMARY}
1395
1288
 
1396
1289
  1. \u6839\u636E\u5DF2\u786E\u8BA4\u7684\u9700\u6C42\u5B8C\u6210 Agent / Prompt / Tool \u4E0E\u56DE\u5408\u94A9\u5B50\uFF1B\u6709 Booklet \u65F6\u4EE5\u5DF2\u786E\u8BA4\u624B\u518C\u4E3A\u51C6\u3002\u6A21\u677F\u751F\u6210\u4E0D\u7B49\u4E8E\u4E1A\u52A1\u5DF2\u5B9E\u73B0\u3002
1397
- 2. \u6709\u5DF2\u9A8C\u6536\u5C0F\u6302\u4EF6\u8BBE\u8BA1\u65F6\u6309\u5B9E\u73B0\u6307\u5F15\u6267\u884C \`widgets sync \u2192 widgets check \u2192 \u771F\u5B9E\u9884\u89C8\u5BF9\u7167 \u2192 widgets verify\`\uFF0C\u9010\u9879\u62A5\u544A\u72B6\u6001\uFF1B\u68C0\u67E5\u672A\u5B8C\u6210\u65F6\u4E0D\u80FD\u5C06\u7B80\u5316\u7248\u79F0\u4E3A\u5DF2\u6309\u8BBE\u8BA1\u4EA4\u4ED8\u3002\u505A\u57FA\u7840\u6280\u672F\u81EA\u6D4B\uFF1A\u68C0\u67E5\u914D\u7F6E\u3001\u4F9D\u8D56\u3001\u6784\u5EFA\u548C\u542F\u52A8\u5165\u53E3\uFF0C\u6267\u884C\u5DF2\u6709\u81EA\u52A8\u5316\u6D4B\u8BD5\u53CA\u660E\u786E\u4E1A\u52A1\u89C4\u5219\u3001\u5B89\u5168\u8FB9\u754C\u7684\u57FA\u7840\u6D4B\u8BD5\u3002\u4E0D\u8981\u628A\u6280\u672F\u68C0\u67E5\u901A\u8FC7\u8BF4\u6210\u4EA7\u54C1\u4F53\u9A8C\u5DF2\u9A8C\u6536\u3002
1290
+ 2. \u6709 Creator \u5C0F\u6302\u4EF6\u8BBE\u8BA1\u65F6\uFF0C\u6309\u5DF2\u786E\u8BA4\u7684\u9700\u6C42\u3001\u539F\u578B\u548C\u8BBE\u8BA1\u8BF4\u660E\u5B9E\u73B0\u9875\u9762\u3001\u6570\u636E\u7ED3\u6784\u4E0E\u4E1A\u52A1\u4EA4\u4E92\uFF0C\u5E76\u8BF4\u660E\u672A\u5B8C\u6210\u9879\u3002\u505A\u57FA\u7840\u6280\u672F\u81EA\u6D4B\uFF1A\u68C0\u67E5\u914D\u7F6E\u3001\u4F9D\u8D56\u3001\u6784\u5EFA\u548C\u542F\u52A8\u5165\u53E3\uFF0C\u6267\u884C\u5DF2\u6709\u81EA\u52A8\u5316\u6D4B\u8BD5\u53CA\u660E\u786E\u4E1A\u52A1\u89C4\u5219\u3001\u5B89\u5168\u8FB9\u754C\u7684\u57FA\u7840\u6D4B\u8BD5\u3002\u4E0D\u8981\u628A\u6280\u672F\u68C0\u67E5\u901A\u8FC7\u8BF4\u6210\u4EA7\u54C1\u4F53\u9A8C\u5DF2\u9A8C\u6536\u3002
1398
1291
  3. \u4F7F\u7528 \`buddy-cli preview\` \u6253\u5F00\u5F53\u524D\u5DE5\u7A0B\uFF0C\u5728\u9875\u9762\u542F\u52A8 DEV\uFF1B\u5DF2\u6709\u53EF\u7528\u9884\u89C8\u5219\u590D\u7528\uFF0C\u4E0D\u540C\u65F6\u518D\u542F\u52A8\u4E00\u5957 \`dev\` \u8FDB\u7A0B\u3002\u786E\u8BA4\u540D\u79F0\u3001DEV \u72B6\u6001\u548C\u79C1\u804A\u6D88\u606F\u5F80\u8FD4\uFF1B\u82E5\u7F3A\u5C11\u5F80\u8FD4\u8BC1\u636E\uFF0C\u53EA\u53D1\u9001\u4E00\u6761\u4E0D\u542B\u4E2A\u4EBA\u654F\u611F\u4FE1\u606F\u7684\u8054\u8C03\u6D88\u606F\uFF0C\u5DF2\u6709\u5F80\u8FD4\u8BC1\u636E\u65F6\u4E0D\u91CD\u590D\u53D1\u9001\u3002\u5931\u8D25\u5148\u5B9A\u4F4D\u6280\u672F\u95EE\u9898\uFF1B\u4ECD\u672A\u89E3\u51B3\u65F6\u8BF4\u660E\u963B\u585E\uFF0C\u4E0D\u628A Mock\u3001\u9875\u9762\u6253\u5F00\u6216\u8FDB\u7A0B\u542F\u52A8\u5F53\u6210\u94FE\u8DEF\u5DF2\u901A\u3002
1399
1292
  4. \u53EF\u4F53\u9A8C\u540E\u4FDD\u7559\u9884\u89C8\u548C DEV\uFF0C\u63D0\u4F9B\u5B9E\u9645\u6253\u5F00\u7684\u9875\u9762\u5730\u5740\uFF0C\u544A\u8BC9\u5F00\u53D1\u8005\u201C\u73B0\u5728\u53EF\u4EE5\u5F00\u59CB\u8BD5\u804A\u4E86\u201D\uFF0C\u8BF4\u660E\u5DF2\u9A8C\u8BC1\u8303\u56F4\u548C\u5DF2\u77E5\u9650\u5236\uFF0C\u7136\u540E\u7B49\u5F85\u53CD\u9988\u3002\u4E0B\u4E00\u8F6E\u7531\u5F00\u53D1\u8005\u4F53\u9A8C\u540E\u53CD\u9988\uFF0C\u518D\u6309\u53CD\u9988\u4FEE\u6539\u548C\u9A8C\u8BC1\u3002
1400
1293
 
@@ -1462,11 +1355,11 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
1462
1355
 
1463
1356
  \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
1464
1357
 
1465
- \u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002Runtime 0.12.0 \u542B 10 \u9879\uFF0CCLI \u4E0D\u590D\u5236\u679A\u4E3E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`buddy.agent.json.datasets\`\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0C\u7528\u9014\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u6700\u591A 200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
1358
+ \u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002Runtime 0.12.2 \u542B 10 \u9879\uFF0CCLI \u4E0D\u590D\u5236\u679A\u4E3E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`buddy.agent.json.datasets\`\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0C\u7528\u9014\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u6700\u591A 200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
1466
1359
 
1467
1360
  \`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
1468
1361
 
1469
- \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\u5DE5\u7A0B\u6A21\u677F\u5DF2\u9501\u5B9A npm Runtime 0.12.0\u3002
1362
+ \u6A21\u578B\u9700\u8981\u67E5\u6570\u636E\u65F6\uFF0C\u5728 \`src/buddy-options.mjs\` \u7684 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.data_access_query\`\uFF1B\u9700\u8981\u5411\u7528\u6237\u7533\u8BF7\u65F6\u52A0\u5165 \`conversation.tools.data_access_request\`\uFF0C\u4F4D\u7F6E\u3001\u65E5\u5386\u7684\u4E00\u6B21\u6027\u7ED3\u679C\u901A\u8FC7 \`data_access_read_result\` \u8BFB\u53D6\uFF0CHealthKit \u5219\u91CD\u65B0\u67E5\u8BE2 Dataset\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query/request/readResult\`\u3002\u65B0\u5EFA\u5DE5\u7A0B\u52A8\u6001\u9009\u62E9\u516C\u5171 npm latest \u5E76\u9501\u5B9A\u51C6\u786E\u7248\u672C\uFF1B\u8054\u7F51\u5931\u8D25\u65F6\u660E\u786E\u63D0\u793A\u4F7F\u7528\u968F CLI \u9644\u5E26\u7684 Runtime 0.12.2\u3002\u5DF2\u6709\u5DE5\u7A0B\u901A\u8FC7\u5305\u7BA1\u7406\u5668\u663E\u5F0F\u5347\u7EA7\u4F9D\u8D56\u3002
1470
1363
 
1471
1364
  \u5C0F\u6302\u4EF6\u7684\u6A21\u578B\u5DE5\u5177\u4E3A \`widget_create\`\u3001\`widget_read\`\uFF08\u6574\u4E2A\u5C0F\u6302\u4EF6\uFF09\u3001\`widget_read_module\`\uFF08\u4E00\u4E2A\u6A21\u5757\uFF09\u3001\`widget_rename\`\u3001\`widget_write_record\`\u3001\`widget_delete_record\`\u3001\`widget_delete\`\uFF08\u6574\u4E2A\u5C0F\u6302\u4EF6\u8FDE\u8BB0\u5F55\uFF09\u548C \`widget_send\`\uFF0C\u6309\u4E1A\u52A1\u9700\u8981\u6CE8\u518C\u5230 \`initialState.tools\`\u3002\u4FEE\u6539\u8BB0\u5F55\u7528 \`conversation.widget.writeRecord(id, input)\`\uFF1B\u5220\u4E00\u6761\u8BB0\u5F55\u7528 \`conversation.widget.deleteRecord(id, module, recordId)\`\uFF0C\u4E0D\u80FD\u7528\u5220\u9664\u6574\u4E2A\u5C0F\u6302\u4EF6\u7684 \`conversation.widget.delete(id)\` \u4EE3\u66FF\u3002\u4E24\u4E2A\u8BFB\u53D6\u5DE5\u5177\u53EF\u7528\u4E8E\u4E3B\u52A8\u56DE\u5408\uFF0C\u5176\u4F59\u516D\u4E2A\u5199\u5165\u5DE5\u5177\u7531 Runtime \u963B\u6B62\u5728\u4E3B\u52A8\u56DE\u5408\u6267\u884C\u3002
1472
1365
 
@@ -1482,17 +1375,13 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
1482
1375
 
1483
1376
  \u9047\u5230\u771F\u6B63\u7684\u963B\u585E\u5C31\u8BF4\u660E\u5177\u4F53\u7F3A\u53E3\u5E76\u7B49\u5F85\u7B54\u590D\uFF1B\u4E0D\u53D7\u5F71\u54CD\u7684\u5DF2\u6388\u6743\u5DE5\u4F5C\u53EF\u4EE5\u7EE7\u7EED\u3002\u65E0\u6CD5\u5B9E\u73B0\u7684\u8981\u6C42\u5982\u5B9E\u8BF4\u660E\uFF0C\u4E0D\u6697\u4E2D\u5220\u53BB\uFF0C\u4E5F\u4E0D\u4F2A\u9020\u5F00\u53D1\u8005\u540C\u610F\u964D\u7EA7\u3002\u7528\u6237\u53EA\u8981\u8BBE\u8BA1\u3001\u521D\u59CB\u5316\u6216\u5C40\u90E8\u4FEE\u6539\u65F6\u9075\u5B88\u8BE5\u8303\u56F4\uFF0C\u4E0D\u56E0\u624B\u518C\u5B58\u5728\u5C31\u81EA\u52A8\u6269\u5C55\u4EFB\u52A1\u3002
1484
1377
 
1485
- ### \u5C0F\u6302\u4EF6\u8BBE\u8BA1\u843D\u5730\u68C0\u67E5
1486
-
1487
- \u6709 Creator \u5C0F\u6302\u4EF6\u8BBE\u8BA1\u65F6\uFF0C\u5728\u5F00\u53D1\u5F00\u59CB\u524D\u6267\u884C \`buddy-cli widgets sync\`\u3002\u5B83\u4ECE\u5F53\u524D\u6709\u6548\u9A8C\u6536\u4EA4\u4ED8\u751F\u6210 \`widget-design.lock.json\` \u548C \`widget-implementation.json\`\uFF1B\u9010\u9879\u4FDD\u7559\u72EC\u7ACB\u7C7B\u578B ID\uFF0C\u4E0D\u5F97\u628A\u591A\u7C7B\u8BBE\u8BA1\u9759\u9ED8\u5408\u5E76\u6210\u4E00\u4E2A\u901A\u7528\u5DE5\u4F5C\u53F0\u3002\u540C\u6B65\u4E0D\u662F\u5B9E\u73B0\u5B8C\u6210\u3002
1378
+ ### \u6309\u8BBE\u8BA1\u5F00\u53D1\u5C0F\u6302\u4EF6
1488
1379
 
1489
- \u6309\u6620\u5C04\u5B9E\u73B0\u6BCF\u7C7B\u7684\u9875\u9762\u548C Schema\uFF0C\u586B\u5199\u5404\u8BBE\u8BA1\u5B57\u6BB5\u7684\u6570\u636E\u6A21\u5757\u7ED1\u5B9A\uFF0C\u4EE5\u53CA create/update/present \u5BF9\u5E94\u7684\u771F\u5B9E src/ \u4EE3\u7801\u8DEF\u5F84\u3002\u6CBF\u7528\u9A8C\u6536\u539F\u578B\u5E03\u5C40\u548C\u9605\u8BFB\u4EA4\u4E92\uFF0C\u793A\u4F8B\u6570\u636E\u53EA\u7528\u4E8E\u9694\u79BB\u7684\u9884\u89C8\u6838\u5BF9\uFF0C\u4E0D\u5199\u5165\u771F\u5B9E\u7528\u6237\u4F1A\u8BDD\u3002
1380
+ \u6709 Creator \u8BBE\u8BA1\u4EA7\u7269\u65F6\uFF0C\u8BFB\u53D6\u5DF2\u786E\u8BA4\u7684\u9700\u6C42\u624B\u518C\u3001\u5C0F\u6302\u4EF6\u6E05\u5355\u3001\u539F\u578B\u548C\u8BBE\u8BA1\u8BF4\u660E\uFF0C\u6309\u7528\u9014\u5B9E\u73B0\u5404\u7C7B\u5C0F\u6302\u4EF6\u3002\u4FDD\u7559\u8BBE\u8BA1\u8981\u6C42\u7684\u5C55\u793A\u5185\u5BB9\u3001\u5E03\u5C40\u3001\u4EA4\u4E92\u548C\u51FA\u73B0\u65F6\u673A\uFF1B\u65E0\u6CD5\u5B8C\u6210\u65F6\u660E\u786E\u8BF4\u660E\u7F3A\u53E3\uFF0C\u4E0D\u9759\u9ED8\u7701\u7565\u6216\u5408\u5E76\u8BBE\u8BA1\u3002
1490
1381
 
1491
- \u6267\u884C \`buddy-cli widgets check --json\`\uFF0C\u5148\u4FEE\u590D\u7F3A\u5931\u7C7B\u578B\u3001\u5B57\u6BB5\u3001\u4EE3\u7801\u8DEF\u5F84\u6216\u8FC7\u671F\u539F\u578B\u3002DEV \u5141\u8BB8\u7EE7\u7EED\u8C03\u8BD5\uFF0C\u9884\u89C8\u9875\u9762\u4F1A\u5355\u72EC\u5C55\u793A\u672A\u5B8C\u6210\u9879\uFF1B\u4E0A\u4F20\u6210\u529F\u3001DEV \u5728\u7EBF\u5747\u4E0D\u80FD\u4EE3\u66FF\u8FD9\u4EFD\u68C0\u67E5\u3002
1382
+ \u5728\u5DE5\u7A0B\u7684 \`widgets/<type-id>/\` \u4E2D\u7F16\u5199 \`index.html\` \u548C \`schema.json\`\uFF0C\u5728\u4E1A\u52A1\u4EE3\u7801\u4E2D\u63A5\u5165\u521B\u5EFA\u3001\u8BFB\u53D6\u3001\u66F4\u65B0\u548C\u53D1\u9001\u80FD\u529B\u3002\u5F00\u53D1\u8005\u5728 \`buddy-cli preview\` \u4E2D\u67E5\u770B\u771F\u5B9E\u9875\u9762\u548C\u4EA4\u4E92\u6548\u679C\uFF0C\u4FEE\u6539\u540E\u91CD\u542F DEV\u3002\u51C6\u5907\u4E0A\u4F20\u65F6\u4F7F\u7528 \`buddy-cli push\`\uFF0C\u9875\u9762\u548C\u6570\u636E\u5B9A\u4E49\u968F\u5DE5\u7A0B\u6253\u5305\u3002
1492
1383
 
1493
- \u5B8C\u6210\u5B9E\u9645\u9875\u9762\u4E0E\u9A8C\u6536\u539F\u578B\u7684\u9996\u6B21/\u8865\u5145/\u66F4\u65B0\u4E09\u6001\u5BF9\u7167\uFF0C\u8BB0\u5F55 visual\u3001interactions\u3001data-update\u3001trigger\u3001read-only \u4E94\u9879\u5B9E\u9645\u89C2\u5BDF\uFF1B\u4F7F\u7528\u9694\u79BB\u6D4B\u8BD5\u6570\u636E\u9A8C\u8BC1\u672A\u89E6\u53D1\u65F6\u65E0\u5165\u53E3\u3001\u521B\u5EFA\u540E\u663E\u793A\u3001\u66F4\u65B0\u6CBF\u7528\u5B9E\u4F8B\u4E0E\u6458\u8981\u4E00\u81F4\u3002\u4FDD\u7559\u622A\u56FE\u6216\u53EF\u590D\u6838\u6D4B\u8BD5\u8F93\u51FA\u5230\u9879\u76EE .buddy/ \u4E0B\u3002\u8BB0\u5F55\u91CC\u586B\u5199 check \u8F93\u51FA\u7684\u5F53\u524D implementationDigest\u3001\u65E0\u51ED\u636E previewUrl\u3001observedAt\u3001reviewer\u3001states\uFF08\u5404\u6001 notes/artifact\uFF09\u548C checks\uFF08\u4E94\u9879\u8BF4\u660E\uFF09\uFF0C\u7136\u540E\u6267\u884C \`buddy-cli widgets verify --id <\u8BBE\u8BA1ID> --evidence <\u9879\u76EE\u5185\u8BB0\u5F55.json>\`\u3002\u547D\u4EE4\u8BA1\u7B97\u8BC1\u636E\u6458\u8981\u5E76\u7ED1\u5B9A\u5F53\u524D\u4EE3\u7801\uFF1B\u5B83\u4FDD\u5B58\u6838\u5BF9\u8005\u7684\u89C2\u5BDF\uFF0C\u4E0D\u81EA\u52A8\u8BC1\u660E\u89C6\u89C9\u76F8\u540C\uFF0C\u4E5F\u4E0D\u65B0\u589E\u4E00\u8F6E\u7528\u6237\u5BA1\u6279\u3002
1494
-
1495
- \u6240\u6709\u7C7B\u578B\u7ED3\u6784\u548C\u6838\u5BF9\u8BB0\u5F55\u9F50\u5168\u540E\u624D\u79F0\u201C\u5C0F\u6302\u4EF6\u5F00\u53D1\u6838\u5BF9\u5B8C\u6210\u201D\u3002\u4EE3\u7801\u3001\u9875\u9762\u3001\u4F9D\u8D56\u3001\u6570\u636E\u7ED1\u5B9A\u6216\u8BBE\u8BA1\u7248\u672C\u53D8\u5316\u4F1A\u8BA9\u65E7\u8BB0\u5F55\u5931\u6548\uFF0C\u5E94\u9488\u5BF9\u53D8\u5316\u91CD\u65B0\u6838\u5BF9\u3002\u6CA1\u6709\u5B8C\u6210\u5C31\u660E\u786E\u5217\u51FA\u7F3A\u9879\u3002push \u4F1A\u5728\u4E0A\u4F20\u524D\u62E6\u622A\u4E0D\u5B8C\u6574\u4EA4\u4ED8\uFF0C\u4F46\u4E0D\u4F1A\u66FF\u5F00\u53D1\u8005\u53D1\u8D77\u63D0\u5BA1\u3002\u76F4\u63A5\u5F00\u53D1\u4E14\u65E0 Creator \u8BBE\u8BA1\u7684\u9879\u76EE\u6CBF\u7528\u539F\u6D41\u7A0B\uFF0C\u68C0\u67E5\u7ED3\u679C\u660E\u786E\u4E3A\u201C\u672A\u914D\u7F6E\u8BBE\u8BA1\u6838\u5BF9\u201D\uFF0C\u4E0D\u5192\u5145\u901A\u8FC7\u3002
1384
+ \u6309\u9700\u6C42\u5B8C\u6210\u57FA\u7840\u6280\u672F\u81EA\u6D4B\uFF0C\u5411\u5F00\u53D1\u8005\u8BF4\u660E\u5DF2\u5B9E\u73B0\u5185\u5BB9\u548C\u4ECD\u5B58\u5728\u7684\u95EE\u9898\uFF0C\u518D\u4EA4\u7ED9\u5F00\u53D1\u8005\u4F53\u9A8C\u3002\u8BBE\u8BA1\u8BF4\u660E\u4F5C\u4E3A\u5F00\u53D1\u53C2\u8003\uFF0CCLI \u4E0D\u8981\u6C42\u989D\u5916\u586B\u5199\u8BBE\u8BA1\u6620\u5C04\u6216\u63D0\u4EA4\u9884\u89C8\u6838\u5BF9\u8BB0\u5F55\u3002
1496
1385
 
1497
1386
  ### \u6838\u5BF9\u5B9E\u73B0\uFF0C\u518D\u4EA4\u7ED9\u5F00\u53D1\u8005\u4F53\u9A8C
1498
1387
 
@@ -1563,11 +1452,11 @@ async function safeRead(path) {
1563
1452
  if (!entry.isFile() || entry.size > MAX_LOCAL_FILE_BYTES) {
1564
1453
  throw new CreatorPreparationError(`\u521B\u4F5C\u6587\u4EF6\u4E0D\u662F\u666E\u901A\u6587\u4EF6\u6216\u8D85\u51FA\u5927\u5C0F\u9650\u5236\uFF1A${path}`);
1565
1454
  }
1566
- return readFile5(path);
1455
+ return readFile6(path);
1567
1456
  }
1568
1457
  async function writeOnce(path, bytes) {
1569
1458
  const temporary = `${path}.${randomUUID2()}.tmp`;
1570
- await writeFile2(temporary, bytes, { flag: "wx", mode: 384 });
1459
+ await writeFile3(temporary, bytes, { flag: "wx", mode: 384 });
1571
1460
  try {
1572
1461
  await link2(temporary, path).catch((cause) => {
1573
1462
  if (cause.code !== "EEXIST") throw cause;
@@ -1578,17 +1467,17 @@ async function writeOnce(path, bytes) {
1578
1467
  }
1579
1468
  async function bundledSkill(root) {
1580
1469
  for (const path of REQUIRED) {
1581
- if (!(await state(join5(root, path)))?.isFile()) {
1470
+ if (!(await state(join6(root, path)))?.isFile()) {
1582
1471
  throw new CreatorPreparationError(`CLI \u5185\u7F6E Creator Skill \u4E0D\u5B8C\u6574\uFF0C\u8BF7\u91CD\u65B0\u5B89\u88C5 CLI\uFF08\u7F3A\u5C11 ${path}\uFF09\u3002\u4E0D\u4F1A\u5C1D\u8BD5\u5728\u7EBF\u4E0B\u8F7D\u6216\u8986\u76D6\u9879\u76EE\u8D44\u6599\u3002`);
1583
1472
  }
1584
1473
  }
1585
1474
  return root;
1586
1475
  }
1587
1476
  function handoffMarkdown(context, skillRoot, session, workspacePath) {
1588
- const contextPath = join5(context.projectRoot, ".buddy", "creator", "initial-context.json");
1477
+ const contextPath = join6(context.projectRoot, ".buddy", "creator", "initial-context.json");
1589
1478
  const openArgs = [
1590
1479
  "-B",
1591
- join5(skillRoot, "scripts/buddy.py"),
1480
+ join6(skillRoot, "scripts/buddy.py"),
1592
1481
  "open",
1593
1482
  "--workspace",
1594
1483
  workspacePath,
@@ -1618,7 +1507,7 @@ function handoffMarkdown(context, skillRoot, session, workspacePath) {
1618
1507
 
1619
1508
  ## \u73B0\u5728\u7531 Coding Agent \u6267\u884C
1620
1509
 
1621
- 1. \u5B8C\u6574\u8BFB\u53D6 ${JSON.stringify(join5(skillRoot, "SKILL.md"))} \u53CA\u5176\u6307\u5B9A\u7684 references\u3002\u4FDD\u7559\u539F\u6709\u56DB\u9636\u6BB5\u89C4\u5219\uFF0C\u7531\u5F53\u524D\u4E3B\u5BF9\u8BDD\u5B8C\u6210\u91C7\u8BBF\uFF1B\u65E0\u9700\u53E6\u8D77 Sub-agent \u6216\u8FD0\u884C\u91C7\u8BBF\u6A21\u578B\u670D\u52A1\u3002
1510
+ 1. \u5B8C\u6574\u8BFB\u53D6 ${JSON.stringify(join6(skillRoot, "SKILL.md"))} \u53CA\u5176\u6307\u5B9A\u7684 references\u3002\u4FDD\u7559\u539F\u6709\u56DB\u9636\u6BB5\u89C4\u5219\uFF0C\u7531\u5F53\u524D\u4E3B\u5BF9\u8BDD\u5B8C\u6210\u91C7\u8BBF\uFF1B\u65E0\u9700\u53E6\u8D77 Sub-agent \u6216\u8FD0\u884C\u91C7\u8BBF\u6A21\u578B\u670D\u52A1\u3002
1622
1511
  2. \u67E5\u627E\u5BBF\u4E3B\u6216\u7CFB\u7EDF\u5B9E\u9645\u53EF\u7528\u7684 Python 3.9+\uFF0C\u68C0\u67E5\u7248\u672C\uFF0C\u4FDD\u5B58\u5176\u7EDD\u5BF9\u8DEF\u5F84\u3002\u4E0D\u8981\u5199\u6B7B\u672C\u673A\u8DEF\u5F84\uFF0C\u4E0D\u5B89\u88C5 pip/npm \u4F9D\u8D56\u3002\u6CA1\u6709 Python \u65F6\u62A5\u544A\u7F3A\u53E3\uFF0C\u4FDD\u7559\u672C\u5730\u9879\u76EE\u3002\u6240\u6709 Python \u8C03\u7528\u5747\u52A0 -B\uFF0C\u5E76\u8BBE\u7F6E\u8FDB\u7A0B\u73AF\u5883\u53D8\u91CF PYTHONDONTWRITEBYTECODE=1\uFF08\u7531\u9884\u89C8\u5B50\u8FDB\u7A0B\u7EE7\u627F\uFF09\uFF0C\u907F\u514D\u5411 CLI \u5B89\u88C5\u76EE\u5F55\u5199\u5165\u5B57\u8282\u7801\u7F13\u5B58\u3002
1623
1512
  3. \u4F7F\u7528\u5DE5\u5177\u4F20\u9012\u72EC\u7ACB\u53C2\u6570\uFF0C\u4E0D\u62FC\u63A5 shell \u5B57\u7B26\u4E32\u3002\u5DE5\u4F5C\u76EE\u5F55\u4E3A ${JSON.stringify(context.projectRoot)}\uFF1B\u4EE5\u5B9E\u9645 Python \u8DEF\u5F84\u4E3A executable\uFF0C\u9996\u6B21\u6253\u5F00\u7684 argv \u5982\u4E0B\uFF1A
1624
1513
 
@@ -1655,11 +1544,11 @@ ${DEVELOPMENT_HANDOFF}
1655
1544
  `;
1656
1545
  }
1657
1546
  async function prepareCreatorSkill(context, io, options = {}) {
1658
- const root = join5(context.projectRoot, ".buddy", "creator");
1547
+ const root = join6(context.projectRoot, ".buddy", "creator");
1659
1548
  try {
1660
- await safeDirectory(join5(context.projectRoot, ".buddy"));
1549
+ await safeDirectory(join6(context.projectRoot, ".buddy"));
1661
1550
  await safeDirectory(root);
1662
- const sessionPath = join5(root, "session.json");
1551
+ const sessionPath = join6(root, "session.json");
1663
1552
  await writeOnce(sessionPath, JSON.stringify({
1664
1553
  schemaVersion: 1,
1665
1554
  platformBuddyId: context.buddyId,
@@ -1671,11 +1560,11 @@ async function prepareCreatorSkill(context, io, options = {}) {
1671
1560
  }
1672
1561
  options.signal?.throwIfAborted();
1673
1562
  const skillRoot = await bundledSkill(options.bundledSkillRoot ?? BUNDLED_CREATOR_SKILL_ROOT);
1674
- await safeDirectory(join5(root, "workspaces"));
1675
- const workspacePath = join5(root, "workspaces", session.creationKey);
1563
+ await safeDirectory(join6(root, "workspaces"));
1564
+ const workspacePath = join6(root, "workspaces", session.creationKey);
1676
1565
  const workspace = await state(workspacePath);
1677
1566
  if (workspace && !workspace.isDirectory()) throw new CreatorPreparationError("\u5DF2\u6709\u521B\u4F5C\u5DE5\u4F5C\u533A\u4E0D\u662F\u666E\u901A\u76EE\u5F55\u3002");
1678
- const contextPath = join5(root, "initial-context.json");
1567
+ const contextPath = join6(root, "initial-context.json");
1679
1568
  await writeOnce(contextPath, JSON.stringify({
1680
1569
  source: "platform_meta",
1681
1570
  name: context.appName,
@@ -1691,7 +1580,7 @@ async function prepareCreatorSkill(context, io, options = {}) {
1691
1580
  } catch {
1692
1581
  throw new CreatorPreparationError(`\u5DF2\u6709\u521D\u59CB\u80CC\u666F\u65E0\u6548\uFF0C\u5DF2\u4FDD\u7559\u539F\u6587\u4EF6\uFF0C\u8BF7\u68C0\u67E5\uFF1A${contextPath}`);
1693
1582
  }
1694
- const handoffPath = join5(root, "HANDOFF.md");
1583
+ const handoffPath = join6(root, "HANDOFF.md");
1695
1584
  const handoff = handoffMarkdown({
1696
1585
  ...context,
1697
1586
  appName: initial.name,
@@ -1702,11 +1591,11 @@ async function prepareCreatorSkill(context, io, options = {}) {
1702
1591
  if ((await safeRead(handoffPath))?.toString("utf8") !== handoff) {
1703
1592
  throw new CreatorPreparationError(`\u5DF2\u6709\u63A5\u7EED\u8BF4\u660E\u88AB\u4FEE\u6539\u6216\u9879\u76EE\u8DEF\u5F84\u5DF2\u53D8\u5316\uFF0C\u5DF2\u4FDD\u7559\u539F\u6587\u4EF6\u3002\u8BF7\u5907\u4EFD\u79FB\u8D70\u8BE5\u8BF4\u660E\u540E\u91CD\u8BD5\uFF1A${handoffPath}`);
1704
1593
  }
1705
- io.write(`\u4F7F\u7528 CLI \u5185\u7F6E Creator Skill\uFF0C\u65E0\u9700\u989D\u5916\u4E0B\u8F7D\uFF1A${join5(skillRoot, "SKILL.md")}`);
1594
+ io.write(`\u4F7F\u7528 CLI \u5185\u7F6E Creator Skill\uFF0C\u65E0\u9700\u989D\u5916\u4E0B\u8F7D\uFF1A${join6(skillRoot, "SKILL.md")}`);
1706
1595
  io.write(`\u4E0B\u4E00\u6B65\u4EA4\u7ED9 Codex / Claude Code \u7B49 Coding Agent\uFF1A\u8BF7\u8BFB\u53D6 ${JSON.stringify(handoffPath)}\uFF0C\u6309\u5F53\u524D\u9636\u6BB5\u63A5\u7EED\uFF1BCreator \u5B8C\u6210\u540E\u8FD4\u56DE CLI \u5F00\u53D1\u6D41\u7A0B\u3002`);
1707
1596
  io.write(DEVELOPMENT_HANDOFF_SUMMARY);
1708
1597
  io.write("\u672C\u547D\u4EE4\u53EA\u8D1F\u8D23\u8EAB\u4EFD\u767B\u8BB0\u548C Skill \u51C6\u5907\uFF0C\u4E0D\u4EE3\u8868\u91C7\u8BBF\u3001Booklet \u6216 Agent \u5DF2\u5B8C\u6210\u3002\u8BF7\u6309\u5DF2\u6709\u4F5C\u54C1\u8FDB\u5EA6\u63A5\u7EED\uFF0C\u56DB\u518C\u53CA\u5C0F\u6302\u4EF6\u8BBE\u8BA1\u9A8C\u6536\u3001\u4EA4\u4ED8\u6821\u9A8C\u5B8C\u6210\u540E\u81EA\u52A8\u8FDB\u5165\u5B98\u65B9 Runtime \u5F00\u53D1\uFF1B\u91CD\u590D create \u4F1A\u590D\u7528\u540C\u4E00\u4F5C\u54C1\u3002");
1709
- return { exitCode: 0, creator: { skillPath: join5(skillRoot, "SKILL.md"), handoffPath, workspacePath } };
1598
+ return { exitCode: 0, creator: { skillPath: join6(skillRoot, "SKILL.md"), handoffPath, workspacePath } };
1710
1599
  } catch (cause) {
1711
1600
  const message = cause instanceof CreatorPreparationError ? cause.message : "\u5185\u7F6E\u8D44\u6E90\u8BFB\u53D6\u6216\u672C\u5730\u5199\u5165\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 CLI \u5B89\u88C5\u548C\u76EE\u5F55\u6743\u9650\u3002";
1712
1601
  io.writeError(`Creator Skill \u51C6\u5907\u5931\u8D25\uFF1A${message}`);
@@ -1766,7 +1655,7 @@ function validateBuddyMetaUpdate(meta2) {
1766
1655
  }
1767
1656
 
1768
1657
  // packages/cli-core/src/commands/dev.ts
1769
- import { resolve as resolve11 } from "node:path";
1658
+ import { resolve as resolve10 } from "node:path";
1770
1659
 
1771
1660
  // packages/cli-core/src/platform-url.ts
1772
1661
  var DEFAULT_MLB_TEST_URL = "http://47.116.168.81:8788";
@@ -1827,7 +1716,7 @@ function safeCredential(value, name) {
1827
1716
  function endpoint(baseUrl, path) {
1828
1717
  return new URL(path.replace(/^\//u, ""), baseUrl);
1829
1718
  }
1830
- function object2(value) {
1719
+ function object(value) {
1831
1720
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
1832
1721
  }
1833
1722
  async function responseJson(response) {
@@ -1869,7 +1758,7 @@ async function responseJson(response) {
1869
1758
  }
1870
1759
  }
1871
1760
  function safeServerError(value, fallback) {
1872
- const candidate = object2(value)?.error;
1761
+ const candidate = object(value)?.error;
1873
1762
  if (typeof candidate !== "string" || !candidate.trim()) return fallback;
1874
1763
  return candidate.slice(0, 1024).replace(/[\u0000-\u001f\u007f]/gu, " ");
1875
1764
  }
@@ -1950,7 +1839,7 @@ var MlbDevRegistrationClient = class {
1950
1839
  message: "buddy.agent.json \u4E2D\u7684 buddyId \u65E0\u6548\u3002"
1951
1840
  });
1952
1841
  }
1953
- const body = object2(await this.#request(
1842
+ const body = object(await this.#request(
1954
1843
  `/cli/buddies/${encodeURIComponent(request.devAgentId)}`,
1955
1844
  {
1956
1845
  method: "GET",
@@ -1971,7 +1860,7 @@ var MlbDevRegistrationClient = class {
1971
1860
  });
1972
1861
  }
1973
1862
  async listOnline(options) {
1974
- const body = object2(await this.#request("/cli/fleet", {
1863
+ const body = object(await this.#request("/cli/fleet", {
1975
1864
  method: "GET",
1976
1865
  signal: options.signal
1977
1866
  }));
@@ -2063,16 +1952,16 @@ function buildAgentEnvironment(options) {
2063
1952
  }
2064
1953
 
2065
1954
  // packages/cli-core/src/dev/orchestrator.ts
2066
- import { createHash as createHash3 } from "node:crypto";
2067
- import { readFile as readFile7 } from "node:fs/promises";
2068
- import { join as join7, resolve as resolve9 } from "node:path";
1955
+ import { createHash as createHash2 } from "node:crypto";
1956
+ import { readFile as readFile8 } from "node:fs/promises";
1957
+ import { join as join8, resolve as resolve8 } from "node:path";
2069
1958
 
2070
1959
  // packages/cli-core/src/dev/launch.ts
2071
1960
  import { lstatSync, readFileSync } from "node:fs";
2072
1961
  import { createRequire as createRequire2 } from "node:module";
2073
- import { dirname as dirname2, resolve as resolve8 } from "node:path";
1962
+ import { dirname as dirname2, resolve as resolve7 } from "node:path";
2074
1963
  async function officialAgentLaunchPlan(input) {
2075
- const entry = resolve8(input.projectRoot, BUDDY_PLATFORM_START_ENTRY);
1964
+ const entry = resolve7(input.projectRoot, BUDDY_PLATFORM_START_ENTRY);
2076
1965
  for (const [filename, kind] of [
2077
1966
  [dirname2(BUDDY_PLATFORM_FACTORY_ENTRY), "directory"],
2078
1967
  [BUDDY_PLATFORM_START_ENTRY, "file"],
@@ -2080,7 +1969,7 @@ async function officialAgentLaunchPlan(input) {
2080
1969
  [BUDDY_PLATFORM_PACKAGE_JSON, "file"]
2081
1970
  ]) {
2082
1971
  try {
2083
- const entry2 = lstatSync(resolve8(input.projectRoot, filename));
1972
+ const entry2 = lstatSync(resolve7(input.projectRoot, filename));
2084
1973
  if (!(kind === "directory" ? entry2.isDirectory() : entry2.isFile())) {
2085
1974
  throw new Error(`${filename} must be a regular ${kind}`);
2086
1975
  }
@@ -2093,7 +1982,7 @@ async function officialAgentLaunchPlan(input) {
2093
1982
  });
2094
1983
  }
2095
1984
  }
2096
- const packagePath = resolve8(input.projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
1985
+ const packagePath = resolve7(input.projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
2097
1986
  try {
2098
1987
  const expected = runtimeDependencyVersion(JSON.parse(readFileSync(packagePath, "utf8")));
2099
1988
  if (!expected) throw new Error(`package.json \u7684 dependencies \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C`);
@@ -2101,6 +1990,7 @@ async function officialAgentLaunchPlan(input) {
2101
1990
  const installed = JSON.parse(readFileSync(runtimePath, "utf8")).version;
2102
1991
  if (installed !== expected) throw new Error(`Runtime \u5DF2\u5B89\u88C5 ${installed}\uFF0C\u5DE5\u7A0B\u8981\u6C42 ${expected}`);
2103
1992
  await validateRuntimeDatasets(input.projectRoot, input.datasets);
1993
+ await validateRuntimeModel(input.projectRoot, input.model);
2104
1994
  } catch (cause) {
2105
1995
  throw new BuddyDevError({
2106
1996
  code: "DEV_CONFIG_INVALID",
@@ -2143,16 +2033,16 @@ var NodeAgentProcessLauncher = class {
2143
2033
  }
2144
2034
  let hasExited = false;
2145
2035
  let spawned = false;
2146
- const exit = new Promise((resolve16) => {
2036
+ const exit = new Promise((resolve15) => {
2147
2037
  child.once("error", (error2) => {
2148
2038
  if (!spawned) {
2149
2039
  hasExited = true;
2150
- resolve16({ code: null, signal: null, error: error2 });
2040
+ resolve15({ code: null, signal: null, error: error2 });
2151
2041
  }
2152
2042
  });
2153
2043
  child.once("exit", (code2, signal) => {
2154
2044
  hasExited = true;
2155
- resolve16({ code: code2, signal });
2045
+ resolve15({ code: code2, signal });
2156
2046
  });
2157
2047
  });
2158
2048
  child.stdout?.on("data", (chunk) => {
@@ -2168,11 +2058,11 @@ var NodeAgentProcessLauncher = class {
2168
2058
  }
2169
2059
  });
2170
2060
  try {
2171
- await new Promise((resolve16, reject) => {
2061
+ await new Promise((resolve15, reject) => {
2172
2062
  const onSpawn = () => {
2173
2063
  spawned = true;
2174
2064
  child.off("error", onError);
2175
- resolve16();
2065
+ resolve15();
2176
2066
  };
2177
2067
  const onError = (error2) => {
2178
2068
  child.off("spawn", onSpawn);
@@ -2211,11 +2101,11 @@ var NodeAgentProcessLauncher = class {
2211
2101
  };
2212
2102
  function waitForExit(process2, timeoutMs) {
2213
2103
  if (process2.hasExited()) return Promise.resolve(true);
2214
- return new Promise((resolve16) => {
2215
- const timeout = setTimeout(() => resolve16(false), timeoutMs);
2104
+ return new Promise((resolve15) => {
2105
+ const timeout = setTimeout(() => resolve15(false), timeoutMs);
2216
2106
  process2.exit.then(() => {
2217
2107
  clearTimeout(timeout);
2218
- resolve16(true);
2108
+ resolve15(true);
2219
2109
  });
2220
2110
  });
2221
2111
  }
@@ -2298,7 +2188,7 @@ async function waitForGroupExit(pid, isGroupAlive, timeoutMs) {
2298
2188
  while (isGroupAlive(pid)) {
2299
2189
  const remaining = deadline - Date.now();
2300
2190
  if (remaining <= 0) return false;
2301
- await new Promise((resolve16) => setTimeout(resolve16, Math.min(25, remaining)));
2191
+ await new Promise((resolve15) => setTimeout(resolve15, Math.min(25, remaining)));
2302
2192
  }
2303
2193
  return true;
2304
2194
  }
@@ -2312,10 +2202,10 @@ function processTreeControllerFor(platform) {
2312
2202
  }
2313
2203
 
2314
2204
  // packages/cli-core/src/dev/instance-lock.ts
2315
- import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
2316
- import { mkdir as mkdir5, readFile as readFile6, readdir as readdir3, rename as rename3, rmdir as rmdir2, unlink as unlink4, writeFile as writeFile3 } from "node:fs/promises";
2317
- import { homedir } from "node:os";
2318
- import { join as join6 } from "node:path";
2205
+ import { createHash, randomUUID as randomUUID3 } from "node:crypto";
2206
+ import { mkdir as mkdir5, readFile as readFile7, readdir as readdir2, rename as rename3, rmdir as rmdir2, unlink as unlink4, writeFile as writeFile4 } from "node:fs/promises";
2207
+ import { homedir as homedir2 } from "node:os";
2208
+ import { join as join7 } from "node:path";
2319
2209
  function alreadyRunningError() {
2320
2210
  const message = "\u8FD9\u4E2A\u642D\u5B50\u5DF2\u6709 DEV \u5B9E\u4F8B\u5728\u8FD0\u884C\u3002\u8BF7\u5148\u5728\u539F\u9884\u89C8\u9875\u70B9\u51FB\u300C\u505C\u6B62 DEV\u300D\uFF0C\u6216\u5728\u8FD0\u884C dev \u7684\u7EC8\u7AEF\u6309 Ctrl+C\uFF0C\u518D\u542F\u52A8\u3002";
2321
2211
  return Object.assign(new BuddyDevError({ code: "DEV_ALREADY_RUNNING", phase: "launch", message }), { publicMessage: message });
@@ -2335,16 +2225,16 @@ function code(error2) {
2335
2225
  return error2?.code;
2336
2226
  }
2337
2227
  async function acquireDevInstanceLock(options) {
2338
- const root = options.directory ?? join6(homedir(), ".buddy", "dev-locks");
2339
- const key = createHash2("sha256").update(`${new URL(options.gatewayUrl).origin}
2228
+ const root = options.directory ?? join7(homedir2(), ".buddy", "dev-locks");
2229
+ const key = createHash("sha256").update(`${new URL(options.gatewayUrl).origin}
2340
2230
  ${options.devAgentId}`).digest("hex");
2341
- const path = join6(root, key);
2231
+ const path = join7(root, key);
2342
2232
  const ownerName = `owner-${randomUUID3()}.json`;
2343
- const candidate = join6(root, `.pending-${randomUUID3()}`);
2233
+ const candidate = join7(root, `.pending-${randomUUID3()}`);
2344
2234
  const owner = { pid: process.pid };
2345
2235
  await mkdir5(root, { recursive: true, mode: 448 });
2346
2236
  await mkdir5(candidate, { mode: 448 });
2347
- await writeFile3(join6(candidate, ownerName), JSON.stringify(owner), { mode: 384, flag: "wx" });
2237
+ await writeFile4(join7(candidate, ownerName), JSON.stringify(owner), { mode: 384, flag: "wx" });
2348
2238
  try {
2349
2239
  for (let attempt = 0; ; attempt++) {
2350
2240
  try {
@@ -2356,17 +2246,17 @@ ${options.devAgentId}`).digest("hex");
2356
2246
  }
2357
2247
  let names;
2358
2248
  try {
2359
- names = await readdir3(path);
2249
+ names = await readdir2(path);
2360
2250
  } catch (error2) {
2361
2251
  if (code(error2) === "ENOENT") continue;
2362
2252
  throw error2;
2363
2253
  }
2364
2254
  if (names.length === 0) continue;
2365
2255
  if (names.length !== 1 || !/^owner-[a-f0-9-]+\.json$/u.test(names[0])) throw alreadyRunningError();
2366
- const previousPath = join6(path, names[0]);
2256
+ const previousPath = join7(path, names[0]);
2367
2257
  let previous;
2368
2258
  try {
2369
- previous = JSON.parse(await readFile6(previousPath, "utf8"));
2259
+ previous = JSON.parse(await readFile7(previousPath, "utf8"));
2370
2260
  } catch (error2) {
2371
2261
  if (code(error2) === "ENOENT") continue;
2372
2262
  throw alreadyRunningError();
@@ -2383,17 +2273,17 @@ ${options.devAgentId}`).digest("hex");
2383
2273
  });
2384
2274
  }
2385
2275
  } finally {
2386
- await unlink4(join6(candidate, ownerName)).catch(() => void 0);
2276
+ await unlink4(join7(candidate, ownerName)).catch(() => void 0);
2387
2277
  await rmdir2(candidate).catch(() => void 0);
2388
2278
  }
2389
2279
  let released = false;
2390
2280
  return {
2391
2281
  async attachRuntime(pid) {
2392
2282
  if (!validPid(pid)) throw new TypeError("Runtime PID is invalid");
2393
- const temporary = join6(root, `.update-${randomUUID3()}`);
2283
+ const temporary = join7(root, `.update-${randomUUID3()}`);
2394
2284
  try {
2395
- await writeFile3(temporary, JSON.stringify({ ...owner, runtimePid: pid }), { mode: 384, flag: "wx" });
2396
- await rename3(temporary, join6(path, ownerName));
2285
+ await writeFile4(temporary, JSON.stringify({ ...owner, runtimePid: pid }), { mode: 384, flag: "wx" });
2286
+ await rename3(temporary, join7(path, ownerName));
2397
2287
  } finally {
2398
2288
  await unlink4(temporary).catch(() => void 0);
2399
2289
  }
@@ -2401,7 +2291,7 @@ ${options.devAgentId}`).digest("hex");
2401
2291
  async release() {
2402
2292
  if (released) return;
2403
2293
  released = true;
2404
- await unlink4(join6(path, ownerName)).catch((error2) => {
2294
+ await unlink4(join7(path, ownerName)).catch((error2) => {
2405
2295
  if (code(error2) !== "ENOENT") throw error2;
2406
2296
  });
2407
2297
  await rmdir2(path).catch((error2) => {
@@ -2454,6 +2344,7 @@ function validateLaunchPlan(value) {
2454
2344
  async function launchPlanFor(config, options, projectRoot, signal) {
2455
2345
  const provider = options.platformLaunchPlan ?? ((context) => officialAgentLaunchPlan({
2456
2346
  datasets: config.datasets,
2347
+ model: config.model,
2457
2348
  projectRoot: context.projectRoot
2458
2349
  }));
2459
2350
  try {
@@ -2644,7 +2535,7 @@ async function startBuddyDev(options) {
2644
2535
  const pollIntervalMs = positiveDuration(options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS, "pollIntervalMs");
2645
2536
  const stopGracePeriodMs = positiveDuration(options.stopGracePeriodMs ?? DEFAULT_STOP_GRACE_PERIOD_MS, "stopGracePeriodMs");
2646
2537
  const devAgentId = safeDevAgentId(options.devAgentId);
2647
- const projectRoot = resolve9(options.projectRoot);
2538
+ const projectRoot = resolve8(options.projectRoot);
2648
2539
  const lifecycle = new AbortController();
2649
2540
  const signal = options.signal === void 0 ? lifecycle.signal : AbortSignal.any([lifecycle.signal, options.signal]);
2650
2541
  let agentProcess;
@@ -2662,7 +2553,7 @@ async function startBuddyDev(options) {
2662
2553
  let config;
2663
2554
  let configSource;
2664
2555
  try {
2665
- configSource = await readFile7(join7(projectRoot, BUDDY_AGENT_FILENAME), "utf8");
2556
+ configSource = await readFile8(join8(projectRoot, BUDDY_AGENT_FILENAME), "utf8");
2666
2557
  config = combineBuddyProject(parseBuddyAgentConfig(configSource));
2667
2558
  } catch (cause) {
2668
2559
  throw new BuddyDevError({
@@ -2672,14 +2563,12 @@ async function startBuddyDev(options) {
2672
2563
  cause
2673
2564
  });
2674
2565
  }
2675
- const widgetDelivery = await checkWidgetDelivery(projectRoot);
2676
- if (widgetDelivery.status === "incomplete") options.onLog?.({ source: "agent.stderr", text: widgetDeliverySummary(widgetDelivery) + "\nDEV \u5141\u8BB8\u7EE7\u7EED\u8C03\u8BD5\uFF0C\u63D0\u5BA1\u524D\u987B\u8865\u9F50\u3002\n" });
2677
2566
  const launchPlan = await launchPlanFor(config, options, projectRoot, signal);
2678
2567
  const registration = await registerDevAgent({
2679
2568
  client: options.registrationClient,
2680
2569
  devAgentId,
2681
2570
  configSource,
2682
- configDigest: `sha256:${createHash3("sha256").update(configSource).digest("hex")}`,
2571
+ configDigest: `sha256:${createHash2("sha256").update(configSource).digest("hex")}`,
2683
2572
  signal
2684
2573
  });
2685
2574
  throwIfDevAborted(signal);
@@ -2709,8 +2598,8 @@ async function startBuddyDev(options) {
2709
2598
  shell: false,
2710
2599
  detached: platform === "darwin",
2711
2600
  ...options.onLog === void 0 ? {} : {
2712
- onStdout: (text2) => options.onLog?.({ source: "agent.stdout", text: text2 }),
2713
- onStderr: (text2) => options.onLog?.({ source: "agent.stderr", text: text2 })
2601
+ onStdout: (text) => options.onLog?.({ source: "agent.stdout", text }),
2602
+ onStderr: (text) => options.onLog?.({ source: "agent.stderr", text })
2714
2603
  }
2715
2604
  });
2716
2605
  await instanceLock.attachRuntime(agentProcess.pid);
@@ -2766,7 +2655,7 @@ async function startBuddyDev(options) {
2766
2655
  }
2767
2656
 
2768
2657
  // packages/cli-core/src/dev/starter.ts
2769
- import { resolve as resolve10 } from "node:path";
2658
+ import { resolve as resolve9 } from "node:path";
2770
2659
  function createBuddyDevStarter(options = {}) {
2771
2660
  const readManifest = options.readManifest ?? (async (projectRoot) => {
2772
2661
  const manifest = await readBuddyProjectManifest(projectRoot);
@@ -2775,7 +2664,7 @@ function createBuddyDevStarter(options = {}) {
2775
2664
  const startDev = options.startDev ?? startBuddyDev;
2776
2665
  return Object.freeze({
2777
2666
  async start(input) {
2778
- const projectRoot = resolve10(input.projectRoot);
2667
+ const projectRoot = resolve9(input.projectRoot);
2779
2668
  const manifest = await readManifest(projectRoot);
2780
2669
  return startDev({
2781
2670
  ...input,
@@ -2866,7 +2755,7 @@ async function runDevCommand(args, io, options = {}) {
2866
2755
  return { exitCode: 0 };
2867
2756
  }
2868
2757
  try {
2869
- const requestedRoot = resolve11(options.cwd ?? process.cwd(), parsed.directory);
2758
+ const requestedRoot = resolve10(options.cwd ?? process.cwd(), parsed.directory);
2870
2759
  const root = await (options.resolveProjectRoot ?? requireBuddyAgentProjectRoot)(requestedRoot);
2871
2760
  const environment = options.env ?? process.env;
2872
2761
  const url = appServerUrl(parsed.appServer, environment);
@@ -2919,22 +2808,22 @@ async function runDevCommand(args, io, options = {}) {
2919
2808
  }
2920
2809
 
2921
2810
  // packages/cli-core/src/commands/cloud.ts
2922
- import { resolve as resolve12 } from "node:path";
2811
+ import { resolve as resolve11 } from "node:path";
2923
2812
 
2924
2813
  // packages/cli-core/src/cloud/avatar.ts
2925
2814
  import { open as open3 } from "node:fs/promises";
2926
2815
  import { basename } from "node:path";
2927
2816
  var MAX_BUDDY_AVATAR_BYTES = 5 * 1024 * 1024;
2928
2817
  async function readBuddyAvatarFile(path) {
2929
- const file2 = await open3(path, "r");
2818
+ const file = await open3(path, "r");
2930
2819
  try {
2931
- const stat2 = await file2.stat();
2820
+ const stat2 = await file.stat();
2932
2821
  if (!stat2.isFile()) throw new Error("\u5934\u50CF\u5FC5\u987B\u662F\u666E\u901A\u56FE\u7247\u6587\u4EF6");
2933
2822
  if (!stat2.size || stat2.size > MAX_BUDDY_AVATAR_BYTES) throw new Error("\u5934\u50CF\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u4E0D\u80FD\u8D85\u8FC7 5 MiB");
2934
2823
  const buffer = Buffer.alloc(MAX_BUDDY_AVATAR_BYTES + 1);
2935
2824
  let size = 0;
2936
2825
  while (size < buffer.length) {
2937
- const { bytesRead } = await file2.read(buffer, size, buffer.length - size, null);
2826
+ const { bytesRead } = await file.read(buffer, size, buffer.length - size, null);
2938
2827
  if (!bytesRead) break;
2939
2828
  size += bytesRead;
2940
2829
  }
@@ -2944,7 +2833,7 @@ async function readBuddyAvatarFile(path) {
2944
2833
  if (!mediaType) throw new Error("\u4EC5\u652F\u6301 PNG\u3001JPEG\u3001WebP \u56FE\u7247\u6587\u4EF6");
2945
2834
  return { bytes, fileName: basename(path), mediaType };
2946
2835
  } finally {
2947
- await file2.close();
2836
+ await file.close();
2948
2837
  }
2949
2838
  }
2950
2839
 
@@ -3117,7 +3006,7 @@ function positiveTimeout(value, fallback, name) {
3117
3006
  if (!Number.isSafeInteger(result) || result <= 0) throw new TypeError(`${name} must be a positive safe integer`);
3118
3007
  return result;
3119
3008
  }
3120
- function object3(value, path) {
3009
+ function object2(value, path) {
3121
3010
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
3122
3011
  throw invalid(`${path} \u5FC5\u987B\u662F\u5BF9\u8C61`);
3123
3012
  }
@@ -3137,7 +3026,7 @@ function optionalText(value, path, allowNewlines = false) {
3137
3026
  }
3138
3027
  function meta(value, path) {
3139
3028
  if (value === null) return null;
3140
- const source = object3(value, path);
3029
+ const source = object2(value, path);
3141
3030
  const name = source.name === void 0 ? void 0 : safeText(source.name, `${path}.name`);
3142
3031
  const avatar = optionalText(source.avatar, `${path}.avatar`);
3143
3032
  const tagline = optionalText(source.tagline, `${path}.tagline`);
@@ -3172,7 +3061,7 @@ function auditStatus(value, path) {
3172
3061
  return value;
3173
3062
  }
3174
3063
  function packageVersion(value, path) {
3175
- const source = object3(value, path);
3064
+ const source = object2(value, path);
3176
3065
  const auditNote = source.auditNote === null ? null : safeText(source.auditNote, `${path}.auditNote`, true);
3177
3066
  return Object.freeze({
3178
3067
  version: safeText(source.version, `${path}.version`),
@@ -3190,7 +3079,7 @@ function positivePage(value, name) {
3190
3079
  return value;
3191
3080
  }
3192
3081
  function buddy(value, includeToken) {
3193
- const source = object3(value, "response");
3082
+ const source = object2(value, "response");
3194
3083
  const token = includeToken ? safeText(source.token, "response.token") : void 0;
3195
3084
  return Object.freeze({
3196
3085
  id: safeText(source.id, "response.id"),
@@ -3326,7 +3215,7 @@ var HttpDeveloperPlatformClient = class {
3326
3215
  }), true);
3327
3216
  }
3328
3217
  async listBuddies() {
3329
- const source = object3(await this.#request("/cli/buddies", "GET"), "response");
3218
+ const source = object2(await this.#request("/cli/buddies", "GET"), "response");
3330
3219
  if (!Array.isArray(source.buddies)) throw invalid("response.buddies \u5FC5\u987B\u662F\u6570\u7EC4");
3331
3220
  return Object.freeze({
3332
3221
  buddies: Object.freeze(source.buddies.map((item) => buddy(item, false)))
@@ -3343,7 +3232,7 @@ var HttpDeveloperPlatformClient = class {
3343
3232
  ...pageSize === void 0 ? {} : { pageSize: String(pageSize) }
3344
3233
  });
3345
3234
  const suffix = query.size === 0 ? "" : `?${query.toString()}`;
3346
- const source = object3(await this.#request(
3235
+ const source = object2(await this.#request(
3347
3236
  `/cli/buddies/${encodeURIComponent(request.id)}/packages${suffix}`,
3348
3237
  "GET"
3349
3238
  ), "response");
@@ -3365,7 +3254,7 @@ var HttpDeveloperPlatformClient = class {
3365
3254
  throw new CloudLifecycleError("INVALID_REQUEST", "\u63D0\u4EA4\u5305\u4E0D\u80FD\u4E3A\u7A7A");
3366
3255
  }
3367
3256
  const query = new URLSearchParams({ commit });
3368
- const source = object3(await this.#request(
3257
+ const source = object2(await this.#request(
3369
3258
  `/cli/buddies/${encodeURIComponent(request.id)}/packages/push?${query.toString()}`,
3370
3259
  "POST",
3371
3260
  {
@@ -3382,13 +3271,13 @@ var HttpDeveloperPlatformClient = class {
3382
3271
  });
3383
3272
  }
3384
3273
  async logout(accessToken) {
3385
- const source = object3(await this.#request("/cli/auth/logout", "POST", { accessToken }), "response");
3274
+ const source = object2(await this.#request("/cli/auth/logout", "POST", { accessToken }), "response");
3386
3275
  if (source.ok !== true) throw invalid("response.ok \u5FC5\u987B\u662F true");
3387
3276
  }
3388
3277
  };
3389
3278
 
3390
3279
  // packages/cli-core/src/cloud/browser-login.ts
3391
- import { createHash as createHash4, randomBytes } from "node:crypto";
3280
+ import { createHash as createHash3, randomBytes } from "node:crypto";
3392
3281
  import { spawn } from "node:child_process";
3393
3282
  import { createServer } from "node:http";
3394
3283
 
@@ -3448,10 +3337,10 @@ function browserCommand(url) {
3448
3337
  }
3449
3338
  async function openExternalUrl(url) {
3450
3339
  const launch = browserCommand(url);
3451
- await new Promise((resolve16, reject) => {
3340
+ await new Promise((resolve15, reject) => {
3452
3341
  const child = spawn(launch.command, launch.args, { shell: false, stdio: "ignore", windowsHide: true });
3453
3342
  child.once("error", reject);
3454
- child.once("exit", (code2) => code2 === 0 ? resolve16() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
3343
+ child.once("exit", (code2) => code2 === 0 ? resolve15() : reject(new Error(`browser launcher exited with ${code2 ?? "unknown"}`)));
3455
3344
  });
3456
3345
  }
3457
3346
  async function write(res, status, title, message, webUrl, tone = "error") {
@@ -3463,10 +3352,10 @@ async function write(res, status, title, message, webUrl, tone = "error") {
3463
3352
  "referrer-policy": "no-referrer",
3464
3353
  "x-content-type-options": "nosniff"
3465
3354
  });
3466
- await new Promise((resolve16, reject) => {
3355
+ await new Promise((resolve15, reject) => {
3467
3356
  res.once("error", reject);
3468
- res.once("close", resolve16);
3469
- res.end(renderLoginResult(title, message, webUrl, tone), resolve16);
3357
+ res.once("close", resolve15);
3358
+ res.end(renderLoginResult(title, message, webUrl, tone), resolve15);
3470
3359
  });
3471
3360
  }
3472
3361
  async function readJson(response) {
@@ -3496,16 +3385,16 @@ var LoopbackBrowserLoginAdapter = class {
3496
3385
  if (request.signal?.aborted) throw request.signal.reason;
3497
3386
  const callbackSecret = randomBytes(24).toString("hex");
3498
3387
  const codeVerifier = randomBytes(32).toString("base64url");
3499
- const codeChallenge = createHash4("sha256").update(codeVerifier).digest("base64url");
3388
+ const codeChallenge = createHash3("sha256").update(codeVerifier).digest("base64url");
3500
3389
  let requestId = "";
3501
3390
  let settle;
3502
3391
  let reject;
3503
3392
  let settled = false;
3504
- const result = new Promise((resolve16, rejectResult) => {
3393
+ const result = new Promise((resolve15, rejectResult) => {
3505
3394
  settle = (value) => {
3506
3395
  if (!settled) {
3507
3396
  settled = true;
3508
- resolve16(value);
3397
+ resolve15(value);
3509
3398
  }
3510
3399
  };
3511
3400
  reject = (reason) => {
@@ -3524,9 +3413,9 @@ var LoopbackBrowserLoginAdapter = class {
3524
3413
  state: request.state
3525
3414
  }).then(settle, reject);
3526
3415
  });
3527
- await new Promise((resolve16, rejectListen) => {
3416
+ await new Promise((resolve15, rejectListen) => {
3528
3417
  server.once("error", rejectListen);
3529
- server.listen(0, "127.0.0.1", () => resolve16());
3418
+ server.listen(0, "127.0.0.1", () => resolve15());
3530
3419
  });
3531
3420
  const address = server.address();
3532
3421
  if (!address || typeof address === "string") {
@@ -3559,8 +3448,8 @@ var LoopbackBrowserLoginAdapter = class {
3559
3448
  } finally {
3560
3449
  clearTimeout(timer);
3561
3450
  request.signal?.removeEventListener("abort", abort);
3562
- await new Promise((resolve16) => {
3563
- server.close(() => resolve16());
3451
+ await new Promise((resolve15) => {
3452
+ server.close(() => resolve15());
3564
3453
  server.closeIdleConnections();
3565
3454
  server.closeAllConnections();
3566
3455
  });
@@ -3675,7 +3564,7 @@ function parse(source) {
3675
3564
  });
3676
3565
  }
3677
3566
  async function runCredentialCommand(input) {
3678
- return await new Promise((resolve16, reject) => {
3567
+ return await new Promise((resolve15, reject) => {
3679
3568
  const child = spawn2(input.command, [...input.args], {
3680
3569
  shell: false,
3681
3570
  windowsHide: true,
@@ -3691,7 +3580,7 @@ async function runCredentialCommand(input) {
3691
3580
  child.stdout.on("data", (chunk) => collect(stdout, chunk));
3692
3581
  child.stderr.on("data", (chunk) => collect(stderr, chunk));
3693
3582
  child.once("error", reject);
3694
- child.once("close", (code2) => resolve16({
3583
+ child.once("close", (code2) => resolve15({
3695
3584
  code: code2 ?? 1,
3696
3585
  stdout: Buffer.concat(stdout).toString("utf8"),
3697
3586
  stderr: Buffer.concat(stderr).toString("utf8")
@@ -3751,7 +3640,7 @@ var SystemCloudTokenStore = class {
3751
3640
  };
3752
3641
 
3753
3642
  // packages/cli-core/src/cloud/mock-client.ts
3754
- import { createHash as createHash5, randomBytes as randomBytes2 } from "node:crypto";
3643
+ import { createHash as createHash4, randomBytes as randomBytes2 } from "node:crypto";
3755
3644
  var MockDeveloperPlatformClient = class {
3756
3645
  #now;
3757
3646
  #buddies = /* @__PURE__ */ new Map();
@@ -3779,7 +3668,7 @@ var MockDeveloperPlatformClient = class {
3779
3668
  const current = this.#require(request.id);
3780
3669
  validateBuddyMetaUpdate(request.meta);
3781
3670
  const onlyAvatar = Object.keys(request.meta).every((key) => key === "avatar");
3782
- const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash5("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
3671
+ const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash4("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
3783
3672
  const next = this.#value({ ...current, meta: { ...onlyAvatar ? current.meta : request.meta, avatar }, updatedAt: this.#now() });
3784
3673
  this.#buddies.set(request.id, next);
3785
3674
  return structuredClone(next);
@@ -3923,7 +3812,7 @@ function dependencies(options) {
3923
3812
  return { session: options.session, client: options.client };
3924
3813
  }
3925
3814
  function requestedDirectory(options, parsed) {
3926
- return resolve12(options.cwd ?? process.cwd(), parsed.values.get("--directory") ?? ".");
3815
+ return resolve11(options.cwd ?? process.cwd(), parsed.values.get("--directory") ?? ".");
3927
3816
  }
3928
3817
  function auditLabel(status) {
3929
3818
  if (status === "auditing") return "\u5BA1\u6838\u4E2D";
@@ -4004,10 +3893,10 @@ async function runAvatar(parsed, io, options) {
4004
3893
  if (parsed.values.has("--buddy-id") && parsed.values.has("--directory")) {
4005
3894
  throw new CloudCommandUsageError("--buddy-id \u548C --directory \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
4006
3895
  }
4007
- const file2 = parsed.values.get("--file");
3896
+ const file = parsed.values.get("--file");
4008
3897
  let upload;
4009
3898
  try {
4010
- upload = file2 ? await readBuddyAvatarFile(resolve12(options.cwd ?? process.cwd(), file2)) : void 0;
3899
+ upload = file ? await readBuddyAvatarFile(resolve11(options.cwd ?? process.cwd(), file)) : void 0;
4011
3900
  } catch (error2) {
4012
3901
  throw new CloudCommandUsageError(error2 instanceof Error ? error2.message : "\u65E0\u6CD5\u8BFB\u53D6\u5934\u50CF\u56FE\u7247");
4013
3902
  }
@@ -4076,8 +3965,8 @@ async function runCloudCommand(command, args, io, options = {}) {
4076
3965
  var CLOUD_COMMAND_HELP = HELP;
4077
3966
 
4078
3967
  // packages/cli-core/src/migration/index.ts
4079
- import { lstat as lstat7, open as open4, readdir as readdir4, realpath as realpath4, stat } from "node:fs/promises";
4080
- import { extname, isAbsolute as isAbsolute2, join as join8, relative, resolve as resolve13, sep, win32 as win322 } from "node:path";
3968
+ import { lstat as lstat7, open as open4, readdir as readdir3, realpath as realpath3, stat } from "node:fs/promises";
3969
+ import { extname, isAbsolute as isAbsolute2, join as join9, relative, resolve as resolve12, sep, win32 as win322 } from "node:path";
4081
3970
  var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
4082
3971
  maxFiles: 128,
4083
3972
  maxFileBytes: 256 * 1024,
@@ -4230,7 +4119,7 @@ async function existingProjectRoot(value) {
4230
4119
  return rejectScan("SKILL_PROJECT_ROOT_INVALID", ".", "projectRoot \u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u5DF2\u6709\u9879\u76EE\u76EE\u5F55\u3002");
4231
4120
  }
4232
4121
  try {
4233
- const root = await realpath4(resolve13(value));
4122
+ const root = await realpath3(resolve12(value));
4234
4123
  if (!(await stat(root)).isDirectory()) {
4235
4124
  return rejectScan("SKILL_PROJECT_ROOT_INVALID", ".", "projectRoot \u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u5DF2\u6709\u9879\u76EE\u76EE\u5F55\u3002");
4236
4125
  }
@@ -4246,7 +4135,7 @@ async function existingProjectRoot(value) {
4246
4135
  }
4247
4136
  }
4248
4137
  async function existingSkillRoot(projectRoot, skillPath) {
4249
- const candidate = skillPath === "." ? projectRoot : join8(projectRoot, ...skillPath.split("/"));
4138
+ const candidate = skillPath === "." ? projectRoot : join9(projectRoot, ...skillPath.split("/"));
4250
4139
  try {
4251
4140
  await lstat7(candidate);
4252
4141
  } catch (cause) {
@@ -4257,7 +4146,7 @@ async function existingSkillRoot(projectRoot, skillPath) {
4257
4146
  }
4258
4147
  let root;
4259
4148
  try {
4260
- root = await realpath4(candidate);
4149
+ root = await realpath3(candidate);
4261
4150
  } catch (cause) {
4262
4151
  if (filesystemCode(cause) === "ELOOP") {
4263
4152
  return rejectScan("SKILL_SYMLINK_CYCLE", skillPath, "Skill \u8DEF\u5F84\u5305\u542B\u7B26\u53F7\u94FE\u63A5\u5FAA\u73AF\u3002", cause);
@@ -4283,10 +4172,10 @@ async function existingSkillRoot(projectRoot, skillPath) {
4283
4172
  }
4284
4173
  async function assertEntrypoint(context) {
4285
4174
  const entryPath = reportChild(context.skillPath, "SKILL.md");
4286
- const candidate = join8(context.skillRoot, "SKILL.md");
4175
+ const candidate = join9(context.skillRoot, "SKILL.md");
4287
4176
  try {
4288
4177
  await lstat7(candidate);
4289
- const target = await realpath4(candidate);
4178
+ const target = await realpath3(candidate);
4290
4179
  if (!isWithin(context.projectRoot, target) || !isWithin(context.skillRoot, target)) {
4291
4180
  rejectScan(
4292
4181
  "SKILL_SYMLINK_ESCAPE",
@@ -4330,7 +4219,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
4330
4219
  }
4331
4220
  let directory;
4332
4221
  try {
4333
- directory = await realpath4(actualDirectory);
4222
+ directory = await realpath3(actualDirectory);
4334
4223
  } catch (cause) {
4335
4224
  if (filesystemCode(cause) === "ELOOP") {
4336
4225
  return rejectScan("SKILL_SYMLINK_CYCLE", reportDirectory, "Skill \u76EE\u5F55\u5305\u542B\u7B26\u53F7\u94FE\u63A5\u5FAA\u73AF\u3002", cause);
@@ -4350,7 +4239,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
4350
4239
  nextAncestors.add(directoryKey);
4351
4240
  let entries;
4352
4241
  try {
4353
- entries = await readdir4(directory, { withFileTypes: true, encoding: "utf8" });
4242
+ entries = await readdir3(directory, { withFileTypes: true, encoding: "utf8" });
4354
4243
  } catch (cause) {
4355
4244
  return rejectScan("SKILL_SCAN_IO_ERROR", reportDirectory, "\u65E0\u6CD5\u5217\u51FA Skill \u5B50\u76EE\u5F55\u3002", cause);
4356
4245
  }
@@ -4387,10 +4276,10 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
4387
4276
  }
4388
4277
  for (const entry of entries) {
4389
4278
  const childReportPath = reportChild(reportDirectory, entry.name);
4390
- const childPath = join8(directory, entry.name);
4279
+ const childPath = join9(directory, entry.name);
4391
4280
  let target;
4392
4281
  try {
4393
- target = await realpath4(childPath);
4282
+ target = await realpath3(childPath);
4394
4283
  } catch (cause) {
4395
4284
  if (filesystemCode(cause) === "ELOOP") {
4396
4285
  return rejectScan("SKILL_SYMLINK_CYCLE", childReportPath, "Skill \u5185\u5BB9\u5305\u542B\u7B26\u53F7\u94FE\u63A5\u5FAA\u73AF\u3002", cause);
@@ -4841,9 +4730,9 @@ async function scanExternalSkillPortability(options) {
4841
4730
  }
4842
4731
 
4843
4732
  // packages/cli-core/src/push/preflight.ts
4844
- import { createHash as createHash6 } from "node:crypto";
4845
- import { lstat as lstat8, open as open5, readdir as readdir5, realpath as realpath5 } from "node:fs/promises";
4846
- import { isAbsolute as isAbsolute3, join as join9, relative as relative2, resolve as resolve14, sep as sep2, win32 as win323 } from "node:path";
4733
+ import { createHash as createHash5 } from "node:crypto";
4734
+ import { lstat as lstat8, open as open5, readdir as readdir4, realpath as realpath4 } from "node:fs/promises";
4735
+ import { isAbsolute as isAbsolute3, join as join10, relative as relative2, resolve as resolve13, sep as sep2, win32 as win323 } from "node:path";
4847
4736
 
4848
4737
  // packages/cli-core/src/push/errors.ts
4849
4738
  var PushPreflightError = class extends Error {
@@ -4941,7 +4830,7 @@ function error(options) {
4941
4830
  throw new PushPreflightError(options);
4942
4831
  }
4943
4832
  function sha256(value) {
4944
- return `sha256:${createHash6("sha256").update(value).digest("hex")}`;
4833
+ return `sha256:${createHash5("sha256").update(value).digest("hex")}`;
4945
4834
  }
4946
4835
  function positiveLimit(value, name, hardMaximum) {
4947
4836
  if (!Number.isSafeInteger(value) || value < 1 || value > hardMaximum) {
@@ -5031,7 +4920,7 @@ function normalizeBookletPath(value) {
5031
4920
  return normalized;
5032
4921
  }
5033
4922
  async function canonicalProjectRoot(projectRoot) {
5034
- const absolute = resolve14(projectRoot);
4923
+ const absolute = resolve13(projectRoot);
5035
4924
  let entry;
5036
4925
  try {
5037
4926
  entry = await lstat8(absolute);
@@ -5051,7 +4940,7 @@ async function canonicalProjectRoot(projectRoot) {
5051
4940
  });
5052
4941
  }
5053
4942
  try {
5054
- return await realpath5(absolute);
4943
+ return await realpath4(absolute);
5055
4944
  } catch (cause) {
5056
4945
  error({
5057
4946
  code: "PUSH_PROJECT_INVALID",
@@ -5062,7 +4951,7 @@ async function canonicalProjectRoot(projectRoot) {
5062
4951
  }
5063
4952
  }
5064
4953
  async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
5065
- const path = join9(projectRoot, filename);
4954
+ const path = join10(projectRoot, filename);
5066
4955
  let entry;
5067
4956
  try {
5068
4957
  entry = await lstat8(path);
@@ -5096,22 +4985,22 @@ async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
5096
4985
  maxFileBytes
5097
4986
  });
5098
4987
  }
5099
- function decodeCapturedConfig(file2) {
5100
- if (file2.contents === void 0) {
4988
+ function decodeCapturedConfig(file) {
4989
+ if (file.contents === void 0) {
5101
4990
  error({
5102
4991
  code: "PUSH_CONFIG_INVALID",
5103
- path: file2.path,
5104
- message: `\u65E0\u6CD5\u8BFB\u53D6 ${file2.path} \u5185\u5BB9\u3002`
4992
+ path: file.path,
4993
+ message: `\u65E0\u6CD5\u8BFB\u53D6 ${file.path} \u5185\u5BB9\u3002`
5105
4994
  });
5106
4995
  }
5107
4996
  let source;
5108
4997
  try {
5109
- source = new TextDecoder("utf-8", { fatal: true }).decode(file2.contents);
4998
+ source = new TextDecoder("utf-8", { fatal: true }).decode(file.contents);
5110
4999
  } catch (cause) {
5111
5000
  error({
5112
5001
  code: "PUSH_CONFIG_INVALID",
5113
- path: file2.path,
5114
- message: `${file2.path} \u4E0D\u662F\u6709\u6548 UTF-8\u3002`,
5002
+ path: file.path,
5003
+ message: `${file.path} \u4E0D\u662F\u6709\u6548 UTF-8\u3002`,
5115
5004
  cause
5116
5005
  });
5117
5006
  }
@@ -5132,7 +5021,7 @@ function parseCapturedProject(agentFile) {
5132
5021
  async function selectLockfile(projectRoot) {
5133
5022
  let names;
5134
5023
  try {
5135
- names = await readdir5(projectRoot);
5024
+ names = await readdir4(projectRoot);
5136
5025
  } catch (cause) {
5137
5026
  error({
5138
5027
  code: "PUSH_PROJECT_INVALID",
@@ -5187,7 +5076,7 @@ async function hashRegularFile(options) {
5187
5076
  message: `\u751F\u6210\u6E05\u5355\u65F6\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${options.portablePath}`
5188
5077
  });
5189
5078
  }
5190
- const hash = createHash6("sha256");
5079
+ const hash = createHash5("sha256");
5191
5080
  const captured = [];
5192
5081
  const buffer = Buffer.allocUnsafe(READ_BUFFER_BYTES);
5193
5082
  let bytes = 0;
@@ -5241,7 +5130,7 @@ async function createManifest(options) {
5241
5130
  }
5242
5131
  let names;
5243
5132
  try {
5244
- names = await readdir5(directory);
5133
+ names = await readdir4(directory);
5245
5134
  } catch (cause) {
5246
5135
  error({
5247
5136
  code: "PUSH_PROJECT_INVALID",
@@ -5265,7 +5154,7 @@ async function createManifest(options) {
5265
5154
  sensitiveEntriesExcluded += 1;
5266
5155
  continue;
5267
5156
  }
5268
- const absolutePath = join9(directory, name);
5157
+ const absolutePath = join10(directory, name);
5269
5158
  let entry;
5270
5159
  try {
5271
5160
  entry = await lstat8(absolutePath);
@@ -5299,7 +5188,7 @@ async function createManifest(options) {
5299
5188
  }
5300
5189
  let canonicalPath;
5301
5190
  try {
5302
- canonicalPath = await realpath5(absolutePath);
5191
+ canonicalPath = await realpath4(absolutePath);
5303
5192
  } catch (cause) {
5304
5193
  error({
5305
5194
  code: "PUSH_FILE_CHANGED",
@@ -5358,15 +5247,15 @@ async function createManifest(options) {
5358
5247
  message: `\u63D0\u4EA4\u6587\u4EF6\u603B\u91CF\u8D85\u8FC7\u4E0A\u9650 ${options.limits.maxTotalBytes} bytes\u3002`
5359
5248
  });
5360
5249
  }
5361
- const file2 = await hashRegularFile({
5250
+ const file = await hashRegularFile({
5362
5251
  absolutePath,
5363
5252
  portablePath: path,
5364
5253
  expected: entry,
5365
5254
  captureContents: options.capturePaths.has(path),
5366
5255
  maxFileBytes: options.limits.maxFileBytes
5367
5256
  });
5368
- files.push(file2);
5369
- totalBytes += file2.bytes;
5257
+ files.push(file);
5258
+ totalBytes += file.bytes;
5370
5259
  }
5371
5260
  };
5372
5261
  await walk(options.projectRoot, []);
@@ -5447,10 +5336,10 @@ function validateLockfile(lockfile, contents) {
5447
5336
  function bundleDigest(files) {
5448
5337
  const descriptor = JSON.stringify({
5449
5338
  schemaVersion: "1",
5450
- files: files.map((file2) => ({
5451
- path: file2.path,
5452
- bytes: file2.bytes,
5453
- digest: file2.digest
5339
+ files: files.map((file) => ({
5340
+ path: file.path,
5341
+ bytes: file.bytes,
5342
+ digest: file.digest
5454
5343
  }))
5455
5344
  });
5456
5345
  return sha256(`buddy-push-bundle-v1\0${descriptor}`);
@@ -5460,8 +5349,8 @@ function warning(code2, message) {
5460
5349
  }
5461
5350
  function assertOfficialProjectIncluded(files) {
5462
5351
  for (const path of OFFICIAL_RUNTIME_INPUTS) {
5463
- const file2 = files.find((entry) => entry.path === path);
5464
- if (file2 === void 0 || file2.bytes === 0) {
5352
+ const file = files.find((entry) => entry.path === path);
5353
+ if (file === void 0 || file.bytes === 0) {
5465
5354
  error({
5466
5355
  code: "PUSH_PROJECT_INVALID",
5467
5356
  path,
@@ -5500,7 +5389,7 @@ function assertOfficialProjectIncluded(files) {
5500
5389
  }
5501
5390
  }
5502
5391
  async function assertCapturedConfigStable(options) {
5503
- const manifestEntry = options.manifestFiles.find((file2) => file2.path === options.filename);
5392
+ const manifestEntry = options.manifestFiles.find((file) => file.path === options.filename);
5504
5393
  if (manifestEntry === void 0) {
5505
5394
  error({
5506
5395
  code: "PUSH_CONFIG_INVALID",
@@ -5517,7 +5406,7 @@ async function assertCapturedConfigStable(options) {
5517
5406
  }
5518
5407
  let current;
5519
5408
  try {
5520
- const path = join9(options.projectRoot, options.filename);
5409
+ const path = join10(options.projectRoot, options.filename);
5521
5410
  const entry = await lstat8(path);
5522
5411
  if (!entry.isFile() || entry.isSymbolicLink()) {
5523
5412
  error({
@@ -5561,8 +5450,6 @@ async function createPushPreflight(options) {
5561
5450
  BUDDY_AGENT_FILENAME
5562
5451
  );
5563
5452
  parseCapturedProject(initialAgentEntry);
5564
- const widgetDelivery = await checkWidgetDelivery(projectRoot);
5565
- if (widgetDelivery.status === "incomplete") error({ code: "PUSH_WIDGET_DELIVERY_INCOMPLETE", message: widgetDeliverySummary(widgetDelivery) });
5566
5453
  const lockfile = await selectLockfile(projectRoot);
5567
5454
  assertBookletIsNotRequiredInput(bookletPath, lockfile);
5568
5455
  const manifest = await createManifest({
@@ -5571,12 +5458,7 @@ async function createPushPreflight(options) {
5571
5458
  capturePaths: /* @__PURE__ */ new Set([BUDDY_AGENT_FILENAME, lockfile.path, BUDDY_PLATFORM_PACKAGE_JSON, BUDDY_PLATFORM_AGENT_ENTRY, BUDDY_PLATFORM_FACTORY_ENTRY]),
5572
5459
  ...bookletPath === void 0 ? {} : { bookletPath }
5573
5460
  });
5574
- for (const checked of widgetDelivery.files ?? []) {
5575
- if (manifest.files.find((file2) => file2.path === checked.path)?.digest !== checked.digest) {
5576
- error({ code: "PUSH_WIDGET_DELIVERY_INCOMPLETE", message: `\u5C0F\u6302\u4EF6\u6838\u5BF9\u540E\u6587\u4EF6\u53D8\u5316\u6216\u672A\u8FDB\u5165\u4E0A\u4F20\u5305\uFF1A${checked.path}\uFF1B\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002` });
5577
- }
5578
- }
5579
- const lockEntry = manifest.files.find((file2) => file2.path === lockfile.path);
5461
+ const lockEntry = manifest.files.find((file) => file.path === lockfile.path);
5580
5462
  if (lockEntry?.contents === void 0) {
5581
5463
  error({
5582
5464
  code: "PUSH_LOCKFILE_INVALID",
@@ -5601,22 +5483,23 @@ async function createPushPreflight(options) {
5601
5483
  maxFileBytes: limits.maxFileBytes
5602
5484
  });
5603
5485
  const config = parseCapturedProject(agentEntry);
5604
- if (config.datasets?.length) {
5486
+ if (config.datasets?.length || config.model !== void 0) {
5605
5487
  try {
5606
- await validateRuntimeDatasets(projectRoot, config.datasets);
5488
+ if (config.datasets?.length) await validateRuntimeDatasets(projectRoot, config.datasets);
5489
+ await validateRuntimeModel(projectRoot, config.model);
5607
5490
  } catch (cause) {
5608
5491
  error({
5609
5492
  code: "PUSH_CONFIG_INVALID",
5610
5493
  path: BUDDY_AGENT_FILENAME,
5611
- message: `\u65E0\u6CD5\u6309\u5DE5\u7A0B Runtime \u6821\u9A8C\u6570\u636E\u58F0\u660E\uFF1A${cause instanceof Error ? cause.message : String(cause)}`,
5494
+ message: `\u65E0\u6CD5\u6309\u5DE5\u7A0B Runtime \u6821\u9A8C\u6A21\u578B\u6216\u6570\u636E\u58F0\u660E\uFF1A${cause instanceof Error ? cause.message : String(cause)}`,
5612
5495
  cause
5613
5496
  });
5614
5497
  }
5615
5498
  }
5616
- const files = Object.freeze(manifest.files.map((file2) => Object.freeze({
5617
- path: file2.path,
5618
- bytes: file2.bytes,
5619
- digest: file2.digest
5499
+ const files = Object.freeze(manifest.files.map((file) => Object.freeze({
5500
+ path: file.path,
5501
+ bytes: file.bytes,
5502
+ digest: file.digest
5620
5503
  })));
5621
5504
  const warnings = [warning(
5622
5505
  "PREFLIGHT_ONLY",
@@ -5652,16 +5535,16 @@ async function createPushPreflight(options) {
5652
5535
  }
5653
5536
 
5654
5537
  // packages/cli-core/src/push/bundle.ts
5655
- import { createHash as createHash7 } from "node:crypto";
5656
- import { lstat as lstat9, readFile as readFile8, realpath as realpath6 } from "node:fs/promises";
5657
- import { join as join10, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
5538
+ import { createHash as createHash6 } from "node:crypto";
5539
+ import { lstat as lstat9, readFile as readFile9, realpath as realpath5 } from "node:fs/promises";
5540
+ import { join as join11, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
5658
5541
  import { Writable } from "node:stream";
5659
5542
  import { pipeline } from "node:stream/promises";
5660
5543
  import { createGzip } from "node:zlib";
5661
5544
  import { pack } from "tar-stream";
5662
5545
  var MEDIA_TYPE = "application/gzip";
5663
5546
  function digest(bytes) {
5664
- return `sha256:${createHash7("sha256").update(bytes).digest("hex")}`;
5547
+ return `sha256:${createHash6("sha256").update(bytes).digest("hex")}`;
5665
5548
  }
5666
5549
  function changed(path, message, cause) {
5667
5550
  throw new PushPreflightError({
@@ -5675,42 +5558,42 @@ function inside(root, target) {
5675
5558
  const path = relative3(root, target);
5676
5559
  return path === "" || path !== ".." && !path.startsWith(`..${sep3}`) && !path.startsWith("/") && !win324.isAbsolute(path);
5677
5560
  }
5678
- async function capture(root, file2) {
5679
- const absolute = join10(root, ...file2.path.split("/"));
5561
+ async function capture(root, file) {
5562
+ const absolute = join11(root, ...file.path.split("/"));
5680
5563
  try {
5681
5564
  const entry = await lstat9(absolute);
5682
- if (!entry.isFile() || entry.isSymbolicLink() || entry.size !== file2.bytes) {
5683
- changed(file2.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${file2.path}`);
5565
+ if (!entry.isFile() || entry.isSymbolicLink() || entry.size !== file.bytes) {
5566
+ changed(file.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${file.path}`);
5684
5567
  }
5685
- const canonical = await realpath6(absolute);
5686
- if (!inside(root, canonical)) changed(file2.path, `\u63D0\u4EA4\u6587\u4EF6\u8D8A\u8FC7\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${file2.path}`);
5687
- const contents = await readFile8(absolute);
5688
- if (contents.byteLength !== file2.bytes || digest(contents) !== file2.digest) {
5689
- changed(file2.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u5185\u5BB9\u53D1\u751F\u53D8\u5316\uFF1A${file2.path}`);
5568
+ const canonical = await realpath5(absolute);
5569
+ if (!inside(root, canonical)) changed(file.path, `\u63D0\u4EA4\u6587\u4EF6\u8D8A\u8FC7\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${file.path}`);
5570
+ const contents = await readFile9(absolute);
5571
+ if (contents.byteLength !== file.bytes || digest(contents) !== file.digest) {
5572
+ changed(file.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u5185\u5BB9\u53D1\u751F\u53D8\u5316\uFF1A${file.path}`);
5690
5573
  }
5691
5574
  return Object.freeze({
5692
- path: file2.path,
5693
- bytes: file2.bytes,
5694
- digest: file2.digest,
5575
+ path: file.path,
5576
+ bytes: file.bytes,
5577
+ digest: file.digest,
5695
5578
  content: contents
5696
5579
  });
5697
5580
  } catch (cause) {
5698
5581
  if (cause instanceof PushPreflightError) throw cause;
5699
- changed(file2.path, `\u63D0\u4EA4\u524D\u65E0\u6CD5\u518D\u6B21\u8BFB\u53D6\u6587\u4EF6\uFF1A${file2.path}`, cause);
5582
+ changed(file.path, `\u63D0\u4EA4\u524D\u65E0\u6CD5\u518D\u6B21\u8BFB\u53D6\u6587\u4EF6\uFF1A${file.path}`, cause);
5700
5583
  }
5701
5584
  }
5702
5585
  async function createPushSourceBundle(plan) {
5703
- const canonicalRoot = await realpath6(plan.projectRoot).catch((cause) => changed(plan.projectRoot, "\u63D0\u4EA4\u9879\u76EE\u76EE\u5F55\u5728\u6253\u5305\u524D\u5DF2\u4E0D\u53EF\u7528", cause));
5586
+ const canonicalRoot = await realpath5(plan.projectRoot).catch((cause) => changed(plan.projectRoot, "\u63D0\u4EA4\u9879\u76EE\u76EE\u5F55\u5728\u6253\u5305\u524D\u5DF2\u4E0D\u53EF\u7528", cause));
5704
5587
  if (canonicalRoot !== plan.projectRoot) {
5705
5588
  changed(plan.projectRoot, "\u63D0\u4EA4\u9879\u76EE\u6839\u76EE\u5F55\u5728\u9884\u68C0\u540E\u53D1\u751F\u53D8\u5316");
5706
5589
  }
5707
5590
  const files = [];
5708
- for (const file2 of plan.files) files.push(await capture(canonicalRoot, file2));
5591
+ for (const file of plan.files) files.push(await capture(canonicalRoot, file));
5709
5592
  const descriptor = JSON.stringify({
5710
5593
  schemaVersion: "1",
5711
- files: files.map((file2) => ({ path: file2.path, bytes: file2.bytes, digest: file2.digest }))
5594
+ files: files.map((file) => ({ path: file.path, bytes: file.bytes, digest: file.digest }))
5712
5595
  });
5713
- const calculatedBundleDigest = `sha256:${createHash7("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
5596
+ const calculatedBundleDigest = `sha256:${createHash6("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
5714
5597
  if (calculatedBundleDigest !== plan.bundleDigest) {
5715
5598
  changed(plan.projectRoot, "\u63D0\u4EA4\u6E05\u5355\u8EAB\u4EFD\u5728\u6253\u5305\u524D\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C push");
5716
5599
  }
@@ -5723,16 +5606,16 @@ async function createPushSourceBundle(plan) {
5723
5606
  }
5724
5607
  });
5725
5608
  const completed = pipeline(archive, createGzip({ level: 9 }), output);
5726
- for (const file2 of files) {
5609
+ for (const file of files) {
5727
5610
  await new Promise((resolveEntry, rejectEntry) => {
5728
5611
  archive.entry({
5729
- name: file2.path,
5730
- size: file2.content.byteLength,
5612
+ name: file.path,
5613
+ size: file.content.byteLength,
5731
5614
  mode: 420,
5732
5615
  uid: 0,
5733
5616
  gid: 0,
5734
5617
  mtime: /* @__PURE__ */ new Date(0)
5735
- }, file2.content, (cause) => cause ? rejectEntry(cause) : resolveEntry());
5618
+ }, file.content, (cause) => cause ? rejectEntry(cause) : resolveEntry());
5736
5619
  });
5737
5620
  }
5738
5621
  archive.finalize();
@@ -5773,8 +5656,7 @@ var HELP2 = `\u642D\u642D Developer Platform CLI
5773
5656
  buddy-cli dev [--app-server <URL>] [--directory <\u9879\u76EE\u76EE\u5F55>]
5774
5657
  buddy-cli login | logout | push | status
5775
5658
  buddy-cli avatar (--file <\u56FE\u7247\u6587\u4EF6> | --clear) [--directory <\u9879\u76EE\u76EE\u5F55> | --buddy-id <\u642D\u5B50 ID>]
5776
- buddy-cli models [--json]
5777
- buddy-cli widgets sync | check | verify
5659
+ buddy-cli models [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
5778
5660
  buddy-cli datasets [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
5779
5661
  buddy-cli preview [--app-server <URL>] [--directory <\u9879\u76EE\u76EE\u5F55>]
5780
5662
  buddy-cli help
@@ -5786,8 +5668,8 @@ var HELP2 = `\u642D\u642D Developer Platform CLI
5786
5668
  dev \u542F\u52A8\u5B98\u65B9 Runtime \u5E76\u8FDE\u63A5 DEV App Server
5787
5669
  login \u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u642D\u642D\u8D26\u53F7
5788
5670
  logout \u9000\u51FA\u642D\u642D\u5F00\u53D1\u8005\u8D26\u53F7\u5E76\u6E05\u9664\u672C\u673A\u767B\u5F55\u72B6\u6001
5789
- models \u67E5\u770B CLI \u5185\u7F6E\u6A21\u578B ID\uFF08\u65E0\u9700\u767B\u5F55\u3001\u8054\u7F51\u6216 Agent \u5DE5\u7A0B\uFF09
5790
- datasets \u8BFB\u53D6\u5DE5\u7A0B Runtime \u63D0\u4F9B\u7684\u6570\u636E\u96C6\u76EE\u5F55\uFF08\u65E0\u9700\u767B\u5F55\uFF09
5671
+ models \u67E5\u770B Runtime \u6A21\u578B ID\uFF08\u5DE5\u7A0B\u5916\u8054\u7F51\u8BFB\u53D6\u6700\u65B0\u7248\uFF0C\u65E0\u9700\u767B\u5F55\uFF09
5672
+ datasets \u67E5\u770B Runtime \u6570\u636E\u96C6\u76EE\u5F55\uFF08\u5DE5\u7A0B\u5916\u8054\u7F51\u8BFB\u53D6\u6700\u65B0\u7248\uFF0C\u65E0\u9700\u767B\u5F55\uFF09
5791
5673
  push \u4E0A\u4F20 Agent \u5DE5\u7A0B\u548C commit\uFF0C\u63D0\u4EA4\u5E73\u53F0\u5BA1\u6838
5792
5674
  status \u67E5\u8BE2\u642D\u5B50\u7684\u8D44\u6599\u3001\u4EE3\u7801\u3001\u8FD0\u884C\u4E0E\u53D1\u5E03\u72B6\u6001
5793
5675
  avatar \u8BBE\u7F6E\u6216\u6E05\u9664\u642D\u5B50\u5934\u50CF\uFF0C\u4FDD\u7559\u5176\u4ED6\u4E91\u7AEF\u8D44\u6599
@@ -5996,7 +5878,7 @@ function defaultProjectDirectory(name) {
5996
5878
  return `./${folder}`;
5997
5879
  }
5998
5880
  async function initializeProjectRoute(route, args, io, options, application) {
5999
- const cwd = resolve15(options.cwd ?? process.cwd());
5881
+ const cwd = resolve14(options.cwd ?? process.cwd());
6000
5882
  const { name, tagline, intro } = application;
6001
5883
  const directoryInput = await textAnswer(
6002
5884
  io,
@@ -6005,7 +5887,7 @@ async function initializeProjectRoute(route, args, io, options, application) {
6005
5887
  "\u9879\u76EE\u76EE\u5F55\uFF08\u7A7A\u76EE\u5F55\u6216\u5DF2\u6709\u642D\u642D\u5DE5\u7A0B\uFF09",
6006
5888
  defaultProjectDirectory(name)
6007
5889
  );
6008
- const rootDirectory = resolve15(cwd, directoryInput);
5890
+ const rootDirectory = resolve14(cwd, directoryInput);
6009
5891
  await assertInitializableBuddyTarget(rootDirectory);
6010
5892
  const initializationTarget = { directory: rootDirectory, kind: "new" };
6011
5893
  const initializationPlan = options.initializeProject ? void 0 : await planBuddyProjectInitialization(initializationTarget);
@@ -6049,7 +5931,7 @@ async function initializeProjectRoute(route, args, io, options, application) {
6049
5931
  }
6050
5932
  async function runRoute(route, args, io, options) {
6051
5933
  if (!io.canPrompt) assertNonInteractiveProjectArguments(route, args);
6052
- const cwd = resolve15(options.cwd ?? process.cwd());
5934
+ const cwd = resolve14(options.cwd ?? process.cwd());
6053
5935
  const name = await textAnswer(io, args.name, "--name", "\u642D\u5B50\u540D\u79F0", void 0, BUDDY_PROFILE_TEXT_LIMITS.name);
6054
5936
  const tagline = await textAnswer(
6055
5937
  io,
@@ -6077,7 +5959,7 @@ async function runRoute(route, args, io, options) {
6077
5959
  "\u9879\u76EE\u76EE\u5F55",
6078
5960
  defaultProjectDirectory(name)
6079
5961
  );
6080
- const rootDirectory = resolve15(cwd, directoryInput);
5962
+ const rootDirectory = resolve14(cwd, directoryInput);
6081
5963
  await assertInitializableBuddyTarget(rootDirectory);
6082
5964
  const plan = await planBuddyDraftInitialization(rootDirectory);
6083
5965
  const existingBuddyId = plan.existingManifest?.buddyId;
@@ -6111,11 +5993,11 @@ async function runRoute(route, args, io, options) {
6111
5993
  return { ...result, route: "create", draft, buddyId };
6112
5994
  }
6113
5995
  async function resumeProjectArguments(args, cwd, options) {
6114
- const root = resolve15(cwd, args.directory?.trim() || ".");
5996
+ const root = resolve14(cwd, args.directory?.trim() || ".");
6115
5997
  await assertInitializableBuddyTarget(root);
6116
5998
  let entry;
6117
5999
  try {
6118
- entry = await lstat10(join11(root, "buddy.agent.json"));
6000
+ entry = await lstat10(join12(root, "buddy.agent.json"));
6119
6001
  } catch (cause) {
6120
6002
  if (cause.code === "ENOENT") return;
6121
6003
  throw cause;
@@ -6144,7 +6026,7 @@ async function runBuddyCli(args, io, options = {}) {
6144
6026
  try {
6145
6027
  const [command, ...rest] = args;
6146
6028
  if (!command) {
6147
- const cwd = resolve15(options.cwd ?? process.cwd());
6029
+ const cwd = resolve14(options.cwd ?? process.cwd());
6148
6030
  let projectRoot;
6149
6031
  try {
6150
6032
  projectRoot = await findBuddyProjectRoot(cwd);
@@ -6172,13 +6054,12 @@ async function runBuddyCli(args, io, options = {}) {
6172
6054
  io.write(HELP2);
6173
6055
  return { exitCode: 0 };
6174
6056
  }
6175
- if (command === "models") return runModelsCommand(rest, io);
6176
- if (command === "widgets") return await runWidgetsCommand(rest, io, options.cwd ?? process.cwd());
6057
+ if (command === "models") return await runModelsCommand(rest, io, options.cwd ?? process.cwd(), options.runtimeCatalog);
6177
6058
  if (command === "preview") {
6178
6059
  return options.preview?.(rest, io) ?? failure("preview \u5BBF\u4E3B\u672A\u914D\u7F6E", io, true);
6179
6060
  }
6180
6061
  if (command === "datasets") {
6181
- return await runDatasetsCommand(rest, io, options.cwd ?? process.cwd());
6062
+ return await runDatasetsCommand(rest, io, options.cwd ?? process.cwd(), options.runtimeCatalog);
6182
6063
  }
6183
6064
  if (command === "dev") {
6184
6065
  return await runDevCommand(rest, io, {
@@ -6200,11 +6081,11 @@ async function runBuddyCli(args, io, options = {}) {
6200
6081
  }
6201
6082
  let route = routeFromMode(parsed.mode);
6202
6083
  if (route === void 0 && !io.canPrompt) requireModeForNonInteractive();
6203
- const cwd = resolve15(options.cwd ?? process.cwd());
6084
+ const cwd = resolve14(options.cwd ?? process.cwd());
6204
6085
  await assertInitializableBuddyTarget(cwd);
6205
6086
  if (parsed.directory !== void 0) {
6206
6087
  if (!parsed.directory.trim()) throw new CliUsageError("--directory \u4E0D\u80FD\u4E3A\u7A7A");
6207
- await assertInitializableBuddyTarget(resolve15(cwd, parsed.directory));
6088
+ await assertInitializableBuddyTarget(resolve14(cwd, parsed.directory));
6208
6089
  }
6209
6090
  await authenticate(options);
6210
6091
  await resumeProjectArguments(parsed, cwd, options);
@@ -6346,7 +6227,6 @@ export {
6346
6227
  assertOutsideBuddyProject,
6347
6228
  buddyAgentConfig,
6348
6229
  buildAgentEnvironment,
6349
- checkWidgetDelivery,
6350
6230
  combineBuddyProject,
6351
6231
  createBuddyConfig,
6352
6232
  createBuddyDevStarter,
@@ -6357,6 +6237,7 @@ export {
6357
6237
  isAbortLike,
6358
6238
  isSafeProjectRelativePath,
6359
6239
  isWindowsReservedPathSegment,
6240
+ latestRuntimeTemplate,
6360
6241
  normalizePlatformUrl,
6361
6242
  openExternalUrl,
6362
6243
  parseBuddyAgentConfig,
@@ -6384,7 +6265,6 @@ export {
6384
6265
  throwIfDevAborted,
6385
6266
  validateBuddyAgentConfig,
6386
6267
  validateBuddyConfig,
6387
- validateBuddyProjectManifest,
6388
- widgetDeliverySummary
6268
+ validateBuddyProjectManifest
6389
6269
  };
6390
6270
  //# sourceMappingURL=core.js.map