@my-life-buddies/cli 0.21.0 → 0.22.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,6 +1,233 @@
1
+ // packages/cli-core/src/dev/project-env.ts
2
+ import { constants } from "node:fs";
3
+ import { open, rename, unlink } from "node:fs/promises";
4
+ import { randomUUID } from "node:crypto";
5
+ import { join } from "node:path";
6
+ import { parseEnv } from "node:util";
7
+
8
+ // packages/cli-core/src/platform-url.ts
9
+ var DEFAULT_MLB_TEST_URL = "https://47.116.168.81";
10
+ var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
11
+ function isLegacyEcsGateway(value) {
12
+ try {
13
+ const url = new URL(value);
14
+ return !url.username && !url.password && !url.search && !url.hash && url.pathname === "/" && ["http://47.116.168.81:8788", "http://47.116.168.81"].includes(url.origin);
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+ function normalizePlatformUrl(value) {
20
+ const url = new URL(value);
21
+ if (url.username || url.password || url.search || url.hash) {
22
+ throw new TypeError("\u5E73\u53F0\u5730\u5740\u4E0D\u80FD\u5305\u542B credentials\u3001query \u6216 fragment");
23
+ }
24
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname))) {
25
+ throw new TypeError(`\u5E73\u53F0\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1BHTTP \u4EC5\u5141\u8BB8\u672C\u673A\u5F00\u53D1`);
26
+ }
27
+ if (!url.pathname.endsWith("/")) url.pathname += "/";
28
+ return url;
29
+ }
30
+ function resolvePlatformUrl(options = {}) {
31
+ const env = options.env ?? process.env;
32
+ const target = new URL(DEFAULT_MLB_TEST_URL);
33
+ const settings = {
34
+ "--app-server": options.override,
35
+ MLB_GATEWAY_URL: env.MLB_GATEWAY_URL,
36
+ BUDDY_APP_SERVER_URL: env.BUDDY_APP_SERVER_URL,
37
+ BUDDY_DEV_APP_SERVER_URL: env.BUDDY_DEV_APP_SERVER_URL
38
+ };
39
+ for (const [name, value] of Object.entries(settings)) {
40
+ if (value === void 0) continue;
41
+ let url;
42
+ try {
43
+ url = normalizePlatformUrl(isLegacyEcsGateway(value) ? target : value);
44
+ } catch {
45
+ throw new TypeError(`${name} \u65E0\u6548\uFF1B\u6B63\u5F0F\u7248 buddy-cli \u56FA\u5B9A\u8FDE\u63A5 ${DEFAULT_MLB_TEST_URL}\u3002${name === "--app-server" ? "\u8BF7\u79FB\u9664 --app-server \u53C2\u6570" : `\u8BF7 unset ${name}`} \u540E\u91CD\u8BD5\u3002`);
46
+ }
47
+ if (url.href !== target.href) {
48
+ throw new TypeError(`${name} \u4E0E\u6B63\u5F0F\u7248\u5E73\u53F0\u4E0D\u4E00\u81F4\uFF1Bbuddy-cli \u56FA\u5B9A\u8FDE\u63A5 ECS Test\uFF08${DEFAULT_MLB_TEST_URL}\uFF09\u3002\u8BF7\u79FB\u9664\u51B2\u7A81\u53C2\u6570\u6216\u73AF\u5883\u53D8\u91CF\uFF1B\u5176\u4ED6\u73AF\u5883\u7684\u5DE5\u7A0B\u8BF7\u4F7F\u7528\u5BF9\u5E94 CLI\uFF0C\u4E0D\u8981\u590D\u5236\u5176 Token\u3002`);
49
+ }
50
+ }
51
+ resolveDeveloperWebUrl(target, env.BUDDY_DEVELOPER_WEB_URL);
52
+ return target;
53
+ }
54
+ function resolveDeveloperWebUrl(platformUrl, override) {
55
+ const target = new URL("/developer/", DEFAULT_MLB_TEST_URL);
56
+ let url;
57
+ try {
58
+ url = normalizePlatformUrl(override ?? target);
59
+ } catch {
60
+ throw new TypeError("\u5F00\u53D1\u8005\u540E\u53F0\u5730\u5740\u65E0\u6548\uFF0C\u8BF7\u79FB\u9664 BUDDY_DEVELOPER_WEB_URL / --developer-web \u540E\u91CD\u8BD5\u3002");
61
+ }
62
+ if (platformUrl.href !== new URL(DEFAULT_MLB_TEST_URL).href || url.href !== target.href) {
63
+ throw new TypeError("\u5F00\u53D1\u8005\u540E\u53F0\u4E0E\u6B63\u5F0F\u7248\u56FA\u5B9A\u5E73\u53F0\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u79FB\u9664 BUDDY_DEVELOPER_WEB_URL / --developer-web\uFF1B\u6B63\u5F0F\u7248\u53EA\u8FDE\u63A5 ECS Test \u7684 /developer/\u3002");
64
+ }
65
+ return target;
66
+ }
67
+
68
+ // packages/cli-core/src/dev/errors.ts
69
+ var BuddyDevError = class extends Error {
70
+ /** Only explicitly safe, developer-facing explanations may be shown in Preview. */
71
+ publicMessage;
72
+ code;
73
+ phase;
74
+ retryable;
75
+ constructor(options) {
76
+ super(options.message, options.cause === void 0 ? void 0 : { cause: options.cause });
77
+ this.name = "BuddyDevError";
78
+ this.publicMessage = options.publicMessage;
79
+ this.code = options.code;
80
+ this.phase = options.phase;
81
+ this.retryable = options.retryable ?? false;
82
+ }
83
+ };
84
+ function isAbortLike(error2) {
85
+ return error2 instanceof DOMException && error2.name === "AbortError" || error2 instanceof Error && error2.name === "AbortError";
86
+ }
87
+ function abortedDevError(signal) {
88
+ return new BuddyDevError({
89
+ code: "DEV_ABORTED",
90
+ phase: "stop",
91
+ message: "\u642D\u642D DEV \u542F\u52A8\u5DF2\u53D6\u6D88\u3002",
92
+ ...signal?.reason === void 0 ? {} : { cause: signal.reason }
93
+ });
94
+ }
95
+ function throwIfDevAborted(signal) {
96
+ if (signal?.aborted) throw abortedDevError(signal);
97
+ }
98
+
99
+ // packages/cli-core/src/dev/project-env.ts
100
+ function invalid(message) {
101
+ return new BuddyDevError({ code: "DEV_CONFIG_INVALID", phase: "config", message, publicMessage: message });
102
+ }
103
+ async function readLocalFile(path) {
104
+ let file;
105
+ try {
106
+ file = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
107
+ const stat2 = await file.stat();
108
+ if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > 256 * 1024) throw invalid("\u672C\u5730\u914D\u7F6E\u5FC5\u987B\u662F\u5C0F\u4E8E 256 KB \u7684\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u94FE\u63A5\u3002");
109
+ return await file.readFile("utf8");
110
+ } catch (cause) {
111
+ if (cause.code === "ENOENT") return "";
112
+ if (cause instanceof BuddyDevError) throw cause;
113
+ throw invalid("\u65E0\u6CD5\u8BFB\u53D6\u5DE5\u7A0B\u672C\u5730\u914D\u7F6E\uFF0C\u8BF7\u68C0\u67E5 .env \u548C .gitignore \u7684\u6587\u4EF6\u7C7B\u578B\u4E0E\u6743\u9650\u3002");
114
+ } finally {
115
+ await file?.close();
116
+ }
117
+ }
118
+ async function readProjectEnvironment(projectRoot) {
119
+ const source = await readLocalFile(join(projectRoot, ".env"));
120
+ let values;
121
+ try {
122
+ values = parseEnv(source);
123
+ } catch {
124
+ throw invalid("\u5DE5\u7A0B .env \u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002");
125
+ }
126
+ return values;
127
+ }
128
+ function gatewayNeedsRefresh(value, gatewayUrl) {
129
+ if (value) {
130
+ if (isLegacyEcsGateway(value)) {
131
+ if (gatewayUrl.href === `${DEFAULT_MLB_TEST_URL}/`) return true;
132
+ throw invalid(".env \u4FDD\u5B58\u7684\u662F\u65E7\u516C\u5171\u73AF\u5883\u5730\u5740\uFF0C\u4E0E\u672C\u6B21\u5E73\u53F0\u4E0D\u540C\uFF1B\u8BF7\u4F7F\u7528\u5BF9\u5E94\u73AF\u5883\u7684 CLI\u3002\u8FC1\u79FB\u5230\u516C\u5171\u5E73\u53F0\u65F6\uFF0C\u8BF7\u5728\u65B0\u76EE\u5F55\u7528\u6B63\u5F0F CLI \u91CD\u65B0\u767B\u8BB0\u642D\u5B50\uFF0C\u518D\u590D\u5236\u4E1A\u52A1\u4EE3\u7801\uFF1B\u4E0D\u8981\u590D\u5236 .env\u3001buddyId \u6216\u51ED\u636E\u3002");
133
+ }
134
+ let gateway;
135
+ try {
136
+ gateway = normalizePlatformUrl(value);
137
+ } catch {
138
+ throw invalid(".env \u4E2D\u7684 MLB_GATEWAY_URL \u65E0\u6548\uFF1B\u8BF7\u4FEE\u6B63\u5730\u5740\uFF1B--refresh-token \u53EA\u80FD\u5237\u65B0\u540C\u4E00\u73AF\u5883\u7684\u51ED\u636E\uFF0C\u4E0D\u80FD\u5207\u6362\u5E73\u53F0\u3002");
139
+ }
140
+ if (gateway.href !== gatewayUrl.href) throw invalid(".env \u7684\u5E73\u53F0\u5730\u5740\u4E0E\u672C\u6B21\u542F\u52A8\u4E0D\u540C\uFF1B\u8BF7\u4F7F\u7528\u5BF9\u5E94\u73AF\u5883\u7684 CLI\u3002\u8FC1\u79FB\u5230\u516C\u5171\u5E73\u53F0\u65F6\uFF0C\u8BF7\u5728\u65B0\u76EE\u5F55\u7528\u6B63\u5F0F CLI \u91CD\u65B0\u767B\u8BB0\u642D\u5B50\uFF0C\u518D\u590D\u5236\u4E1A\u52A1\u4EE3\u7801\uFF1B\u4E0D\u8981\u590D\u5236 .env\u3001buddyId \u6216\u51ED\u636E\u3002--refresh-token \u4E0D\u80FD\u5207\u6362\u5E73\u53F0\u3002");
141
+ }
142
+ return false;
143
+ }
144
+ async function checkProjectGateway(projectRoot, gatewayUrl, options = {}) {
145
+ const values = await readProjectEnvironment(projectRoot);
146
+ if (gatewayNeedsRefresh(values.MLB_GATEWAY_URL, gatewayUrl)) {
147
+ options.report?.("\u68C0\u6D4B\u5230\u5DE5\u7A0B\u4F7F\u7528\u65E7 ECS \u5730\u5740\uFF1B\u542F\u52A8 DEV \u65F6\u5C06\u6821\u9A8C\u642D\u5B50\u5F52\u5C5E\uFF0C\u5E76\u81EA\u52A8\u66F4\u65B0\u5730\u5740\u548C\u5F00\u53D1\u51ED\u636E\u3002");
148
+ }
149
+ }
150
+ async function projectBuddyToken(projectRoot, gatewayUrl) {
151
+ const values = await readProjectEnvironment(projectRoot);
152
+ if (gatewayNeedsRefresh(values.MLB_GATEWAY_URL, gatewayUrl) || !values.BUDDY_TOKEN) return void 0;
153
+ if (!values.BUDDY_TOKEN.trim() || /[\u0000-\u001f\u007f]/u.test(values.BUDDY_TOKEN)) throw invalid(".env \u4E2D\u7684\u5F00\u53D1\u4EE4\u724C\u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u3002");
154
+ return values.BUDDY_TOKEN;
155
+ }
156
+ function quote(value) {
157
+ if (/[\u0000-\u001f\u007f]/u.test(value)) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26\u3002");
158
+ const delimiter = ["'", '"', "`"].find((character) => !value.includes(character));
159
+ if (!delimiter) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u5305\u542B\u65E0\u6CD5\u5199\u5165 .env \u7684\u5F15\u53F7\u7EC4\u5408\u3002");
160
+ return `${delimiter}${value}${delimiter}`;
161
+ }
162
+ function updateValues(source, values) {
163
+ const assignment = /^[\t ]*(?:export[\t ]+)?([A-Za-z_][A-Za-z0-9_]*)[\t ]*=[\t ]*/gm;
164
+ let output = "", cursor = 0, match;
165
+ const written = /* @__PURE__ */ new Set();
166
+ while (match = assignment.exec(source)) {
167
+ const valueStart = assignment.lastIndex;
168
+ let end = source.indexOf("\n", valueStart);
169
+ if (end < 0) end = source.length;
170
+ let commentStart = valueStart;
171
+ const delimiter = source[valueStart];
172
+ if (delimiter && ["'", '"', "`"].includes(delimiter)) {
173
+ const close = source.indexOf(delimiter, valueStart + 1);
174
+ if (close < 0) throw invalid(".env \u4E2D\u6709\u672A\u95ED\u5408\u7684\u5F15\u53F7\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002");
175
+ commentStart = close + 1;
176
+ end = source.indexOf("\n", close + 1);
177
+ if (end < 0) end = source.length;
178
+ }
179
+ assignment.lastIndex = end;
180
+ const name = match[1];
181
+ if (!(name in values)) continue;
182
+ const comment = source.slice(commentStart, end).match(/[\t ]*#[^\r\n]*/u)?.[0] ?? "";
183
+ output += source.slice(cursor, match.index);
184
+ output += written.has(name) || values[name] === void 0 ? comment : `${name}=${quote(values[name])}${comment ? ` ${comment.trimStart()}` : ""}`;
185
+ if (source[end - 1] === "\r") output += "\r";
186
+ cursor = end;
187
+ written.add(name);
188
+ }
189
+ output += source.slice(cursor);
190
+ const newline = source.includes("\r\n") ? "\r\n" : "\n";
191
+ for (const [name, value] of Object.entries(values)) if (value !== void 0 && !written.has(name)) {
192
+ if (output && !output.endsWith("\n")) output += newline;
193
+ output += `${name}=${quote(value)}${newline}`;
194
+ }
195
+ const parsed = parseEnv(output);
196
+ if (Object.entries(values).some(([name, value]) => parsed[name] !== value)) throw invalid("\u65E0\u6CD5\u5B8C\u6574\u66F4\u65B0 .env\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u683C\u5F0F\u3002");
197
+ return output;
198
+ }
199
+ async function replaceFile(path, contents, mode) {
200
+ const temporary = `${path}.${randomUUID()}.tmp`;
201
+ let file;
202
+ try {
203
+ file = await open(temporary, "wx", mode);
204
+ await file.writeFile(contents, "utf8");
205
+ await file.sync();
206
+ await file.close();
207
+ file = void 0;
208
+ await rename(temporary, path);
209
+ } finally {
210
+ await file?.close();
211
+ await unlink(temporary).catch((cause) => {
212
+ if (cause.code !== "ENOENT") throw cause;
213
+ });
214
+ }
215
+ }
216
+ async function writeProjectEnvironment(projectRoot, values) {
217
+ const envPath = join(projectRoot, ".env"), ignorePath = join(projectRoot, ".gitignore");
218
+ const contents = updateValues(await readLocalFile(envPath), { ...values, BUDDY_ID: void 0 });
219
+ const ignored = await readLocalFile(ignorePath);
220
+ if (ignored.trimEnd().split(/\r?\n/u).at(-1) !== "/.env") {
221
+ await replaceFile(ignorePath, `${ignored}${ignored && !ignored.endsWith("\n") ? "\n" : ""}/.env
222
+ `, 420);
223
+ }
224
+ await replaceFile(envPath, contents, 384);
225
+ return contents;
226
+ }
227
+
1
228
  // packages/cli-core/src/config/runtime-update.ts
2
229
  import { readFile as readFile2 } from "node:fs/promises";
3
- import { join as join2 } from "node:path";
230
+ import { join as join3 } from "node:path";
4
231
 
5
232
  // packages/cli-core/src/config/runtime-dependency.ts
6
233
  var BUDDY_RUNTIME_PACKAGE = "@my-life-buddies/buddy-runtime";
@@ -23,54 +250,28 @@ function runtimeUsesEnvironmentIdentity(pkg) {
23
250
 
24
251
  // packages/cli-core/src/config/runtime-package.ts
25
252
  import { execFile } from "node:child_process";
26
- import { lstat, mkdir, mkdtemp, readFile, rename, rm, writeFile } from "node:fs/promises";
253
+ import { lstat, mkdir, mkdtemp, readFile, rename as rename2, rm, writeFile } from "node:fs/promises";
27
254
  import { homedir } from "node:os";
28
- import { join } from "node:path";
255
+ import { join as join2 } from "node:path";
29
256
  import { promisify } from "node:util";
30
257
  var RUNTIME_REGISTRY = "https://registry.npmjs.org/";
31
258
  var execute = promisify(execFile);
32
259
  async function latestRuntimeVersion(options = {}) {
33
- return resolveRuntimeVersion("latest", options);
34
- }
35
- async function runtimeMetadata(suffix, options) {
36
260
  options.signal?.throwIfAborted();
37
261
  const timeout = AbortSignal.timeout(1e4);
38
262
  const signal = options.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
39
- const response = await (options.fetch ?? globalThis.fetch)(`${RUNTIME_REGISTRY}${encodeURIComponent(BUDDY_RUNTIME_PACKAGE)}${suffix}`, {
263
+ const response = await (options.fetch ?? globalThis.fetch)(`${RUNTIME_REGISTRY}${encodeURIComponent(BUDDY_RUNTIME_PACKAGE)}/latest`, {
40
264
  signal,
41
265
  headers: { Accept: "application/json" },
42
266
  redirect: "error"
43
267
  });
44
268
  if (!response.ok) throw new Error(`npm \u8FD4\u56DE HTTP ${response.status}`);
45
- return response.json();
46
- }
47
- async function resolveRuntimeVersion(selector, options = {}) {
48
- if (!isExactRuntimeVersion(selector) && selector !== "latest" && selector !== "dev") {
49
- throw new Error("Runtime \u7248\u672C\u5FC5\u987B\u662F\u51C6\u786E\u7248\u672C\u3001latest \u6216 dev\uFF0C\u4E0D\u80FD\u4F7F\u7528\u8303\u56F4\u3001\u8DEF\u5F84\u6216 URL");
50
- }
51
- const metadata = await runtimeMetadata(`/${encodeURIComponent(selector)}`, options);
52
- if (metadata?.name !== BUDDY_RUNTIME_PACKAGE || !isExactRuntimeVersion(metadata.version) || selector === "latest" && metadata.version.includes("-") || isExactRuntimeVersion(selector) && metadata.version !== selector) {
53
- throw new Error(`npm ${selector} \u672A\u8FD4\u56DE\u6B64 Runtime \u7684\u51C6\u786E${selector === "latest" ? "\u7A33\u5B9A" : ""}\u7248\u672C`);
269
+ const metadata = await response.json();
270
+ if (metadata?.name !== BUDDY_RUNTIME_PACKAGE || !isExactRuntimeVersion(metadata.version) || metadata.version.includes("-")) {
271
+ throw new Error("npm latest \u672A\u8FD4\u56DE\u6B64 Runtime \u7684\u51C6\u786E\u7A33\u5B9A\u7248\u672C");
54
272
  }
55
273
  return metadata.version;
56
274
  }
57
- async function runtimeReleaseChoices(options = {}) {
58
- const metadata = await runtimeMetadata("", options);
59
- const latest = metadata?.["dist-tags"]?.latest;
60
- const dev = metadata?.["dist-tags"]?.dev;
61
- if (metadata?.name !== BUDDY_RUNTIME_PACKAGE || !isExactRuntimeVersion(latest) || latest.includes("-") || !metadata.versions || !(latest in metadata.versions)) throw new Error("npm \u672A\u8FD4\u56DE\u6709\u6548\u7684 Runtime \u7248\u672C\u5217\u8868");
62
- const versions = Object.keys(metadata.versions).filter(isExactRuntimeVersion).sort((a, b) => b.localeCompare(a, "en", { numeric: true }));
63
- return { latest, ...isExactRuntimeVersion(dev) && dev in metadata.versions ? { dev } : {}, versions };
64
- }
65
- async function runtimeSelectionPrompt(options = {}) {
66
- const releases = await runtimeReleaseChoices(options);
67
- return [
68
- "\u8BF7\u5148\u8BE2\u95EE\u5F00\u53D1\u8005\u9009\u62E9 Runtime \u7248\u672C\uFF0C\u518D\u4F20 --runtime-version <\u51C6\u786E\u7248\u672C|latest|dev>\uFF1B\u4E0D\u8981\u66FF\u5F00\u53D1\u8005\u9ED8\u8BA4\u9009\u62E9\u3002",
69
- `\u6700\u65B0\u7A33\u5B9A\u7248\uFF08\u63A8\u8350\uFF09\uFF1A${releases.latest}\uFF08latest\uFF09`,
70
- ...releases.dev ? [`\u6700\u65B0\u6D4B\u8BD5\u7248\uFF1A${releases.dev}\uFF08dev\uFF09`] : [],
71
- `\u5176\u4ED6\u5DF2\u53D1\u5E03\u7248\u672C\uFF1A${releases.versions.join("\u3001")}`
72
- ].join("\n");
73
- }
74
275
  async function cachedLatestRuntimeRoot(options = {}) {
75
276
  options.report?.("\u6B63\u5728\u67E5\u8BE2\u516C\u5171 npm \u7684\u6700\u65B0 Runtime\u2026");
76
277
  const version = await latestRuntimeVersion(options);
@@ -78,8 +279,8 @@ async function cachedLatestRuntimeRoot(options = {}) {
78
279
  }
79
280
  async function cachedRuntimeRoot(version, options = {}) {
80
281
  if (!isExactRuntimeVersion(version)) throw new Error("Runtime \u7F13\u5B58\u9700\u8981\u51C6\u786E\u7248\u672C");
81
- const cache = options.cacheDirectory ?? join(homedir(), ".cache", "buddy-cli", "runtimes");
82
- const destination = join(cache, version);
282
+ const cache = options.cacheDirectory ?? join2(homedir(), ".cache", "buddy-cli", "runtimes");
283
+ const destination = join2(cache, version);
83
284
  let cacheExists = false;
84
285
  try {
85
286
  await lstat(destination);
@@ -89,8 +290,8 @@ async function cachedRuntimeRoot(version, options = {}) {
89
290
  }
90
291
  if (cacheExists) {
91
292
  try {
92
- const pkg = JSON.parse(await readFile(join(destination, "package.json"), "utf8"));
93
- const installed2 = JSON.parse(await readFile(join(destination, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"), "utf8"));
293
+ const pkg = JSON.parse(await readFile(join2(destination, "package.json"), "utf8"));
294
+ const installed2 = JSON.parse(await readFile(join2(destination, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"), "utf8"));
94
295
  if (runtimeDependencyVersion(pkg) === version && installed2.version === version) return destination;
95
296
  throw new Error("\u7F13\u5B58\u7248\u672C\u4E0D\u5339\u914D");
96
297
  } catch (cause) {
@@ -98,15 +299,15 @@ async function cachedRuntimeRoot(version, options = {}) {
98
299
  }
99
300
  }
100
301
  await mkdir(cache, { recursive: true });
101
- const temporaryRoot = await mkdtemp(join(cache, `.install-${version}-`));
302
+ const temporaryRoot = await mkdtemp(join2(cache, `.install-${version}-`));
102
303
  try {
103
- await writeFile(join(temporaryRoot, "package.json"), JSON.stringify({
304
+ await writeFile(join2(temporaryRoot, "package.json"), JSON.stringify({
104
305
  name: "buddy-runtime-catalog",
105
306
  private: true,
106
307
  type: "module",
107
308
  dependencies: { [BUDDY_RUNTIME_PACKAGE]: version }
108
309
  }));
109
- const userConfig = join(temporaryRoot, ".npmrc");
310
+ const userConfig = join2(temporaryRoot, ".npmrc");
110
311
  await writeFile(userConfig, `registry=${RUNTIME_REGISTRY}
111
312
  `);
112
313
  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`);
@@ -124,11 +325,11 @@ async function cachedRuntimeRoot(version, options = {}) {
124
325
  "--fetch-retries=0",
125
326
  "--fetch-timeout=20000"
126
327
  ], { cwd: temporaryRoot, signal: options.signal, timeout: 18e4 });
127
- const installed2 = JSON.parse(await readFile(join(temporaryRoot, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"), "utf8"));
328
+ const installed2 = JSON.parse(await readFile(join2(temporaryRoot, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"), "utf8"));
128
329
  if (installed2.version !== version) throw new Error(`\u7F13\u5B58\u7684 Runtime \u7248\u672C\u4E0E\u9009\u5B9A\u7684 ${version} \u4E0D\u4E00\u81F4`);
129
330
  options.signal?.throwIfAborted();
130
331
  try {
131
- await rename(temporaryRoot, destination);
332
+ await rename2(temporaryRoot, destination);
132
333
  } catch (cause) {
133
334
  if (!["EEXIST", "ENOTEMPTY"].includes(cause.code ?? "")) throw cause;
134
335
  }
@@ -138,59 +339,17 @@ async function cachedRuntimeRoot(version, options = {}) {
138
339
  }
139
340
  }
140
341
 
141
- // packages/cli-core/src/platform-url.ts
142
- var DEFAULT_MLB_TEST_URL = "https://47.116.168.81";
143
- var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
144
- function normalizePlatformUrl(value) {
145
- const url = new URL(value);
146
- if (url.username || url.password || url.search || url.hash) {
147
- throw new TypeError("\u5E73\u53F0\u5730\u5740\u4E0D\u80FD\u5305\u542B credentials\u3001query \u6216 fragment");
148
- }
149
- if (url.protocol !== "https:" && !(url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname))) {
150
- throw new TypeError(`\u5E73\u53F0\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1BHTTP \u4EC5\u5141\u8BB8\u672C\u673A\u5F00\u53D1`);
151
- }
152
- if (!url.pathname.endsWith("/")) url.pathname += "/";
153
- return url;
154
- }
155
- function resolvePlatformUrl(options = {}) {
156
- const env = options.env ?? process.env;
157
- const legacy = options.development ? env.BUDDY_DEV_APP_SERVER_URL ?? env.BUDDY_APP_SERVER_URL : env.BUDDY_APP_SERVER_URL ?? env.BUDDY_DEV_APP_SERVER_URL;
158
- const url = normalizePlatformUrl(options.override ?? env.MLB_GATEWAY_URL ?? legacy ?? DEFAULT_MLB_TEST_URL);
159
- if (url.pathname !== "/") throw new TypeError("\u5E73\u53F0\u5730\u5740\u53EA\u9700\u534F\u8BAE\u3001\u57DF\u540D\u548C\u7AEF\u53E3\uFF0C\u4E0D\u5E94\u5305\u542B /cli\u3001/developer \u6216\u5176\u4ED6\u8DEF\u5F84");
160
- return url;
161
- }
162
- function resolveDeveloperWebUrl(platformUrl, override) {
163
- const url = normalizePlatformUrl(override ?? new URL("/developer/", platformUrl));
164
- if (url.origin !== platformUrl.origin) {
165
- throw new TypeError("\u5F00\u53D1\u8005\u540E\u53F0\u4E0E MLB \u7F51\u5173\u5730\u5740\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u79FB\u9664\u6216\u66F4\u65B0 BUDDY_DEVELOPER_WEB_URL / --developer-web\uFF0C\u4F7F\u7528\u540C\u4E00\u5E73\u53F0");
166
- }
167
- return url;
168
- }
169
- function allowsRuntimeVersionSelection(options = {}) {
170
- const env = options.env ?? process.env;
171
- if (!env.MLB_GATEWAY_URL?.trim()) return false;
172
- const configured = resolvePlatformUrl({ env });
173
- return configured.origin !== new URL(DEFAULT_MLB_TEST_URL).origin && (options.platformUrl === void 0 || options.platformUrl.origin === configured.origin);
174
- }
175
-
176
342
  // packages/cli-core/src/config/runtime-update.ts
177
343
  async function projectRuntimeVersion(root) {
178
344
  try {
179
- return runtimeDependencyVersion(JSON.parse(await readFile2(join2(root, "package.json"), "utf8")));
345
+ return runtimeDependencyVersion(JSON.parse(await readFile2(join3(root, "package.json"), "utf8")));
180
346
  } catch (cause) {
181
347
  if (cause.code === "ENOENT") return void 0;
182
348
  throw cause;
183
349
  }
184
350
  }
185
- async function runtimeVersionStatus(project, latest, selected = false) {
351
+ async function runtimeVersionStatus(project, latest) {
186
352
  const current = project ? await projectRuntimeVersion(project) : void 0;
187
- if (selected) return {
188
- projectRuntimeVersion: current ?? null,
189
- latestRuntimeVersion: null,
190
- selectedRuntimeVersion: latest,
191
- versionStatus: !project ? "no_project" : current === latest ? "selected" : "unconfigured",
192
- adaptationRequired: !!project && current !== latest
193
- };
194
353
  let versionStatus;
195
354
  if (!project) versionStatus = "no_project";
196
355
  else if (!current) versionStatus = "unconfigured";
@@ -210,10 +369,6 @@ async function runtimeVersionStatus(project, latest, selected = false) {
210
369
  }
211
370
  function reportRuntimeVersion(status, report) {
212
371
  if (status.versionStatus === "no_project") return;
213
- if (status.selectedRuntimeVersion !== void 0) {
214
- report(status.versionStatus === "selected" ? `Runtime \u7248\u672C\uFF1A\u5DE5\u7A0B ${status.projectRuntimeVersion}\uFF0C\u6CBF\u7528\u5DE5\u7A0B\u9009\u5B9A\u7248\u672C\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u5207\u6362\u5230 latest \u6216\u65B0\u7684\u6D4B\u8BD5\u7248\u3002` : `Runtime \u76EE\u5F55\u4F7F\u7528\u9009\u5B9A\u7248\u672C ${status.selectedRuntimeVersion}\uFF1B\u5DE5\u7A0B\u5C1A\u672A\u56FA\u5B9A\u51C6\u786E\u7248\u672C\uFF0C\u751F\u6210\u6216\u5B89\u88C5\u4F9D\u8D56\u540E\u518D\u542F\u52A8 DEV\u3002`);
215
- return;
216
- }
217
372
  report(`Runtime \u7248\u672C\uFF1A\u5DE5\u7A0B ${status.projectRuntimeVersion ?? "\u672A\u9501\u5B9A\u51C6\u786E\u7248\u672C"}\uFF0Cnpm \u6700\u65B0 ${status.latestRuntimeVersion}\u3002`);
218
373
  if (status.adaptationRequired) {
219
374
  report("\u8BF7\u7531\u4F60\u6216\u5F00\u53D1 Agent \u66F4\u65B0\u4F9D\u8D56\u5E76\u9002\u914D\uFF1A\u68C0\u67E5\u65B0\u7248 Runtime \u7684\u542F\u52A8\u53C2\u6570\u3001\u6A21\u578B\u3001datasets\u3001\u5DE5\u5177\u53CA Hook\uFF0C\u5B8C\u6210\u9002\u914D\u540E\u9A8C\u8BC1 DEV\u3002CLI \u672A\u4FEE\u6539\u5DE5\u7A0B\u4F9D\u8D56\u6216\u914D\u7F6E\uFF1BDEV \u542F\u52A8\u3001\u81EA\u52A8\u91CD\u8F7D\u548C push \u5FC5\u987B\u901A\u8FC7\u6700\u65B0 Runtime \u68C0\u67E5\u3002");
@@ -223,69 +378,13 @@ function reportRuntimeVersion(status, report) {
223
378
  async function checkRuntimeUpdate(root, report, options = {}) {
224
379
  options.signal?.throwIfAborted();
225
380
  try {
226
- if (allowsRuntimeVersionSelection(options)) {
227
- const current = await projectRuntimeVersion(root);
228
- if (!current) {
229
- report("\u5DE5\u7A0B\u5C1A\u672A\u56FA\u5B9A Runtime \u51C6\u786E\u7248\u672C\uFF1B\u751F\u6210 Runtime \u5DE5\u7A0B\u524D\u8BF7\u5148\u9009\u62E9\u7248\u672C\u3002\u5DF2\u6709\u5DE5\u7A0B\u8BF7\u4FEE\u6B63\u4F9D\u8D56\u58F0\u660E\u5E76\u5B89\u88C5\u3002");
230
- return;
231
- }
232
- const selected = await resolveRuntimeVersion(current, options);
233
- reportRuntimeVersion(await runtimeVersionStatus(root, selected, true), report);
234
- options.signal?.throwIfAborted();
235
- return;
236
- }
237
381
  const latest = await latestRuntimeVersion(options);
238
382
  const status = await runtimeVersionStatus(root, latest);
239
383
  options.signal?.throwIfAborted();
240
384
  reportRuntimeVersion(status, report);
241
385
  } catch (cause) {
242
386
  options.signal?.throwIfAborted();
243
- report(`\u65E0\u6CD5\u68C0\u67E5 Runtime \u66F4\u65B0\uFF1A${cause instanceof Error ? cause.message : String(cause)}\u3002\u672C\u6B21\u672A\u786E\u8BA4${allowsRuntimeVersionSelection(options) ? "\u9009\u5B9A\u7248\u672C\u662F\u5426\u53EF\u7528" : "\u662F\u5426\u4E3A\u6700\u65B0\u7248"}\uFF1B\u53EF\u7EE7\u7EED\u67E5\u770B\u6216\u4FEE\u6539\u5DE5\u7A0B\uFF0CDEV \u542F\u52A8\u548C push \u4F1A\u53E6\u884C\u4E25\u683C\u68C0\u67E5\u3002`);
244
- }
245
- }
246
-
247
- // packages/cli-core/src/init/runtime-selection.ts
248
- import { readFile as readFile3 } from "node:fs/promises";
249
- import { join as join3 } from "node:path";
250
- var RuntimeSelectionError = class extends Error {
251
- };
252
- async function selectInitRuntime(root, requested, io, options = {}) {
253
- if (!allowsRuntimeVersionSelection(options)) {
254
- if (requested !== void 0) throw new RuntimeSelectionError("\u672A\u77E5 init \u53C2\u6570 --runtime-version");
255
- return void 0;
256
- }
257
- let pkg;
258
- try {
259
- pkg = JSON.parse(await readFile3(join3(root, "package.json"), "utf8"));
260
- } catch (cause) {
261
- if (cause.code !== "ENOENT") throw cause;
262
- }
263
- const existing = runtimeDependencyVersion(pkg);
264
- if (pkg?.dependencies?.[BUDDY_RUNTIME_PACKAGE] !== void 0) {
265
- if (!existing) throw new RuntimeSelectionError("\u5DF2\u6709\u5DE5\u7A0B\u7684 Runtime \u672A\u56FA\u5B9A\u51C6\u786E\u7248\u672C\uFF0C\u8BF7\u5148\u7528 npm install --save-exact \u5B89\u88C5\u9009\u5B9A\u7248\u672C\u5E76\u66F4\u65B0\u9501\u6587\u4EF6\u3002");
266
- if (requested !== void 0 && requested !== existing) throw new RuntimeSelectionError(`\u5DE5\u7A0B\u5DF2\u56FA\u5B9A Runtime ${existing}\uFF1Binit \u4E0D\u5207\u6362\u5DF2\u6709\u4F9D\u8D56\u3002\u5207\u6362\u7248\u672C\u8BF7\u5148\u5411\u5F00\u53D1\u8005\u786E\u8BA4\uFF0C\u518D\u7528 npm install --save-exact \u5B89\u88C5\u51C6\u786E\u7248\u672C\u5E76\u5B8C\u6210\u9002\u914D\u3002`);
267
- return existing;
268
- }
269
- try {
270
- let selector = requested;
271
- if (!selector) {
272
- if (!io.canPrompt) throw new RuntimeSelectionError(await runtimeSelectionPrompt(options));
273
- const releases = await runtimeReleaseChoices(options);
274
- selector = await io.select("\u8FD9\u4E2A\u642D\u5B50\u4F7F\u7528\u54EA\u4E2A Runtime \u7248\u672C\uFF1F", [
275
- { value: releases.latest, label: `\u6700\u65B0\u7A33\u5B9A\u7248 ${releases.latest}\uFF08\u63A8\u8350\uFF09` },
276
- ...releases.dev ? [{ value: releases.dev, label: `\u6700\u65B0\u6D4B\u8BD5\u7248 ${releases.dev}` }] : [],
277
- { value: "other", label: "\u6307\u5B9A\u5176\u4ED6\u5DF2\u53D1\u5E03\u7248\u672C" }
278
- ]);
279
- if (selector === "other") {
280
- io.write(`\u53EF\u7528\u7248\u672C\uFF1A${releases.versions.join("\u3001")}`);
281
- selector = (await io.input("\u8F93\u5165 Runtime \u7684\u51C6\u786E\u7248\u672C")).trim();
282
- }
283
- }
284
- return await resolveRuntimeVersion(selector, options);
285
- } catch (cause) {
286
- options.signal?.throwIfAborted();
287
- if (cause instanceof RuntimeSelectionError || cause instanceof Error && cause.name === "PromptCancelledError") throw cause;
288
- throw new RuntimeSelectionError(`\u65E0\u6CD5\u9009\u62E9 Runtime\uFF1A${cause instanceof Error ? cause.message : String(cause)}\u3002\u8BF7\u4FEE\u590D\u540E\u91CD\u8BD5\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u9009\u62E9\u5176\u4ED6\u7248\u672C\u3002`);
387
+ report(`\u65E0\u6CD5\u68C0\u67E5 Runtime \u66F4\u65B0\uFF1A${cause instanceof Error ? cause.message : String(cause)}\u3002\u672C\u6B21\u672A\u786E\u8BA4\u662F\u5426\u4E3A\u6700\u65B0\u6B63\u5F0F\u7248\uFF1B\u53EF\u7EE7\u7EED\u67E5\u770B\u6216\u4FEE\u6539\u5DE5\u7A0B\uFF0CDEV \u542F\u52A8\u548C push \u4F1A\u53E6\u884C\u4E25\u683C\u68C0\u67E5\u3002`);
289
388
  }
290
389
  }
291
390
 
@@ -293,13 +392,13 @@ async function selectInitRuntime(root, requested, io, options = {}) {
293
392
  import { resolve as resolve6 } from "node:path";
294
393
 
295
394
  // packages/cli-core/src/config/runtime-catalog.ts
296
- import { readFile as readFile4, realpath } from "node:fs/promises";
395
+ import { readFile as readFile3, realpath } from "node:fs/promises";
297
396
  import { createRequire } from "node:module";
298
397
  import { resolve } from "node:path";
299
398
  import { pathToFileURL } from "node:url";
300
399
  async function loadRuntime(projectRoot) {
301
400
  const packagePath = resolve(projectRoot, "package.json");
302
- const expected = runtimeDependencyVersion(JSON.parse(await readFile4(packagePath, "utf8")));
401
+ const expected = runtimeDependencyVersion(JSON.parse(await readFile3(packagePath, "utf8")));
303
402
  if (!expected) throw new Error(`package.json \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C`);
304
403
  const projectRequire = createRequire(packagePath);
305
404
  let runtimePath;
@@ -308,7 +407,7 @@ async function loadRuntime(projectRoot) {
308
407
  if (await realpath(projectRequire.resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`)) !== installedPath) {
309
408
  throw new Error("Runtime \u5FC5\u987B\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D");
310
409
  }
311
- const installed2 = JSON.parse(await readFile4(installedPath, "utf8"));
410
+ const installed2 = JSON.parse(await readFile3(installedPath, "utf8"));
312
411
  if (installed2.version !== expected) throw new Error(`\u5DF2\u5B89\u88C5 ${installed2.version}\uFF0C\u5DE5\u7A0B\u8981\u6C42 ${expected}`);
313
412
  runtimePath = projectRequire.resolve(BUDDY_RUNTIME_PACKAGE);
314
413
  } catch (cause) {
@@ -359,7 +458,7 @@ async function validateRuntimeDatasets(projectRoot, requirements = []) {
359
458
  }
360
459
 
361
460
  // packages/cli-core/src/project-context.ts
362
- import { lstat as lstat7, realpath as realpath3, readFile as readFile11 } from "node:fs/promises";
461
+ import { lstat as lstat7, realpath as realpath3, readFile as readFile10 } from "node:fs/promises";
363
462
  import { dirname, join as join10, resolve as resolve5 } from "node:path";
364
463
 
365
464
  // packages/cli-core/src/config/index.ts
@@ -367,13 +466,13 @@ import {
367
466
  link,
368
467
  lstat as lstat6,
369
468
  mkdir as mkdir6,
370
- open as open3,
371
- readFile as readFile10,
469
+ open as open4,
470
+ readFile as readFile9,
372
471
  readdir as readdir3,
373
- rename as rename6,
374
- unlink as unlink4
472
+ rename as rename7,
473
+ unlink as unlink5
375
474
  } from "node:fs/promises";
376
- import { randomUUID as randomUUID4 } from "node:crypto";
475
+ import { randomUUID as randomUUID5 } from "node:crypto";
377
476
  import { isAbsolute as isAbsolute2, join as join9, resolve as resolve4, win32 } from "node:path";
378
477
  import { isDeepStrictEqual } from "node:util";
379
478
  import { Ajv2020 } from "ajv/dist/2020.js";
@@ -398,13 +497,13 @@ var buddy_package_schema_default = {
398
497
  };
399
498
 
400
499
  // packages/cli-core/src/init/meta.ts
401
- import { createHash, randomUUID as randomUUID2 } from "node:crypto";
402
- import { lstat as lstat3, mkdir as mkdir4, readFile as readFile7, readdir as readdir2, rename as rename4, unlink as unlink2, writeFile as writeFile4 } from "node:fs/promises";
500
+ import { createHash, randomUUID as randomUUID3 } from "node:crypto";
501
+ import { lstat as lstat3, mkdir as mkdir4, readFile as readFile6, readdir as readdir2, rename as rename5, unlink as unlink3, writeFile as writeFile4 } from "node:fs/promises";
403
502
  import { join as join6, resolve as resolve2 } from "node:path";
404
503
 
405
504
  // packages/cli-core/src/init/skill-package.ts
406
505
  import { execFile as execFile2 } from "node:child_process";
407
- import { lstat as lstat2, mkdir as mkdir2, mkdtemp as mkdtemp2, readFile as readFile5, realpath as realpath2, rename as rename2, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
506
+ import { lstat as lstat2, mkdir as mkdir2, mkdtemp as mkdtemp2, readFile as readFile4, realpath as realpath2, rename as rename3, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
408
507
  import { homedir as homedir2 } from "node:os";
409
508
  import { isAbsolute, join as join4 } from "node:path";
410
509
  import { promisify as promisify2 } from "node:util";
@@ -427,9 +526,9 @@ function checkProtocol(definition3, pkg) {
427
526
  }
428
527
  async function installed(definition3, root, version) {
429
528
  if (!(await lstat2(root)).isDirectory()) throw new Error(`${definition3.label} \u7F13\u5B58\u4E0D\u80FD\u4F7F\u7528\u7B26\u53F7\u94FE\u63A5\u3002`);
430
- const pkg = JSON.parse(await readFile5(join4(root, "package.json"), "utf8"));
529
+ const pkg = JSON.parse(await readFile4(join4(root, "package.json"), "utf8"));
431
530
  checkProtocol(definition3, pkg);
432
- const meta2 = JSON.parse(await readFile5(join4(root, "version.json"), "utf8"));
531
+ const meta2 = JSON.parse(await readFile4(join4(root, "version.json"), "utf8"));
433
532
  if (pkg.version !== version || meta2.version !== version || meta2.workspaceFormat !== definition3.protocol.workspaceFormat) throw new Error(`${definition3.label} Skill \u7248\u672C\u8BB0\u5F55\u4E0D\u4E00\u81F4\u3002`);
434
533
  for (const file of definition3.requiredFiles) {
435
534
  const path = join4(root, file);
@@ -445,7 +544,7 @@ async function cached(definition3, root, lock) {
445
544
  }
446
545
  const skill = join4(root, "node_modules", definition3.name);
447
546
  try {
448
- const record2 = JSON.parse(await readFile5(join4(root, "package-lock.json"), "utf8"));
547
+ const record2 = JSON.parse(await readFile4(join4(root, "package-lock.json"), "utf8"));
449
548
  const entry2 = record2.packages?.[`node_modules/${definition3.name}`];
450
549
  if (entry2?.version !== lock.version || entry2.integrity !== lock.integrity) throw new Error("\u7F13\u5B58\u6821\u9A8C\u8BB0\u5F55\u4E0D\u5339\u914D");
451
550
  await installed(definition3, skill, lock.version);
@@ -462,7 +561,7 @@ async function resolveSkillPackage(definition3, previous, options = {}) {
462
561
  if (local) {
463
562
  if (!isAbsolute(local)) throw new Error(`${definition3.pathEnvironment} \u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002`);
464
563
  const root = await realpath2(local);
465
- const pkg2 = JSON.parse(await readFile5(join4(root, "package.json"), "utf8"));
564
+ const pkg2 = JSON.parse(await readFile4(join4(root, "package.json"), "utf8"));
466
565
  await installed(definition3, root, pkg2.version);
467
566
  options.report?.(`\u4F7F\u7528\u672C\u5730 ${definition3.label} Skill ${pkg2.version}\uFF1A${root}`);
468
567
  return { root, lock: { source: "local", path: root, version: pkg2.version, protocolVersion: 1 } };
@@ -523,7 +622,7 @@ async function resolveSkillPackage(definition3, previous, options = {}) {
523
622
  await cached(definition3, temporary, lock);
524
623
  options.signal?.throwIfAborted();
525
624
  try {
526
- await rename2(temporary, destination);
625
+ await rename3(temporary, destination);
527
626
  } catch (error2) {
528
627
  if (!["EEXIST", "ENOTEMPTY"].includes(error2.code ?? "")) throw error2;
529
628
  }
@@ -547,11 +646,11 @@ var definition = {
547
646
  var resolveAvatarSkill = (previous, options = {}) => resolveSkillPackage(definition, previous, options);
548
647
 
549
648
  // packages/cli-core/src/cloud/avatar.ts
550
- import { open } from "node:fs/promises";
649
+ import { open as open2 } from "node:fs/promises";
551
650
  import { basename } from "node:path";
552
651
  var MAX_BUDDY_AVATAR_BYTES = 5 * 1024 * 1024;
553
652
  async function readBuddyAvatarFile(path) {
554
- const file = await open(path, "r");
653
+ const file = await open2(path, "r");
555
654
  try {
556
655
  const stat2 = await file.stat();
557
656
  if (!stat2.isFile()) throw new Error("\u5934\u50CF\u5FC5\u987B\u662F\u666E\u901A\u56FE\u7247\u6587\u4EF6");
@@ -574,8 +673,8 @@ async function readBuddyAvatarFile(path) {
574
673
  }
575
674
 
576
675
  // packages/cli-core/src/process-lock.ts
577
- import { randomUUID } from "node:crypto";
578
- import { mkdir as mkdir3, readFile as readFile6, readdir, rename as rename3, rmdir, unlink, writeFile as writeFile3 } from "node:fs/promises";
676
+ import { randomUUID as randomUUID2 } from "node:crypto";
677
+ import { mkdir as mkdir3, readFile as readFile5, readdir, rename as rename4, rmdir, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
579
678
  import { join as join5 } from "node:path";
580
679
  function alive(pid) {
581
680
  try {
@@ -598,8 +697,8 @@ async function acquireProcessLock(options) {
598
697
  const root = options.directory;
599
698
  const key = options.key;
600
699
  const path = join5(root, key);
601
- const ownerName = `owner-${randomUUID()}.json`;
602
- const candidate = join5(root, `.pending-${randomUUID()}`);
700
+ const ownerName = `owner-${randomUUID2()}.json`;
701
+ const candidate = join5(root, `.pending-${randomUUID2()}`);
603
702
  const owner = { ...options.ownerData, pid: process.pid };
604
703
  await mkdir3(root, { recursive: true, mode: 448 });
605
704
  await mkdir3(candidate, { mode: 448 });
@@ -607,7 +706,7 @@ async function acquireProcessLock(options) {
607
706
  try {
608
707
  for (let attempt = 0; ; attempt++) {
609
708
  try {
610
- await rename3(candidate, path);
709
+ await rename4(candidate, path);
611
710
  break;
612
711
  } catch (error2) {
613
712
  if (!["EEXIST", "ENOTEMPTY"].includes(code(error2) ?? "")) throw error2;
@@ -625,14 +724,14 @@ async function acquireProcessLock(options) {
625
724
  const previousPath = join5(path, names[0]);
626
725
  let previous;
627
726
  try {
628
- previous = JSON.parse(await readFile6(previousPath, "utf8"));
727
+ previous = JSON.parse(await readFile5(previousPath, "utf8"));
629
728
  } catch (error2) {
630
729
  if (code(error2) === "ENOENT") continue;
631
730
  throw options.busyError();
632
731
  }
633
732
  if (!validPid(previous.pid) || previous.runtimePid !== void 0 && !validPid(previous.runtimePid) || alive(previous.pid) || previous.runtimePid !== void 0 && runtimeAlive(previous.runtimePid)) throw options.busyError();
634
733
  try {
635
- await unlink(previousPath);
734
+ await unlink2(previousPath);
636
735
  } catch (error2) {
637
736
  if (code(error2) === "ENOENT") continue;
638
737
  throw error2;
@@ -642,25 +741,25 @@ async function acquireProcessLock(options) {
642
741
  });
643
742
  }
644
743
  } finally {
645
- await unlink(join5(candidate, ownerName)).catch(() => void 0);
744
+ await unlink2(join5(candidate, ownerName)).catch(() => void 0);
646
745
  await rmdir(candidate).catch(() => void 0);
647
746
  }
648
747
  let released = false;
649
748
  return {
650
749
  async attachRuntime(pid) {
651
750
  if (!validPid(pid)) throw new TypeError("Runtime PID is invalid");
652
- const temporary = join5(root, `.update-${randomUUID()}`);
751
+ const temporary = join5(root, `.update-${randomUUID2()}`);
653
752
  try {
654
753
  await writeFile3(temporary, JSON.stringify({ ...owner, ...await options.runtimeData?.(pid), runtimePid: pid }), { mode: 384, flag: "wx" });
655
- await rename3(temporary, join5(path, ownerName));
754
+ await rename4(temporary, join5(path, ownerName));
656
755
  } finally {
657
- await unlink(temporary).catch(() => void 0);
756
+ await unlink2(temporary).catch(() => void 0);
658
757
  }
659
758
  },
660
759
  async release() {
661
760
  if (released) return;
662
761
  released = true;
663
- await unlink(join5(path, ownerName)).catch((error2) => {
762
+ await unlink2(join5(path, ownerName)).catch((error2) => {
664
763
  if (code(error2) !== "ENOENT") throw error2;
665
764
  });
666
765
  await rmdir(path).catch((error2) => {
@@ -695,16 +794,16 @@ async function localFile(path) {
695
794
  const item = await entry(path);
696
795
  if (!item) return void 0;
697
796
  if (!item.isFile() || item.size > 8 * 1024 * 1024) throw new MetaPreparationError(`\u5934\u50CF\u8349\u7A3F\u6587\u4EF6\u65E0\u6548\uFF0C\u5DF2\u4FDD\u7559\u539F\u6587\u4EF6\uFF1A${path}`);
698
- return readFile7(path);
797
+ return readFile6(path);
699
798
  }
700
799
  async function save(path, content) {
701
800
  await localFile(path);
702
- const temporary = `${path}.${randomUUID2()}.tmp`;
801
+ const temporary = `${path}.${randomUUID3()}.tmp`;
703
802
  try {
704
803
  await writeFile4(temporary, content, { flag: "wx", mode: 384 });
705
- await rename4(temporary, path);
804
+ await rename5(temporary, path);
706
805
  } finally {
707
- await unlink2(temporary).catch((e) => {
806
+ await unlink3(temporary).catch((e) => {
708
807
  if (e.code !== "ENOENT") throw e;
709
808
  });
710
809
  }
@@ -912,9 +1011,9 @@ import { lstat as lstat5 } from "node:fs/promises";
912
1011
  import { join as join8 } from "node:path";
913
1012
 
914
1013
  // packages/cli-core/src/init/scaffold.ts
915
- import { lstat as lstat4, mkdir as mkdir5, open as open2, readFile as readFile9, rename as rename5, rmdir as rmdir2, unlink as unlink3 } from "node:fs/promises";
1014
+ import { lstat as lstat4, mkdir as mkdir5, open as open3, readFile as readFile8, rename as rename6, rmdir as rmdir2, unlink as unlink4 } from "node:fs/promises";
916
1015
  import { resolve as resolve3 } from "node:path";
917
- import { randomUUID as randomUUID3 } from "node:crypto";
1016
+ import { randomUUID as randomUUID4 } from "node:crypto";
918
1017
 
919
1018
  // packages/cli-core/src/config/models.ts
920
1019
  var MODEL_IDS = Object.freeze([
@@ -927,7 +1026,7 @@ var DEFAULT_MODEL_ID = "kimi-k2.6";
927
1026
 
928
1027
  // packages/cli-core/src/init/runtime-template.ts
929
1028
  import { execFile as execFile3 } from "node:child_process";
930
- import { mkdtemp as mkdtemp3, readFile as readFile8, rm as rm3, writeFile as writeFile5 } from "node:fs/promises";
1029
+ import { mkdtemp as mkdtemp3, readFile as readFile7, rm as rm3, writeFile as writeFile5 } from "node:fs/promises";
931
1030
  import { tmpdir } from "node:os";
932
1031
  import { join as join7 } from "node:path";
933
1032
  import { promisify as promisify3 } from "node:util";
@@ -938,8 +1037,8 @@ async function latestRuntimeTemplate(template, options) {
938
1037
  let temporaryRoot;
939
1038
  try {
940
1039
  options.signal?.throwIfAborted();
941
- options.report(options.runtimeVersion ? `\u6B63\u5728\u786E\u8BA4 Runtime ${options.runtimeVersion}\u2026` : "\u6B63\u5728\u67E5\u8BE2\u516C\u5171 npm \u7684\u6700\u65B0 Runtime\u2026");
942
- const version = options.runtimeVersion ? await resolveRuntimeVersion(options.runtimeVersion, options) : await latestRuntimeVersion(options);
1040
+ options.report("\u6B63\u5728\u67E5\u8BE2\u516C\u5171 npm \u7684\u6700\u65B0\u6B63\u5F0F\u7248 Runtime\u2026");
1041
+ const version = await latestRuntimeVersion(options);
943
1042
  let result = template;
944
1043
  if (version !== bundledVersion) {
945
1044
  temporaryRoot = await mkdtemp3(join7(tmpdir(), "buddy-runtime-template-"));
@@ -967,8 +1066,8 @@ async function latestRuntimeTemplate(template, options) {
967
1066
  "--fetch-timeout=20000"
968
1067
  ], { cwd: temporaryRoot, signal: options.signal, timeout: 6e4 });
969
1068
  result = {
970
- packageJson: await readFile8(join7(temporaryRoot, "package.json"), "utf8"),
971
- packageLock: await readFile8(join7(temporaryRoot, "package-lock.json"), "utf8")
1069
+ packageJson: await readFile7(join7(temporaryRoot, "package.json"), "utf8"),
1070
+ packageLock: await readFile7(join7(temporaryRoot, "package-lock.json"), "utf8")
972
1071
  };
973
1072
  }
974
1073
  const pkg = JSON.parse(result.packageJson);
@@ -978,12 +1077,12 @@ async function latestRuntimeTemplate(template, options) {
978
1077
  throw new Error("\u751F\u6210\u7684 Runtime \u7248\u672C\u4E0E\u4F9D\u8D56\u9501\u6587\u4EF6\u4E0D\u4E00\u81F4");
979
1078
  }
980
1079
  options.signal?.throwIfAborted();
981
- options.report(`\u5DF2\u4ECE\u516C\u5171 npm ${options.runtimeVersion ?? "latest"} \u9501\u5B9A Runtime ${version}\uFF08package.json \u4E0E package-lock.json\uFF09\u3002`);
1080
+ options.report(`\u5DF2\u4ECE\u516C\u5171 npm latest \u9501\u5B9A Runtime ${version}\uFF08package.json \u4E0E package-lock.json\uFF09\u3002`);
982
1081
  return result;
983
1082
  } catch (cause) {
984
1083
  if (options.signal?.aborted) throw new Error("Runtime \u7248\u672C\u9009\u62E9\u5DF2\u53D6\u6D88");
985
1084
  const reason = cause instanceof Error && !cause.message.includes("Command failed") ? cause.message : "npm \u672A\u5B8C\u6210\u9501\u6587\u4EF6\u751F\u6210";
986
- throw new Error(`\u672A\u80FD\u9501\u5B9A${options.runtimeVersion ? "\u9009\u5B9A" : "\u6700\u65B0"} Runtime\uFF1A${reason}\u3002\u5DF2\u505C\u6B62\u751F\u6210\u5DE5\u7A0B\u4F9D\u8D56\uFF0C\u8BF7\u4FEE\u590D\u540E\u91CD\u8BD5\uFF1B\u4E0D\u4F1A\u56DE\u9000\u5230\u5185\u7F6E\u65E7\u7248\u672C\u3002`, { cause });
1085
+ throw new Error(`\u672A\u80FD\u9501\u5B9A\u6700\u65B0\u6B63\u5F0F\u7248 Runtime\uFF1A${reason}\u3002\u5DF2\u505C\u6B62\u751F\u6210\u5DE5\u7A0B\u4F9D\u8D56\uFF0C\u8BF7\u4FEE\u590D\u540E\u91CD\u8BD5\uFF1B\u4E0D\u4F1A\u56DE\u9000\u5230\u5185\u7F6E\u65E7\u7248\u672C\u3002`, { cause });
987
1086
  } finally {
988
1087
  if (temporaryRoot) await rm3(temporaryRoot, { recursive: true, force: true });
989
1088
  }
@@ -1073,7 +1172,7 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1073
1172
  const path = resolve3(projectRoot, BUDDY_PLATFORM_AGENT_ENTRY);
1074
1173
  const packagePath = resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
1075
1174
  if (!(await lstat4(packagePath)).isFile()) throw new Error("package.json \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6");
1076
- const originalPackage = await readFile9(packagePath, "utf8");
1175
+ const originalPackage = await readFile8(packagePath, "utf8");
1077
1176
  const projectPackage = parseBuddyProjectManifest(originalPackage);
1078
1177
  const isIdentityDraft = Object.keys(projectPackage).every((key) => key === "buddyId");
1079
1178
  const hasAlternateLockfile = (await Promise.all(["pnpm-lock.yaml", "yarn.lock"].map(async (name2) => {
@@ -1090,12 +1189,12 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1090
1189
  const files = [
1091
1190
  { path, content: platformAgentTemplate(name) },
1092
1191
  { path: resolve3(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate(options.model) },
1093
- { path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile9(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
1094
- ...hasAlternateLockfile ? [] : [{ path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK), content: await readFile9(new URL("../../resources/agent-template/package-lock.json", import.meta.url), "utf8") }],
1192
+ { path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile8(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
1193
+ ...hasAlternateLockfile ? [] : [{ path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK), content: await readFile8(new URL("../../resources/agent-template/package-lock.json", import.meta.url), "utf8") }],
1095
1194
  { path: resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() },
1096
1195
  { path: resolve3(projectRoot, "data-access.json"), content: '{\n "requirements": []\n}\n' },
1097
1196
  { path: resolve3(projectRoot, ".gitignore"), content: "node_modules/\n/.env\n" },
1098
- { path: resolve3(projectRoot, ".env.example"), content: "# \u642D\u5B50\u8EAB\u4EFD\u7531 package.json \u9876\u5C42\u7684 buddyId \u63D0\u4F9B\u3002\n# \u9996\u6B21\u8FD0\u884C buddy-cli dev \u6216\u5728\u540E\u53F0\u542F\u52A8 DEV \u65F6\uFF0CCLI \u4F1A\u51C6\u5907 .env\u3002\nBUDDY_TOKEN=\n# CLI \u81EA\u52A8\u5199\u5165\u9009\u5B9A\u7684 MLB_GATEWAY_URL\uFF0C\u4F9B Runtime \u4F7F\u7528\u3002\n# \u5207\u6362 CLI \u5E73\u53F0\u65F6\uFF0C\u5728\u8FD0\u884C CLI \u7684\u7EC8\u7AEF export MLB_GATEWAY_URL\uFF1BCLI \u4E0D\u81EA\u52A8\u8BFB\u53D6\u672C\u6587\u4EF6\u6216\u5DE5\u7A0B .env \u6765\u9009\u62E9\u5E73\u53F0\u3002\n" }
1197
+ { path: resolve3(projectRoot, ".env.example"), content: "# \u642D\u5B50\u8EAB\u4EFD\u7531 package.json \u9876\u5C42\u7684 buddyId \u63D0\u4F9B\u3002\n# \u9996\u6B21\u8FD0\u884C buddy-cli dev \u6216\u5728\u540E\u53F0\u542F\u52A8 DEV \u65F6\uFF0CCLI \u4F1A\u51C6\u5907 .env\u3002\nBUDDY_TOKEN=\n# CLI \u81EA\u52A8\u5199\u5165 ECS Test \u7684 MLB_GATEWAY_URL\uFF0C\u4F9B Runtime \u4F7F\u7528\uFF1B\u65E0\u9700\u624B\u52A8\u8BBE\u7F6E\u3002\n# \u6B63\u5F0F CLI \u4E0D\u652F\u6301\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 .env \u5207\u6362\u5E73\u53F0\u3002\n" }
1099
1198
  ];
1100
1199
  const handles = [];
1101
1200
  const createdDirectories = [];
@@ -1114,7 +1213,7 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1114
1213
  }
1115
1214
  for (const file of files) {
1116
1215
  try {
1117
- handles.push({ path: file.path, handle: await open2(file.path, "wx", 384) });
1216
+ handles.push({ path: file.path, handle: await open3(file.path, "wx", 384) });
1118
1217
  } catch (cause) {
1119
1218
  if (cause.code !== "EEXIST") throw cause;
1120
1219
  if (!(await lstat4(file.path)).isFile()) {
@@ -1134,8 +1233,8 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1134
1233
  lockFile.content = template.packageLock;
1135
1234
  }
1136
1235
  if (lockFile && (isIdentityDraft || handles.some((file) => file.path === lockFile.path))) {
1137
- const packageContents = isIdentityDraft ? packageFile.content : await readFile9(packageFile.path, "utf8");
1138
- const lockContents = handles.some((file) => file.path === lockFile.path) ? lockFile.content : await readFile9(lockFile.path, "utf8");
1236
+ const packageContents = isIdentityDraft ? packageFile.content : await readFile8(packageFile.path, "utf8");
1237
+ const lockContents = handles.some((file) => file.path === lockFile.path) ? lockFile.content : await readFile8(lockFile.path, "utf8");
1139
1238
  const declared = JSON.parse(packageContents).dependencies ?? {};
1140
1239
  const locked = JSON.parse(lockContents).packages?.[""]?.dependencies ?? {};
1141
1240
  if (JSON.stringify(Object.entries(declared).sort()) !== JSON.stringify(Object.entries(locked).sort())) {
@@ -1148,19 +1247,19 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1148
1247
  await handle.sync();
1149
1248
  }
1150
1249
  if (isIdentityDraft) {
1151
- const temporary = `${packagePath}.${randomUUID3()}.tmp`;
1152
- const handle = await open2(temporary, "wx", 384);
1250
+ const temporary = `${packagePath}.${randomUUID4()}.tmp`;
1251
+ const handle = await open3(temporary, "wx", 384);
1153
1252
  try {
1154
1253
  await handle.writeFile(packageFile.content, "utf8");
1155
1254
  await handle.sync();
1156
1255
  await handle.close();
1157
- if (!(await lstat4(packagePath)).isFile() || await readFile9(packagePath, "utf8") !== originalPackage) {
1256
+ if (!(await lstat4(packagePath)).isFile() || await readFile8(packagePath, "utf8") !== originalPackage) {
1158
1257
  throw new Error("\u8865\u9F50\u5DE5\u7A0B\u65F6 package.json \u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u8BD5");
1159
1258
  }
1160
- await rename5(temporary, packagePath);
1259
+ await rename6(temporary, packagePath);
1161
1260
  } finally {
1162
1261
  await handle.close().catch(() => void 0);
1163
- await unlink3(temporary).catch((cause) => {
1262
+ await unlink4(temporary).catch((cause) => {
1164
1263
  if (cause.code !== "ENOENT") throw cause;
1165
1264
  });
1166
1265
  }
@@ -1168,7 +1267,7 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1168
1267
  return Object.freeze({ path, created: isIdentityDraft || handles.length > 0 || createdDirectories.length > 0 });
1169
1268
  } catch (cause) {
1170
1269
  await Promise.all(handles.map(({ handle }) => handle.close().catch(() => void 0)));
1171
- await Promise.all(handles.map(({ path: createdPath }) => unlink3(createdPath).catch(() => void 0)));
1270
+ await Promise.all(handles.map(({ path: createdPath }) => unlink4(createdPath).catch(() => void 0)));
1172
1271
  for (const directory of createdDirectories.reverse()) {
1173
1272
  await rmdir2(directory).catch(() => void 0);
1174
1273
  }
@@ -1336,7 +1435,7 @@ async function unlinkMatchingFile(targetPath, expectedIdentity) {
1336
1435
  if (!entry2.isFile() || entry2.isSymbolicLink() || entryIdentity(entry2) !== expectedIdentity) {
1337
1436
  return false;
1338
1437
  }
1339
- await unlink4(targetPath);
1438
+ await unlink5(targetPath);
1340
1439
  return true;
1341
1440
  } catch (cause) {
1342
1441
  return cause.code === "ENOENT";
@@ -1379,7 +1478,7 @@ async function readExistingManifest(agentConfigPath) {
1379
1478
  );
1380
1479
  }
1381
1480
  try {
1382
- return parseBuddyProjectManifest(await readFile10(agentConfigPath, "utf8"));
1481
+ return parseBuddyProjectManifest(await readFile9(agentConfigPath, "utf8"));
1383
1482
  } catch (cause) {
1384
1483
  throw new ProjectInitializationError(
1385
1484
  "TARGET_CHANGED",
@@ -1465,12 +1564,12 @@ async function publishNewFile(options) {
1465
1564
  let publishedHandle;
1466
1565
  const temporaryPath = join9(
1467
1566
  options.rootDirectory,
1468
- `.${options.temporaryLabel}.${process.pid}.${randomUUID4()}.tmp`
1567
+ `.${options.temporaryLabel}.${process.pid}.${randomUUID5()}.tmp`
1469
1568
  );
1470
1569
  let temporaryIdentity;
1471
1570
  let publishedIdentity;
1472
1571
  try {
1473
- temporaryHandle = await open3(temporaryPath, "wx");
1572
+ temporaryHandle = await open4(temporaryPath, "wx");
1474
1573
  temporaryIdentity = entryIdentity(await temporaryHandle.stat());
1475
1574
  await temporaryHandle.writeFile(options.contents, "utf8");
1476
1575
  await temporaryHandle.sync();
@@ -1493,7 +1592,7 @@ async function publishNewFile(options) {
1493
1592
  if (fallbackBeforeOpen.kind !== "directory" || fallbackBeforeOpen.identity !== options.directoryIdentity) {
1494
1593
  throw targetChanged({ rootDirectory: options.rootDirectory });
1495
1594
  }
1496
- publishedHandle = await open3(options.targetPath, "wx");
1595
+ publishedHandle = await open4(options.targetPath, "wx");
1497
1596
  publishedIdentity = entryIdentity(await publishedHandle.stat());
1498
1597
  const fallbackRoot = await pathState(options.rootDirectory);
1499
1598
  if (fallbackRoot.kind !== "directory" || fallbackRoot.identity !== options.directoryIdentity) {
@@ -1507,7 +1606,7 @@ async function publishNewFile(options) {
1507
1606
  const afterPublish = await pathState(options.rootDirectory);
1508
1607
  const publishedFileIdentity = await fileIdentity(options.targetPath);
1509
1608
  const temporaryFileIdentity = await fileIdentity(temporaryPath);
1510
- const publishedContents = publishedFileIdentity ? await readFile10(options.targetPath, "utf8") : void 0;
1609
+ const publishedContents = publishedFileIdentity ? await readFile9(options.targetPath, "utf8") : void 0;
1511
1610
  if (afterPublish.kind !== "directory" || afterPublish.identity !== options.directoryIdentity || !publishedIdentity || publishedFileIdentity !== publishedIdentity || temporaryFileIdentity !== temporaryIdentity || publishedContents !== options.contents) {
1512
1611
  if (afterPublish.kind === "directory" && afterPublish.identity === options.directoryIdentity && publishedIdentity) {
1513
1612
  await unlinkMatchingFile(options.targetPath, publishedIdentity);
@@ -1536,9 +1635,9 @@ async function publishNewFile(options) {
1536
1635
  async function replaceExistingFile(options) {
1537
1636
  const temporaryPath = join9(
1538
1637
  options.rootDirectory,
1539
- `.${options.temporaryLabel}.${process.pid}.${randomUUID4()}.tmp`
1638
+ `.${options.temporaryLabel}.${process.pid}.${randomUUID5()}.tmp`
1540
1639
  );
1541
- const handle = await open3(temporaryPath, "wx", 384);
1640
+ const handle = await open4(temporaryPath, "wx", 384);
1542
1641
  try {
1543
1642
  await handle.writeFile(options.contents, "utf8");
1544
1643
  await handle.sync();
@@ -1548,12 +1647,12 @@ async function replaceExistingFile(options) {
1548
1647
  try {
1549
1648
  const root = await pathState(options.rootDirectory);
1550
1649
  if (root.kind !== "directory" || root.identity !== options.directoryIdentity || await fileIdentity(options.targetPath) !== options.expectedFileIdentity) throw targetChanged({ rootDirectory: options.rootDirectory });
1551
- await rename6(temporaryPath, options.targetPath);
1552
- if (await readFile10(options.targetPath, "utf8") !== options.contents) {
1650
+ await rename7(temporaryPath, options.targetPath);
1651
+ if (await readFile9(options.targetPath, "utf8") !== options.contents) {
1553
1652
  throw targetChanged({ rootDirectory: options.rootDirectory });
1554
1653
  }
1555
1654
  } finally {
1556
- await unlink4(temporaryPath).catch((cause) => {
1655
+ await unlink5(temporaryPath).catch((cause) => {
1557
1656
  if (cause.code !== "ENOENT") throw cause;
1558
1657
  });
1559
1658
  }
@@ -1675,11 +1774,11 @@ async function initializeBuddyProject(options) {
1675
1774
  }
1676
1775
  async function readBuddyProjectManifest(projectRoot) {
1677
1776
  const rootDirectory = resolve4(projectRoot);
1678
- return parseBuddyProjectManifest(await readFile10(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8"));
1777
+ return parseBuddyProjectManifest(await readFile9(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8"));
1679
1778
  }
1680
1779
  async function readBuddyAgentConfig(projectRoot) {
1681
1780
  const rootDirectory = resolve4(projectRoot);
1682
- const source = await readFile10(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8");
1781
+ const source = await readFile9(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8");
1683
1782
  return parseBuddyAgentConfig(source);
1684
1783
  }
1685
1784
  async function readBuddyConfig(projectRoot) {
@@ -1746,7 +1845,7 @@ async function searchUp(startDirectory) {
1746
1845
  if (await projectFileState(directory, BUDDY_PACKAGE_FILENAME) === "valid") {
1747
1846
  let pkg;
1748
1847
  try {
1749
- pkg = JSON.parse(await readFile11(join10(directory, BUDDY_PACKAGE_FILENAME), "utf8"));
1848
+ pkg = JSON.parse(await readFile10(join10(directory, BUDDY_PACKAGE_FILENAME), "utf8"));
1750
1849
  } catch (cause) {
1751
1850
  throw new BuddyProjectContextError("PROJECT_CONFIG_INVALID", `\u65E0\u6CD5\u89E3\u6790 ${join10(directory, BUDDY_PACKAGE_FILENAME)}`, directory, { cause });
1752
1851
  }
@@ -1865,20 +1964,6 @@ async function assertInitializableBuddyTarget(target) {
1865
1964
  // packages/cli-core/src/commands/runtime-source.ts
1866
1965
  async function runtimeCatalogSource(directory, options = {}) {
1867
1966
  const project = await findBuddyProjectRoot(directory);
1868
- if (allowsRuntimeVersionSelection(options)) {
1869
- const declared = project ? await projectRuntimeVersion(project) : void 0;
1870
- if (declared && options.runtimeVersion !== void 0 && options.runtimeVersion !== declared) {
1871
- throw new Error(`\u5DE5\u7A0B\u56FA\u5B9A Runtime ${declared}\uFF0C\u76EE\u5F55\u5FC5\u987B\u4E0E\u8BE5\u7248\u672C\u4E00\u81F4\uFF1B\u5148\u786E\u8BA4\u5E76\u66F4\u65B0\u5DE5\u7A0B\u4F9D\u8D56\u540E\u518D\u67E5\u8BE2\u3002`);
1872
- }
1873
- const requested = declared ?? options.runtimeVersion;
1874
- if (!requested) throw new Error(await runtimeSelectionPrompt(options));
1875
- const selected = await resolveRuntimeVersion(requested, options);
1876
- const root2 = await cachedRuntimeRoot(selected, options);
1877
- const version2 = await runtimeVersionStatus(project, selected, true);
1878
- if (options.report) reportRuntimeVersion(version2, options.report);
1879
- return { root: root2, source: "npm", version: version2 };
1880
- }
1881
- if (options.runtimeVersion !== void 0) throw new Error("\u5F53\u524D\u5E73\u53F0\u7684\u80FD\u529B\u76EE\u5F55\u4F7F\u7528\u6700\u65B0\u7A33\u5B9A\u7248");
1882
1967
  const root = await (options.latestRuntimeRoot?.() ?? cachedLatestRuntimeRoot(options));
1883
1968
  const latest = await projectRuntimeVersion(root);
1884
1969
  if (!latest) throw new Error("npm Runtime \u7F13\u5B58\u7F3A\u5C11\u51C6\u786E\u7248\u672C");
@@ -1894,28 +1979,24 @@ var MODELS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli models [--directory <\u9879\u
1894
1979
  \u5C06\u6240\u9009 ID \u5199\u5165 src/buddy-options.mjs \u7684 initialState.model\uFF1B\u6A21\u677F\u5728 initialState.model \u4E2D\u4F7F\u7528\u5B83\u3002`;
1895
1980
  async function runModelsCommand(args, io, cwd, options = {}) {
1896
1981
  try {
1897
- const selected = allowsRuntimeVersionSelection(options);
1898
- const help = selected ? `\u7528\u6CD5: buddy-cli models [--directory <\u9879\u76EE\u76EE\u5F55>] [--runtime-version <\u51C6\u786E\u7248\u672C|latest|dev>] [--json]
1899
- \u8BFB\u53D6\u5DE5\u7A0B\u56FA\u5B9A Runtime \u7684\u80FD\u529B\u76EE\u5F55\uFF1B\u5DE5\u7A0B\u5C1A\u672A\u751F\u6210\u65F6\uFF0C\u5148\u8BE2\u95EE\u5F00\u53D1\u8005\uFF0C\u518D\u7528 --runtime-version \u9009\u62E9\u7248\u672C\u3002\u4E0D\u4F1A\u81EA\u52A8\u5207\u6362\u5DE5\u7A0B\u4F9D\u8D56\u3002` : MODELS_COMMAND_HELP;
1982
+ const help = MODELS_COMMAND_HELP;
1900
1983
  if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
1901
1984
  io.write(help);
1902
1985
  return { exitCode: 0 };
1903
1986
  }
1904
1987
  let directory;
1905
1988
  let json2 = false;
1906
- let runtimeVersion;
1907
1989
  for (let i = 0; i < args.length; i++) {
1908
1990
  if (args[i] === "--json" && !json2) json2 = true;
1909
1991
  else if (args[i] === "--directory" && directory === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) directory = args[++i];
1910
- else if (selected && args[i] === "--runtime-version" && runtimeVersion === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) runtimeVersion = args[++i];
1911
1992
  else throw new Error(`models \u53C2\u6570\u65E0\u6548\uFF1A${args[i]}
1912
1993
  ${help}`);
1913
1994
  }
1914
- const { root, source, version } = await runtimeCatalogSource(resolve6(cwd, directory ?? "."), { report: (message) => io.writeError(message), ...options, runtimeVersion });
1995
+ const { root, source, version } = await runtimeCatalogSource(resolve6(cwd, directory ?? "."), { report: (message) => io.writeError(message), ...options });
1915
1996
  const catalog = await readRuntimeModelCatalog(root);
1916
1997
  if (json2) io.write(JSON.stringify({ source, ...catalog, ...version }, null, 2));
1917
1998
  else {
1918
- io.write(`npm ${selected ? "\u9009\u5B9A" : "\u6700\u65B0"} Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.models.length} \u4E2A\u6A21\u578B\uFF1A`);
1999
+ io.write(`npm \u6700\u65B0\u6B63\u5F0F\u7248 Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.models.length} \u4E2A\u6A21\u578B\uFF1A`);
1919
2000
  for (const id of catalog.models) io.write(`- ${id}`);
1920
2001
  io.write("\u5C06\u6240\u9009 ID \u5199\u5165 src/buddy-options.mjs \u7684 initialState.model\uFF1B\u81EA\u5B9A\u4E49\u4F1A\u8BDD\u5DE5\u5382\u4E5F\u53EF\u6309\u4F1A\u8BDD\u8BBE\u7F6E initialState.model\u3002");
1921
2002
  }
@@ -1937,28 +2018,24 @@ var DATASETS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli datasets [--directory <\u98
1937
2018
  \u76EE\u5F55\u4E0D\u4EE3\u8868\u7528\u6237\u5DF2\u6388\u6743\u3002\u4F7F\u7528 data_access_query \u67E5\u8BE2\uFF0C\u672A\u6388\u6743\u65F6\u4EE5 datasets\u3001reason \u8BF7\u6C42\u6388\u6743\uFF0C\u7528\u6237\u5904\u7406\u540E\u518D\u6B21\u67E5\u8BE2\u3002`;
1938
2019
  async function runDatasetsCommand(args, io, cwd, options = {}) {
1939
2020
  try {
1940
- const selected = allowsRuntimeVersionSelection(options);
1941
- const help = selected ? `\u7528\u6CD5: buddy-cli datasets [--directory <\u9879\u76EE\u76EE\u5F55>] [--runtime-version <\u51C6\u786E\u7248\u672C|latest|dev>] [--json]
1942
- \u8BFB\u53D6\u5DE5\u7A0B\u56FA\u5B9A Runtime \u7684\u80FD\u529B\u76EE\u5F55\uFF1B\u5DE5\u7A0B\u5C1A\u672A\u751F\u6210\u65F6\uFF0C\u5148\u8BE2\u95EE\u5F00\u53D1\u8005\uFF0C\u518D\u7528 --runtime-version \u9009\u62E9\u7248\u672C\u3002\u4E0D\u4F1A\u81EA\u52A8\u5207\u6362\u5DE5\u7A0B\u4F9D\u8D56\u3002` : DATASETS_COMMAND_HELP;
2021
+ const help = DATASETS_COMMAND_HELP;
1943
2022
  if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
1944
2023
  io.write(help);
1945
2024
  return { exitCode: 0 };
1946
2025
  }
1947
2026
  let directory;
1948
2027
  let json2 = false;
1949
- let runtimeVersion;
1950
2028
  for (let i = 0; i < args.length; i++) {
1951
2029
  if (args[i] === "--json" && !json2) json2 = true;
1952
2030
  else if (args[i] === "--directory" && directory === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) directory = args[++i];
1953
- else if (selected && args[i] === "--runtime-version" && runtimeVersion === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) runtimeVersion = args[++i];
1954
2031
  else throw new Error(`datasets \u53C2\u6570\u65E0\u6548\uFF1A${args[i]}
1955
2032
  ${help}`);
1956
2033
  }
1957
- const { root, source, version } = await runtimeCatalogSource(resolve7(cwd, directory ?? "."), { report: (message) => io.writeError(message), ...options, runtimeVersion });
2034
+ const { root, source, version } = await runtimeCatalogSource(resolve7(cwd, directory ?? "."), { report: (message) => io.writeError(message), ...options });
1958
2035
  const catalog = await readRuntimeDataCatalog(root);
1959
2036
  if (json2) io.write(JSON.stringify({ source, ...catalog, ...version }, null, 2));
1960
2037
  else {
1961
- io.write(`npm ${selected ? "\u9009\u5B9A" : "\u6700\u65B0"} Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.datasets.length} \u9879\u6570\u636E\u80FD\u529B\uFF1A`);
2038
+ io.write(`npm \u6700\u65B0\u6B63\u5F0F\u7248 Runtime ${catalog.runtimeVersion} \u63D0\u4F9B ${catalog.datasets.length} \u9879\u6570\u636E\u80FD\u529B\uFF1A`);
1962
2039
  for (const item of catalog.datasets) io.write(`- ${item.id} \u2014 ${item.title}\uFF08${item.source}\uFF0CSchema ${item.schemaVersion}\uFF09`);
1963
2040
  io.write("\u5C06\u6240\u9009 id \u548C purpose \u5199\u5165 data-access.json.requirements\uFF1B\u7528\u6237\u6388\u6743\u7531\u5E73\u53F0\u5904\u7406\u3002");
1964
2041
  }
@@ -1970,8 +2047,8 @@ ${help}`);
1970
2047
  }
1971
2048
 
1972
2049
  // packages/cli-core/src/commands/knowledge.ts
1973
- import { createHash as createHash2, randomUUID as randomUUID5 } from "node:crypto";
1974
- import { lstat as lstat8, mkdir as mkdir7, readFile as readFile12, rename as rename7, unlink as unlink5, writeFile as writeFile6 } from "node:fs/promises";
2050
+ import { createHash as createHash2, randomUUID as randomUUID6 } from "node:crypto";
2051
+ import { lstat as lstat8, mkdir as mkdir7, readFile as readFile11, rename as rename8, unlink as unlink6, writeFile as writeFile6 } from "node:fs/promises";
1975
2052
  import { dirname as dirname2, join as join11, resolve as resolve8 } from "node:path";
1976
2053
  var MANIFEST = "knowledge-manifest.json";
1977
2054
  var INDEX = "resources/knowledge/index.md";
@@ -2030,7 +2107,7 @@ async function read(root, path) {
2030
2107
  });
2031
2108
  if (!entry2) return void 0;
2032
2109
  if (!entry2.isFile() || entry2.size > MAX_BYTES) throw new Error(`\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6\u4E14\u4E0D\u8D85\u8FC7 100 MiB\uFF1A${path}`);
2033
- return readFile12(full);
2110
+ return readFile11(full);
2034
2111
  }
2035
2112
  async function requiredRead(root, path) {
2036
2113
  const bytes = await read(root, path);
@@ -2040,12 +2117,12 @@ async function requiredRead(root, path) {
2040
2117
  async function atomicWrite(root, path, value) {
2041
2118
  const full = await safePath(root, path);
2042
2119
  await mkdir7(dirname2(full), { recursive: true });
2043
- const temporary = `${full}.${randomUUID5()}.tmp`;
2120
+ const temporary = `${full}.${randomUUID6()}.tmp`;
2044
2121
  await writeFile6(temporary, value, { flag: "wx", mode: 384 });
2045
2122
  try {
2046
- await rename7(temporary, full);
2123
+ await rename8(temporary, full);
2047
2124
  } finally {
2048
- await unlink5(temporary).catch((error2) => {
2125
+ await unlink6(temporary).catch((error2) => {
2049
2126
  if (!missing(error2)) throw error2;
2050
2127
  });
2051
2128
  }
@@ -2216,7 +2293,7 @@ async function syncKnowledge(root, planPath) {
2216
2293
  if (current && hash2(current) !== hash2(content) && hash2(current) !== expected.get(path)) conflicts.push(path);
2217
2294
  }
2218
2295
  if (conflicts.length) {
2219
- const directory = `.buddy/knowledge/conflicts/${randomUUID5()}`;
2296
+ const directory = `.buddy/knowledge/conflicts/${randomUUID6()}`;
2220
2297
  for (const [path, content] of files) await atomicWrite(root, `${directory}/${path}`, content);
2221
2298
  await atomicWrite(root, `${directory}/${MANIFEST}`, json(next));
2222
2299
  return { status: "conflict", conflicts, candidateDirectory: directory, written: [] };
@@ -2283,11 +2360,11 @@ ${KNOWLEDGE_HELP}`);
2283
2360
  }
2284
2361
 
2285
2362
  // packages/cli-core/src/index.ts
2286
- import { join as join23, resolve as resolve18 } from "node:path";
2363
+ import { join as join22, resolve as resolve18 } from "node:path";
2287
2364
 
2288
2365
  // packages/cli-core/src/init/creator.ts
2289
- import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
2290
- import { link as link2, lstat as lstat9, mkdir as mkdir8, readFile as readFile13, rename as rename8, unlink as unlink6, writeFile as writeFile7 } from "node:fs/promises";
2366
+ import { createHash as createHash3, randomUUID as randomUUID7 } from "node:crypto";
2367
+ import { link as link2, lstat as lstat9, mkdir as mkdir8, readFile as readFile12, rename as rename9, unlink as unlink7, writeFile as writeFile7 } from "node:fs/promises";
2291
2368
  import { dirname as dirname3, join as join13 } from "node:path";
2292
2369
 
2293
2370
  // packages/cli-core/src/init/creator-package.ts
@@ -2539,26 +2616,26 @@ async function safeRead(path) {
2539
2616
  if (!entry2.isFile() || entry2.size > MAX_LOCAL_FILE_BYTES) {
2540
2617
  throw new CreatorPreparationError(`\u521B\u4F5C\u6587\u4EF6\u4E0D\u662F\u666E\u901A\u6587\u4EF6\u6216\u8D85\u51FA\u5927\u5C0F\u9650\u5236\uFF1A${path}`);
2541
2618
  }
2542
- return readFile13(path);
2619
+ return readFile12(path);
2543
2620
  }
2544
2621
  async function writeOnce(path, bytes) {
2545
- const temporary = `${path}.${randomUUID6()}.tmp`;
2622
+ const temporary = `${path}.${randomUUID7()}.tmp`;
2546
2623
  await writeFile7(temporary, bytes, { flag: "wx", mode: 384 });
2547
2624
  try {
2548
2625
  await link2(temporary, path).catch((cause) => {
2549
2626
  if (cause.code !== "EEXIST") throw cause;
2550
2627
  });
2551
2628
  } finally {
2552
- await unlink6(temporary);
2629
+ await unlink7(temporary);
2553
2630
  }
2554
2631
  }
2555
- async function replaceFile(path, content) {
2556
- const temporary = `${path}.${randomUUID6()}.tmp`;
2632
+ async function replaceFile2(path, content) {
2633
+ const temporary = `${path}.${randomUUID7()}.tmp`;
2557
2634
  try {
2558
2635
  await writeFile7(temporary, content, { flag: "wx", mode: 384 });
2559
- await rename8(temporary, path);
2636
+ await rename9(temporary, path);
2560
2637
  } finally {
2561
- await unlink6(temporary).catch((error2) => {
2638
+ await unlink7(temporary).catch((error2) => {
2562
2639
  if (error2.code !== "ENOENT") throw error2;
2563
2640
  });
2564
2641
  }
@@ -2623,7 +2700,7 @@ async function prepareCreatorSkill(context, io, options = {}) {
2623
2700
  await writeOnce(sessionPath, JSON.stringify({
2624
2701
  schemaVersion: 1,
2625
2702
  platformBuddyId: context.buddyId,
2626
- creationKey: randomUUID6()
2703
+ creationKey: randomUUID7()
2627
2704
  }, null, 2) + "\n");
2628
2705
  const session = JSON.parse((await safeRead(sessionPath)).toString("utf8"));
2629
2706
  if (session.schemaVersion !== 1 || session.platformBuddyId !== context.buddyId || !/^[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}$/u.test(session.creationKey)) {
@@ -2683,9 +2760,9 @@ async function prepareCreatorSkill(context, io, options = {}) {
2683
2760
  }
2684
2761
  await writeOnce(join13(root, `HANDOFF.${hash3(existing).slice(0, 12)}.bak.md`), existing);
2685
2762
  }
2686
- await replaceFile(lockPath, JSON.stringify({ ...selected.lock, ...existing ? { handoffSha256: hash3(existing) } : {} }, null, 2) + "\n");
2687
- await replaceFile(handoffPath, handoff2);
2688
- await replaceFile(lockPath, JSON.stringify({ ...selected.lock, handoffSha256: hash3(handoff2) }, null, 2) + "\n");
2763
+ await replaceFile2(lockPath, JSON.stringify({ ...selected.lock, ...existing ? { handoffSha256: hash3(existing) } : {} }, null, 2) + "\n");
2764
+ await replaceFile2(handoffPath, handoff2);
2765
+ await replaceFile2(lockPath, JSON.stringify({ ...selected.lock, handoffSha256: hash3(handoff2) }, null, 2) + "\n");
2689
2766
  io.write(`\u4F7F\u7528 ${selected.lock.source === "npm" ? "\u72EC\u7ACB npm" : "\u672C\u5730\u5F00\u53D1"} Creator Skill ${selected.lock.version}\uFF1A${join13(skillRoot, "SKILL.md")}`);
2690
2767
  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`);
2691
2768
  io.write("Skill \u5DF2\u51C6\u5907\u597D\uFF0C\u521B\u4F5C\u4E0E\u5F00\u53D1\u5C1A\u672A\u5B8C\u6210\u3002\u901A\u7528\u5F00\u53D1\u6307\u5F15\uFF1Abuddy-cli guide\u3002");
@@ -2750,7 +2827,7 @@ function validateBuddyMetaUpdate(meta2) {
2750
2827
 
2751
2828
  // packages/cli-core/src/init/implementation-guide.ts
2752
2829
  var IMPLEMENTATION_GUIDE_SUMMARY = "\u5F00\u53D1\u5DF2\u83B7\u6388\u6743\u65F6\uFF0C\u5148\u8BFB\u53D6\u5DF2\u786E\u8BA4\u7684\u624B\u518C\u6216\u9700\u6C42\u53CA\u73B0\u6709\u4EE3\u7801\uFF0C\u628A\u6BCF\u9879\u8981\u6C42\u843D\u5B9E\u5230\u5B9E\u73B0\u548C\u68C0\u67E5\u3002\u5DF2\u7ECF\u660E\u786E\u6216\u80FD\u636E\u6B64\u786E\u5B9A\u7684\u76F4\u63A5\u505A\uFF1B\u53EA\u8865\u95EE\u5F71\u54CD\u4F53\u9A8C\u3001\u6570\u636E\u4F7F\u7528\u6216\u6388\u6743\u7684\u5173\u952E\u7F3A\u53E3\uFF0C\u4E0D\u518D\u9010\u9879\u8BE2\u95EE\u6280\u672F\u9009\u9879\uFF0C\u4E5F\u4E0D\u56FA\u5B9A\u589E\u52A0\u4E00\u8F6E\u65B9\u6848\u786E\u8BA4\u3002\u6A21\u677F\u751F\u6210\u4E0D\u7B49\u4E8E\u9700\u6C42\u5DF2\u5B9E\u73B0\u3002\u642D\u5B50\u4E1A\u52A1\u53EA\u4F7F\u7528\u5E73\u53F0\u63D0\u4F9B\u7684\u670D\u52A1\uFF0C\u4E0D\u76F4\u63A5\u8C03\u7528\u7B2C\u4E09\u65B9\u670D\u52A1\u3002";
2753
- function implementationGuide(selectedRuntime = false) {
2830
+ function implementationGuide() {
2754
2831
  return `## \u4ECE\u9700\u6C42\u624B\u518C\u843D\u5B9E\u5230\u4EE3\u7801
2755
2832
 
2756
2833
  ${IMPLEMENTATION_GUIDE_SUMMARY}
@@ -2777,12 +2854,14 @@ ${KNOWLEDGE_GUIDE}
2777
2854
 
2778
2855
  CLI \u767B\u5F55\u6388\u6743\u548C\u9884\u89C8\u8FDE\u63A5\u76F4\u63A5\u8BF7\u6C42 MLB Server\uFF1B\u5F00\u53D1\u8005\u7F51\u9875\u63D0\u4F9B\u754C\u9762\u3002\u4F7F\u7528\u5F53\u524D\u5E73\u53F0\u751F\u6210\u7684\u8FDE\u63A5\u6307\u4EE4\uFF0C\u786E\u4FDD CLI \u4E0E\u7F51\u9875\u8FDE\u63A5\u540C\u4E00\u73AF\u5883\u3002\u5347\u7EA7\u5230 CLI 0.20 \u540E\u91CD\u65B0\u767B\u5F55\uFF1B\u4E0D\u8981\u8C03\u7528\u65E7 Web \u670D\u52A1\u7684\u6388\u6743\u6216\u9884\u89C8\u63A5\u53E3\u3002
2779
2856
 
2780
- CLI \u4E0E Runtime \u5171\u7528 \`MLB_GATEWAY_URL\`\uFF1ACLI \u4ECE\u8FDB\u7A0B\u73AF\u5883\u8BFB\u53D6\u5730\u5740\uFF0C\u542F\u52A8 DEV \u65F6\u628A\u9009\u5B9A\u5730\u5740\u4E0E\u5F00\u53D1 Token \u5199\u5165\u5DE5\u7A0B \`.env\`\uFF0C\u7531 Node \u52A0\u8F7D\u7ED9 Runtime\u3002\u65E0\u9700\u65B0\u589E\u672C\u673A\u914D\u7F6E\u6587\u4EF6\u6216\u5DE5\u7A0B\u5E73\u53F0\u5B57\u6BB5\u3002\u5E73\u53F0\u914D\u7F6E\u4E0D\u6539\u53D8\u516C\u5171 npm\u3001Runtime \u6216 Skill \u7684\u4E0B\u8F7D\u6765\u6E90\u3002\u4F7F\u7528\u5F53\u524D\u5E73\u53F0\u751F\u6210\u7684\u5B8C\u6574\u8FDE\u63A5/\u505C\u6B62\u6307\u4EE4\u65F6\uFF0C\`--app-server\` \u53EA\u8986\u76D6\u8BE5\u6B21\u547D\u4EE4\uFF1B\u540E\u53F0\u5730\u5740\u5FC5\u987B\u4E0E\u7F51\u5173\u540C\u6E90\u3002\u5730\u5740\u9519\u8BEF\u6216\u540E\u53F0\u51B2\u7A81\u65F6\u5148\u5904\u7406\u914D\u7F6E\uFF0C\u4E0D\u56DE\u9000\u5230\u5176\u4ED6\u5E73\u53F0\uFF1B\u5DE5\u7A0B\u5DF2\u6709 Token \u7684\u5E73\u53F0\u4E0D\u5339\u914D\u65F6\u5148\u786E\u8BA4\u76EE\u6807\uFF0C\u4E0D\u64C5\u81EA\u6362\u73AF\u5883\u6216\u53E6\u5EFA\u642D\u5B50\u3002
2857
+ \u6B63\u5F0F\u7248 CLI \u56FA\u5B9A\u8FDE\u63A5 ECS Test\u3002\u542F\u52A8 DEV \u65F6\u7531 CLI \u5C06\u56FA\u5B9A\u7684 \`MLB_GATEWAY_URL\` \u4E0E\u8BE5\u73AF\u5883\u5F00\u53D1 Token \u5199\u5165\u5DE5\u7A0B \`.env\` \u5E76\u4F20\u7ED9 Runtime\uFF1B\u65E0\u9700\u624B\u52A8\u914D\u7F6E\u5730\u5740\u3002\`--app-server\`\u3001\`--developer-web\` \u4EC5\u6821\u9A8C\u76EE\u6807\uFF0C\u4E0D\u80FD\u5207\u6362\u73AF\u5883\u3002\u5DE5\u7A0B\u5730\u5740\u51B2\u7A81\u65F6\u5148\u6309\u9519\u8BEF\u63D0\u793A\u5904\u7406\uFF0C\u4E0D\u6E05\u7A7A\u51ED\u636E\u7ED5\u8FC7\u68C0\u67E5\u3002\`--refresh-token\` \u53EA\u5237\u65B0\u540C\u4E00\u73AF\u5883\u7684\u5F00\u53D1\u51ED\u636E\u3002\u6B64\u9650\u5236\u53EA\u9488\u5BF9\u5E73\u53F0\u8FDE\u63A5\uFF0C\u4E0D\u5F71\u54CD\u516C\u5171 npm \u4E0E Skill \u4E0B\u8F7D\u3002
2781
2858
 
2782
2859
  ### \u672C\u5730\u8C03\u8BD5\u7684\u9000\u51FA\u548C\u6E05\u7406
2783
2860
 
2784
2861
  \u901A\u8FC7 \`buddy-cli preview\` \u8FDE\u63A5\u540E\u53F0\uFF0C\u9875\u9762\u542F\u52A8 DEV \u540E\u624D\u8FD0\u884C Runtime\u3002\u540E\u53F0\u590D\u5236\u7684\u6307\u4EE4\u5E26 \`--no-open\`\uFF0C\u6267\u884C\u540E\u8FD4\u56DE\u539F\u9875\u9762\uFF1B\u4E0D\u8981\u518D\u5F00\u4E00\u4E2A\u9884\u89C8\u8FDB\u7A0B\u3002\u6B63\u5E38\u505C\u6B62\u7528\u9875\u9762\u300C\u505C\u6B62 DEV\u300D\u6216 \`buddy-cli dev stop\`\uFF0C\u540E\u8005\u65E0\u9700\u8054\u7F51\u66F4\u65B0\u6216\u767B\u5F55\uFF0C\u53EA\u505C\u6B62\u5F53\u524D\u5E73\u53F0\u3001\u5F53\u524D\u642D\u5B50\u7684\u672C\u5730 Runtime \u548C\u76D1\u542C\uFF0C\u4E0D\u81EA\u52A8\u91CD\u8FDE\u6216\u91CD\u542F\u3002\u5173\u95ED\u7EC8\u7AEF\u3001Ctrl+C \u6216 SIGTERM \u4F1A\u505C\u6B62 CLI \u7BA1\u7406\u7684 Runtime \u5E76\u65AD\u5F00\u3002\u82E5\u6B8B\u7559\u5360\u7528\uFF0C\u540E\u53F0\u53EF\u300C\u5F3A\u5236\u65AD\u8FDE\u300D\uFF1B\u9875\u9762\u672A\u786E\u8BA4\u672C\u673A\u505C\u6B62\u65F6\uFF0C\u5728\u539F\u7535\u8111\u3001\u539F\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C\u5176\u505C\u6B62\u6307\u4EE4\u3002\u4E0D\u8981\u624B\u5DE5\u5220\u9501\u6587\u4EF6\uFF0C\u4E0D\u8981\u6279\u91CF\u6740\u6B7B node\uFF1B\u8EAB\u4EFD\u6821\u9A8C\u5931\u8D25\u65F6\u5148\u6838\u5BF9\u5DE5\u7A0B\u548C\u539F\u8FDB\u7A0B\u3002\u8FD9\u4E9B\u64CD\u4F5C\u4E0D\u4F1A\u63D0\u5BA1\u6216\u53D1\u5E03\u3002
2785
2862
 
2863
+ DEV \u542F\u52A8\u6216\u8FD0\u884C\u5931\u8D25\u65F6\uFF0C\u5148\u8BFB\u53D6\u9875\u9762\u9519\u8BEF\u548C\u8FD0\u884C\u65E5\u5FD7\u4E2D\u7684\u5177\u4F53\u539F\u56E0\uFF0C\u518D\u4FEE\u590D\u5DE5\u7A0B\u6216\u5E73\u53F0\u914D\u7F6E\uFF1B\u4E0D\u8981\u628A\u201C\u5DF2\u8FDE\u63A5\u672C\u5730\u5DE5\u7A0B\u201D\u5F53\u4F5C Runtime \u5DF2\u542F\u52A8\u3002CLI \u5347\u7EA7\u4E0D\u4F1A\u66FF\u6362\u5DF2\u8FD0\u884C\u7684 preview \u8FDB\u7A0B\uFF0C\u9700\u5728\u539F\u7EC8\u7AEF\u9000\u51FA\u65E7\u8FDE\u63A5\u540E\u91CD\u65B0\u6267\u884C\u8FDE\u63A5\u6307\u4EE4\uFF0C\u518D\u542F\u52A8 DEV\uFF1B\u53EA\u5237\u65B0\u7F51\u9875\u65E0\u6548\u3002\u4E0D\u8981\u4E3A\u4E86\u7ED5\u8FC7\u9519\u8BEF\u64C5\u81EA\u5207\u6362\u5E73\u53F0\u3001\u6539 buddyId\u3001\u5220\u9664\u8EAB\u4EFD\u9501\u6216\u63D0\u5BA1\u53D1\u5E03\u3002
2864
+
2786
2865
  ### \u4E3B\u52A8\u63D0\u9192\u4E0E\u6570\u636E\u6743\u9650
2787
2866
 
2788
2867
  Creator 1.7+ \u7684 Booklet \u63D0\u4F9B\u300C\u4E3B\u52A8\u6027\u4E0E\u6570\u636E\u300D\u9875\u7B7E\u3002\u8BFB\u53D6\u4EA4\u4ED8\u76EE\u5F55\u4E2D\u7684 \`service-blueprint.json\`\uFF0C\u6309 \`data.proactiveReminders\` \u4E2D\u7684\u89E6\u53D1\u3001\u9891\u7387\u3001\u9759\u9ED8\u548C\u505C\u6B62\u7EA6\u5B9A\u5B9E\u73B0\u5E76\u9A8C\u8BC1\uFF1B\u5B57\u6BB5\u7F3A\u5931\u8868\u793A\u5C1A\u672A\u6574\u7406\uFF0C\u4E0D\u80FD\u64C5\u81EA\u6DFB\u52A0\u9ED8\u8BA4\u63D0\u9192\u3002\u9875\u9762\u5C55\u793A\u7684\u662F\u521B\u4F5C\u65B9\u6848\uFF0C\u4E0D\u4EE3\u8868\u5B9E\u9645\u8C03\u5EA6\u5DF2\u542F\u7528\u3002\u5E73\u53F0\u6570\u636E\u6743\u9650\u76F4\u63A5\u8BFB\u53D6\u5F53\u524D\u5DE5\u7A0B\u7684 \`data-access.json.requirements\`\uFF1B\u6309\u5B9E\u9645\u9700\u8981\u7EF4\u62A4 ID \u548C\u7528\u9014\uFF0C\u4FDD\u5B58\u540E\u9875\u9762\u540C\u6B65\u3002\u4E0D\u8981\u590D\u5236\u4E00\u4EFD\u5C55\u793A\u7528\u6743\u9650\u6E05\u5355\uFF0C\u4E5F\u4E0D\u8981\u628A\u4E1A\u52A1\u8BB0\u5F55\u6DF7\u4F5C\u5E73\u53F0\u6388\u6743\u3002
@@ -2834,14 +2913,16 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
2834
2913
 
2835
2914
  \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
2836
2915
 
2837
- \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${selectedRuntime ? "\u4ECE\u5DE5\u7A0B\u56FA\u5B9A\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF0C\u4E0D\u81EA\u52A8\u5207\u5230 latest\u3002\u5DE5\u7A0B\u5C1A\u672A\u751F\u6210\u65F6\uFF0C\u5148\u8BE2\u95EE\u5F00\u53D1\u8005\u9009\u62E9\u7248\u672C\uFF0C\u518D\u4F20 --runtime-version <\u51C6\u786E\u7248\u672C|latest|dev> \u67E5\u8BE2\u3002" : "\u4ECE npm \u6700\u65B0 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002CLI \u6BCF\u6B21\u67E5\u8BE2 latest\uFF0C\u540C\u7248\u672C\u590D\u7528\u7F13\u5B58\uFF0C\u4E0D\u590D\u5236\u679A\u4E3E\u3002"}\u76EE\u5F55\u547D\u4EE4\u4F1A\u63D0\u793A\u5DE5\u7A0B\u7248\u672C\u5DEE\u5F02\uFF1B\u4F7F\u7528\u65B0\u7248\u80FD\u529B\u524D\uFF0C\u7531\u4F60\u6216\u5F00\u53D1 Agent \u6309\u63D0\u793A\u5347\u7EA7\u4F9D\u8D56\uFF0C\u68C0\u67E5\u542F\u52A8\u53C2\u6570\u3001\u6A21\u578B\u3001datasets\u3001\u5DE5\u5177\u53CA Hook \u7684\u9002\u914D\u5E76\u9A8C\u8BC1 DEV\u3002CLI \u4E0D\u81EA\u52A8\u4FEE\u6539\u5DE5\u7A0B\u4F9D\u8D56\u6216\u914D\u7F6E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`data-access.json.requirements\`\uFF0C\u6700\u591A 32 \u9879\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0CID \u548C\u7528\u9014\u53BB\u9664\u9996\u5C3E\u7A7A\u767D\uFF0C\u7528\u9014\u4E3A 1\uFF5E200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
2916
+ \u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE npm \u6700\u65B0 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002CLI \u6BCF\u6B21\u67E5\u8BE2 latest\uFF0C\u540C\u7248\u672C\u590D\u7528\u7F13\u5B58\uFF0C\u4E0D\u590D\u5236\u679A\u4E3E\u3002\u76EE\u5F55\u547D\u4EE4\u4F1A\u63D0\u793A\u5DE5\u7A0B\u7248\u672C\u5DEE\u5F02\uFF1B\u4F7F\u7528\u65B0\u7248\u80FD\u529B\u524D\uFF0C\u7531\u4F60\u6216\u5F00\u53D1 Agent \u6309\u63D0\u793A\u5347\u7EA7\u4F9D\u8D56\uFF0C\u68C0\u67E5\u542F\u52A8\u53C2\u6570\u3001\u6A21\u578B\u3001datasets\u3001\u5DE5\u5177\u53CA Hook \u7684\u9002\u914D\u5E76\u9A8C\u8BC1 DEV\u3002CLI \u4E0D\u81EA\u52A8\u4FEE\u6539\u5DE5\u7A0B\u4F9D\u8D56\u6216\u914D\u7F6E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`data-access.json.requirements\`\uFF0C\u6700\u591A 32 \u9879\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0CID \u548C\u7528\u9014\u53BB\u9664\u9996\u5C3E\u7A7A\u767D\uFF0C\u7528\u9014\u4E3A 1\uFF5E200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
2838
2917
 
2839
2918
  Runtime \u542F\u52A8\u65F6\u8BFB\u53D6\u6839\u76EE\u5F55 \`data-access.json\`\uFF0C\u901A\u8FC7 \`PUT /internal/v1/data-access/requirements\` \u767B\u8BB0\uFF0C\u6210\u529F\u540E\u518D\u8FDE\u63A5\u4E8B\u4EF6\u6D41\uFF1B\u767B\u8BB0\u5931\u8D25\u963B\u6B62\u542F\u52A8\u3002\u6587\u4EF6\u7F3A\u5931\u6216\u7A7A\u6570\u7EC4\u90FD\u4F1A\u4E0A\u4F20\u7A7A\u58F0\u660E\u5E76\u6E05\u9664\u65E7\u58F0\u660E\u3002DEV \u4FDD\u5B58\u8BE5\u6587\u4EF6\u540E\u81EA\u52A8\u91CD\u542F\u5E76\u91CD\u65B0\u767B\u8BB0\u3002\u58F0\u660E\u4E0D\u8868\u793A\u7528\u6237\u5DF2\u6388\u6743\uFF1B\u6240\u6709\u9700\u8981\u7684\u6570\u636E\u90FD\u8981\u58F0\u660E\uFF0C\u5305\u62EC\u4F4D\u7F6E \`device.location\` \u548C\u65E5\u5386 \`device.calendar\`\u3002
2840
2919
 
2841
2920
  \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\`\u3002\u5065\u5EB7\u3001\u4F4D\u7F6E\u3001\u65E5\u5386\u7EDF\u4E00\u5148 query\uFF1B\u8FD4\u56DE \`notGranted\` \u65F6\uFF0C\u7528 \`data_access_request({ datasets, reason })\` \u7533\u8BF7\u5DF2\u58F0\u660E\u7684 1\uFF5E8 \u9879\u6570\u636E\uFF0C\u7B49\u5F85\u7528\u6237\u5904\u7406\u540E\u518D\u6B21 query\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query({ datasets, memberId? })\` \u4E0E \`conversation.dataAccess.request({ datasets, reason, idempotencyKey })\`\u3002\u67E5\u8BE2\u53EA\u6709 \`available\` \u643A\u5E26\u6570\u636E\uFF1B\`notDeclared\` \u8981\u4FEE\u6B63\u5DE5\u7A0B\u58F0\u660E\uFF0C\`systemPermissionDenied\` \u8868\u793A\u7CFB\u7EDF\u6743\u9650\u5173\u95ED\uFF0C\u5E94\u5F15\u5BFC\u7528\u6237\u5728 App \u6216\u7CFB\u7EDF\u8BBE\u7F6E\u4E2D\u68C0\u67E5\uFF1B\`unavailable\` \u8868\u793A\u6682\u65E0\u53EF\u7528\u7ED3\u679C\uFF0C\u4E0D\u7B49\u4E8E\u7528\u6237\u62D2\u7EDD\uFF0C\u4E5F\u4E0D\u8981\u53CD\u590D\u53D1\u6388\u6743\u5361\u3002\u4F4D\u7F6E\u3001\u65E5\u5386\u5FEB\u7167\u8FC7\u671F\u540E\u7531\u5E73\u53F0\u5C1D\u8BD5\u8BF7\u6C42\u5728\u7EBF App \u5237\u65B0\uFF0CCLI \u4E0D\u91C7\u96C6\u8BBE\u5907\u6570\u636E\u3002
2842
2921
 
2843
- ${selectedRuntime ? "\u65B0\u5EFA Runtime \u5DE5\u7A0B\u524D\u5FC5\u987B\u8BE2\u95EE\u5F00\u53D1\u8005\u9009\u62E9\u7A33\u5B9A\u7248\u3001\u6D4B\u8BD5\u7248\u6216\u5176\u4ED6\u5DF2\u53D1\u5E03\u51C6\u786E\u7248\u672C\uFF1B\u5F00\u53D1\u8005\u5DF2\u660E\u786E\u6307\u5B9A\u65F6\u6CBF\u7528\u8BE5\u9009\u62E9\u3002\u4F7F\u7528 init --mode direct --runtime-version <\u51C6\u786E\u7248\u672C|latest|dev>\uFF0C\u6807\u7B7E\u4EC5\u5728\u521B\u5EFA\u65F6\u89E3\u6790\uFF0C\u5DE5\u7A0B\u4FDD\u5B58\u51C6\u786E\u7248\u672C\u3002\u5DF2\u6709\u5DE5\u7A0B\u7684 DEV\u3001\u81EA\u52A8\u91CD\u8F7D\u548C push \u6CBF\u7528\u8BE5\u7248\u672C\uFF0C\u4E0D\u56E0\u53D1\u5E03\u65B0\u7248\u800C\u5F3A\u5236\u5347\u7EA7\u3002\u5207\u6362\u7248\u672C\u524D\u5411\u5F00\u53D1\u8005\u786E\u8BA4\uFF0C\u518D\u901A\u8FC7 npm install --save-exact \u5B89\u88C5\u51C6\u786E\u7248\u672C\uFF0C\u9002\u914D\u4E1A\u52A1\u5E76\u9A8C\u8BC1\u3002" : "\u65B0\u5EFA\u5DE5\u7A0B\u52A8\u6001\u9009\u62E9\u516C\u5171 npm latest \u5E76\u9501\u5B9A\u51C6\u786E\u7248\u672C\uFF1B\u67E5\u8BE2\u6216\u9501\u6587\u4EF6\u751F\u6210\u5931\u8D25\u65F6\u505C\u6B62\uFF0C\u4E0D\u56DE\u9000\u5185\u7F6E\u65E7\u7248\u672C\u3002\u5DF2\u6709\u5DE5\u7A0B\u901A\u8FC7\u5305\u7BA1\u7406\u5668\u663E\u5F0F\u5347\u7EA7\u4F9D\u8D56\u3002CLI \u7684 DEV \u542F\u52A8\u3001\u81EA\u52A8\u91CD\u8F7D\u548C push \u5FC5\u987B\u4F7F\u7528\u672C\u6B21 npm \u6700\u65B0\u7A33\u5B9A\u7248\uFF0C\u58F0\u660E\u3001\u5B89\u88C5\u548C npm \u9501\u6587\u4EF6\u7248\u672C\u5FC5\u987B\u4E00\u81F4\uFF0C\u67E5\u8BE2\u5931\u8D25\u4F1A\u963B\u6B62\u64CD\u4F5C\u3002"}
2844
- ${selectedRuntime ? "\u7248\u672C\u5FC5\u987B\u5728\u516C\u5171 npm \u5B58\u5728\uFF0C\u4F9D\u8D56\u58F0\u660E\u3001\u5B9E\u9645\u5B89\u88C5\u4E0E npm \u9501\u6587\u4EF6\u5FC5\u987B\u4E00\u81F4\uFF1B\u67E5\u8BE2\u6216\u5B89\u88C5\u5931\u8D25\u4E0D\u5F97\u6362\u7528\u5176\u4ED6\u7248\u672C\u3002models \u548C datasets \u4E0E\u5DE5\u7A0B\u9009\u5B9A Runtime \u4E00\u81F4\u3002" : ""}
2922
+ \u4F4D\u7F6E\u6216\u65E5\u5386\u7684\u6388\u6743\u8BF7\u6C42\u6BCF\u6B21\u53EA\u80FD\u5305\u542B\u4E00\u4E2A Dataset\uFF0C\u4E0D\u80FD\u628A\u4E8C\u8005\u653E\u5728\u4E00\u8D77\uFF0C\u4E5F\u4E0D\u80FD\u4E0E\u5065\u5EB7\u6570\u636E\u6DF7\u5408\u7533\u8BF7\u3002\u7FA4\u804A query \u7684 memberId \u4F7F\u7528\u6D88\u606F\u524D\u7F00\u91CC\u7684\u7A33\u5B9A\u6210\u5458\u53F7 m_\u2026\uFF0C\u4E0D\u5E26 #\uFF0C\u4E0D\u80FD\u6309\u6635\u79F0\u731C\u6D4B\u3002\u7FA4\u804A\u53D1\u6388\u6743\u5361\u524D\u6838\u5BF9\u5DE5\u7A0B Runtime \u7684 request \u662F\u5426\u652F\u6301 memberId\uFF1B\u652F\u6301\u65F6\u67E5\u8BE2\u548C\u53D1\u5361\u6307\u5411\u540C\u4E00\u6210\u5458\uFF0C\u4E0D\u652F\u6301\u65F6\u5F15\u5BFC\u6210\u5458\u5230\u79C1\u804A\u6388\u6743\uFF0C\u4E0D\u7ED5\u8FC7 Runtime \u76F4\u8C03\u5E73\u53F0\u3002\u79C1\u804A\u4E0D\u4F20 memberId\u3002
2923
+
2924
+ \u65B0\u5EFA\u5DE5\u7A0B\u52A8\u6001\u9009\u62E9\u516C\u5171 npm latest \u5E76\u9501\u5B9A\u51C6\u786E\u7248\u672C\uFF1B\u67E5\u8BE2\u6216\u9501\u6587\u4EF6\u751F\u6210\u5931\u8D25\u65F6\u505C\u6B62\uFF0C\u4E0D\u56DE\u9000\u5185\u7F6E\u65E7\u7248\u672C\u3002\u5DF2\u6709\u5DE5\u7A0B\u901A\u8FC7\u5305\u7BA1\u7406\u5668\u663E\u5F0F\u5347\u7EA7\u4F9D\u8D56\u3002CLI \u7684 DEV \u542F\u52A8\u3001\u81EA\u52A8\u91CD\u8F7D\u548C push \u5FC5\u987B\u4F7F\u7528\u672C\u6B21 npm \u6700\u65B0\u7A33\u5B9A\u7248\uFF0C\u58F0\u660E\u3001\u5B89\u88C5\u548C npm \u9501\u6587\u4EF6\u7248\u672C\u5FC5\u987B\u4E00\u81F4\uFF0C\u67E5\u8BE2\u5931\u8D25\u4F1A\u963B\u6B62\u64CD\u4F5C\u3002
2925
+
2845
2926
 
2846
2927
  \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
2847
2928
 
@@ -2962,7 +3043,8 @@ var LoopbackBrowserLoginAdapter = class {
2962
3043
  #fetch;
2963
3044
  constructor(options) {
2964
3045
  this.#platformUrl = normalizePlatformUrl(options.platformUrl);
2965
- this.#developerWebUrl = resolveDeveloperWebUrl(this.#platformUrl, options.developerWebUrl);
3046
+ this.#developerWebUrl = normalizePlatformUrl(options.developerWebUrl ?? new URL("/developer/", this.#platformUrl));
3047
+ if (this.#developerWebUrl.origin !== this.#platformUrl.origin) throw new TypeError("\u5F00\u53D1\u8005\u540E\u53F0\u4E0E MLB \u7F51\u5173\u5730\u5740\u4E0D\u4E00\u81F4");
2966
3048
  this.#openBrowser = options.openBrowser ?? openExternalUrl;
2967
3049
  this.#onLoginUrl = options.onLoginUrl;
2968
3050
  this.#timeoutMs = positive(options.timeoutMs, DEFAULT_LOGIN_TIMEOUT_MS, "timeoutMs");
@@ -3133,10 +3215,11 @@ var CLI_HELP = `\u642D\u642D Developer Platform CLI
3133
3215
  --version \u67E5\u770B\u5F53\u524D CLI \u7248\u672C
3134
3216
 
3135
3217
  \u76F4\u63A5\u8FD0\u884C buddy-cli \u53EF\u8BC6\u522B\u5F53\u524D\u5DE5\u7A0B\u6216\u5F15\u5BFC\u521B\u5EFA\u3002
3136
- \u9ED8\u8BA4\u5E73\u53F0\uFF1A${DEFAULT_MLB_TEST_URL}\uFF1B\u5F00\u53D1\u8005\u540E\u53F0\uFF1A${DEFAULT_DEVELOPER_WEB_URL}\u3002
3137
- \u8BBE\u7F6E MLB_GATEWAY_URL \u53EF\u7EDF\u4E00\u9009\u62E9\u5176\u4ED6\u5E73\u53F0\uFF0C\u540E\u53F0\u7531\u540C\u4E00\u57DF\u540D\u63A8\u5BFC\uFF1Bdev/preview \u7684 --app-server \u53EA\u8986\u76D6\u672C\u6B21\u547D\u4EE4\u3002
3138
- \u4ECE\u6D77\u5916\u56DE\u8FC1\u963F\u91CC\u4E91\u540E\u91CD\u65B0 login\uFF1B\u65E7\u5DE5\u7A0B\u7528 dev --refresh-token \u6216 preview --refresh-token \u66F4\u65B0\u5F00\u53D1\u51ED\u636E\u548C .env \u5730\u5740\u3002
3218
+ \u6B63\u5F0F\u7248\u56FA\u5B9A\u5E73\u53F0\uFF1A${DEFAULT_MLB_TEST_URL}\uFF1B\u5F00\u53D1\u8005\u540E\u53F0\uFF1A${DEFAULT_DEVELOPER_WEB_URL}\u3002
3219
+ \u65E0\u9700\u8BBE\u7F6E\u5E73\u53F0\u73AF\u5883\u53D8\u91CF\uFF1Bdev/preview \u7684 --app-server \u4E0E --developer-web \u4EC5\u6821\u9A8C\u56FA\u5B9A\u76EE\u6807\uFF0C\u4E0D\u80FD\u5207\u6362\u73AF\u5883\u3002
3220
+ \u51B2\u7A81\u914D\u7F6E\u5148\u79FB\u9664\uFF1B--refresh-token \u53EA\u5237\u65B0\u540C\u4E00\u73AF\u5883\u7684\u5F00\u53D1\u51ED\u636E\uFF0C\u4E0D\u80FD\u8FC1\u79FB\u5DE5\u7A0B\u6216\u8DE8\u73AF\u5883\u590D\u7528 Token\u3002
3139
3221
  CLI \u767B\u5F55\u6388\u6743\u4E0E\u9884\u89C8\u8FDE\u63A5\u76F4\u63A5\u8BF7\u6C42 MLB\uFF1B\u7F51\u9875\u627F\u8F7D\u754C\u9762\u30020.20 \u5347\u7EA7\u540E\u8BF7\u91CD\u65B0\u767B\u5F55\u3002
3222
+ DEV \u5931\u8D25\u65F6\u67E5\u770B\u9875\u9762\u548C\u8FD0\u884C\u65E5\u5FD7\u4E2D\u7684\u5177\u4F53\u539F\u56E0\u3002\u5347\u7EA7 CLI \u540E\uFF0C\u9000\u51FA\u65E7 preview \u8FDB\u7A0B\u5E76\u91CD\u65B0\u6267\u884C\u8FDE\u63A5\u6307\u4EE4\uFF0C\u518D\u542F\u52A8 DEV\u3002
3140
3223
  \u6B63\u5E38\u547D\u4EE4\u5148\u8054\u7F51\u81EA\u68C0\uFF0C\u65E7\u7248\u81EA\u52A8\u66F4\u65B0\u540E\u7EE7\u7EED\u6267\u884C\uFF1B\u5931\u8D25\u65F6\u505C\u6B62\u3002\u5E2E\u52A9\u3001--version \u548C dev stop \u79BB\u7EBF\u53EF\u7528\u3002
3141
3224
  \u53C2\u6570\u4E0E\u793A\u4F8B: buddy-cli <\u547D\u4EE4> --help\uFF0C\u4F8B\u5982 buddy-cli init --help\u3002
3142
3225
  Coding Agent \u5F00\u59CB\u5DE5\u4F5C\u524D\u8BF7\u8BFB\u53D6 buddy-cli guide\u3002`;
@@ -3168,9 +3251,9 @@ var GUIDE_HELP = `\u7528\u6CD5: buddy-cli guide
3168
3251
  \u8F93\u51FA Coding Agent \u7684\u5B8C\u6574\u5F00\u53D1\u6307\u5F15\uFF0C\u5305\u62EC\u521B\u4F5C\u5F00\u573A\u3001\u8D44\u6599\u786E\u8BA4\u3001Skill \u63A5\u7EED\u3001\u5B9E\u73B0\u4E0E\u4EA4\u4ED8\u89C4\u5219\u3002
3169
3252
  \u65E0\u9700\u5DE5\u7A0B\u6216\u767B\u5F55\uFF1B\u5148\u8054\u7F51\u68C0\u67E5 CLI \u5E76\u6309\u9700\u81EA\u52A8\u66F4\u65B0\uFF0C\u518D\u8F93\u51FA\u65B0\u7248\u6307\u5357\uFF0C\u4E0D\u4FEE\u6539\u5DE5\u7A0B\u6216\u6267\u884C\u5F00\u53D1\u3002`;
3170
3253
  function agentGuide(options = {}) {
3171
- return renderAgentGuide(allowsRuntimeVersionSelection(options));
3254
+ return renderAgentGuide();
3172
3255
  }
3173
- function renderAgentGuide(selectedRuntime = false) {
3256
+ function renderAgentGuide() {
3174
3257
  return `# Coding Agent \u5F00\u53D1\u6307\u5F15
3175
3258
 
3176
3259
  \u901A\u7528\u89C4\u5219\u5728\u6B64\u8BFB\u53D6\uFF1B\u53C2\u6570\u89C1 buddy-cli <\u547D\u4EE4> --help\uFF0C\u5DE5\u7A0B\u72B6\u6001\u4E0E\u5177\u4F53\u63A5\u7EED\u6B65\u9AA4\u4EE5 CLI \u8FD4\u56DE\u7684 HANDOFF.md \u4E3A\u51C6\u3002
@@ -3179,11 +3262,7 @@ Skill \u7684\u5177\u4F53\u6D41\u7A0B\u8BFB\u53D6 HANDOFF.md \u4E2D\u7684\u6587\u
3179
3262
  ## \u51C6\u5907\u5B8C\u6210\u540E\uFF0C\u5F00\u59CB\u521B\u4F5C\u5BF9\u8BDD
3180
3263
 
3181
3264
  \u7528\u6237\u4ECE\u5F00\u53D1\u8005\u540E\u53F0\u590D\u5236\u521B\u4F5C\u63D0\u793A\u8BCD\u65F6\uFF0C\u76EE\u6807\u662F\u4E0E\u4F60\u4E00\u8D77\u628A\u60F3\u6CD5\u505A\u6210\u642D\u5B50\u3002\u5B89\u88C5 CLI\u3001\u68C0\u67E5\u4F9D\u8D56\u548C\u9605\u8BFB\u672C\u6307\u5357\u662F\u51C6\u5907\u6B65\u9AA4\uFF0C\u5B8C\u6210\u540E\u8981\u4E3B\u52A8\u8FDB\u5165\u521B\u4F5C\u5BF9\u8BDD\u3002
3182
- ${selectedRuntime ? `\u5F53\u524D\u7EC8\u7AEF\u914D\u7F6E\u4E86\u81EA\u5B9A\u4E49\u7F51\u5173\u3002\u5148\u8BE2\u95EE\uFF1A\u201C\u8FD9\u4E2A\u642D\u5B50\u51C6\u5907\u9762\u5411\u516C\u5171\u73AF\u5883\uFF0C\u8FD8\u662F\u5185\u90E8\u6D4B\u8BD5\u73AF\u5883\uFF1F\u201D\u7528\u6237\u5DF2\u660E\u786E\u9009\u62E9\u65F6\u76F4\u63A5\u6CBF\u7528\uFF1B\u4E0D\u80FD\u56E0\u4E3A\u68C0\u6D4B\u5230\u73AF\u5883\u53D8\u91CF\u5C31\u66FF\u7528\u6237\u9009\u62E9\u5185\u90E8\u6D4B\u8BD5\u3002\u8FD9\u4E2A\u9009\u62E9\u786E\u5B9A\u540E\u7EED\u5F00\u53D1\u4E0E\u53D1\u5E03\u7684\u76EE\u6807\uFF0C\u4E0D\u4EE3\u8868\u73B0\u5728\u6267\u884C\u63D0\u5BA1\u6216\u53D1\u5E03\u3002
3183
- \u9009\u62E9\u516C\u5171\u73AF\u5883\uFF1A\u540E\u7EED\u6BCF\u6761 CLI \u547D\u4EE4\u663E\u5F0F\u4F7F\u7528 MLB_GATEWAY_URL=${DEFAULT_MLB_TEST_URL}\uFF0C\u5148\u5728\u8BE5\u73AF\u5883\u91CD\u65B0\u8BFB\u53D6 buddy-cli guide\uFF0C\u518D\u767B\u5F55\u3001\u521B\u5EFA\u3001\u4FEE\u6539\u8D44\u6599\u3001\u9884\u89C8\u548C\u4E0A\u4F20\uFF1B\u9075\u5FAA\u516C\u5171\u73AF\u5883\u7684\u6700\u65B0\u7A33\u5B9A\u7248\u89C4\u5219\uFF0C\u4E0D\u518D\u8BE2\u95EE\u6D4B\u8BD5\u7248\u672C\u3002
3184
- \u9009\u62E9\u5185\u90E8\u6D4B\u8BD5\uFF1A\u540E\u7EED\u547D\u4EE4\u6CBF\u7528\u5F53\u524D MLB_GATEWAY_URL\uFF1B\u5F00\u59CB\u751F\u6210 Runtime \u5DE5\u7A0B\u524D\uFF0C\u518D\u8BE2\u95EE\u4F7F\u7528\u6700\u65B0\u7A33\u5B9A\u7248\u3001\u6700\u65B0\u6D4B\u8BD5\u7248\u8FD8\u662F\u5176\u4ED6\u5DF2\u53D1\u5E03\u51C6\u786E\u7248\u672C\u3002\u4E0D\u80FD\u628A\u9009\u62E9\u5185\u90E8\u73AF\u5883\u7B49\u540C\u4E8E\u9009\u62E9 dev\u3002
3185
- \u5728\u76EE\u6807\u73AF\u5883\u786E\u8BA4\u524D\uFF0C\u4E0D\u767B\u5F55\u3001\u767B\u8BB0\u642D\u5B50\u3001\u5B89\u88C5\u5DE5\u7A0B Runtime \u6216\u4E0A\u4F20\u3002\u5DF2\u6709\u5DE5\u7A0B\u5E94\u6838\u5BF9\u76EE\u6807\u8D26\u53F7\u4E0E\u642D\u5B50\u5F52\u5C5E\uFF0C\u4E0D\u628A\u4E00\u4E2A\u5E73\u53F0\u7684 buddyId \u6216\u51ED\u636E\u76F4\u63A5\u7528\u4E8E\u53E6\u4E00\u4E2A\u5E73\u53F0\uFF1B\u672C\u6B21\u4E0D\u81EA\u52A8\u8FC1\u79FB\u642D\u5B50\u3002\u9009\u62E9\u540E\u5728\u6574\u4E2A\u5F00\u53D1\u6D41\u7A0B\u6CBF\u7528\u5BF9\u5E94\u73AF\u5883\uFF0C\u4E0D\u8981\u6267\u884C\u5B8C\u4E00\u6B21\u547D\u4EE4\u53C8\u56DE\u5230\u7EC8\u7AEF\u9ED8\u8BA4\u5730\u5740\u3002\u5B8C\u6210\u73AF\u5883\u9009\u62E9\u540E\u518D\u6309\u4E0B\u9762\u89C4\u5219\u5F00\u59CB\u521B\u4F5C\u5BF9\u8BDD\u3002
3186
- ` : ""}
3265
+
3187
3266
  \u51C6\u5907\u6210\u529F\u4E14\u7528\u6237\u5C1A\u672A\u8BF4\u660E\u521B\u4F5C\u60F3\u6CD5\u65F6\uFF0C\u76F4\u63A5\u7528\u4E00\u53E5\u7B80\u77ED\u95EE\u5019\u548C\u4E00\u4E2A\u95EE\u9898\u5F00\u573A\uFF0C\u4F8B\u5982\uFF1A\u201C\u51C6\u5907\u597D\u4E86\uFF01\u4F60\u60F3\u521B\u4F5C\u4E00\u4E2A\u600E\u6837\u7684\u642D\u5B50\uFF1F\u201D\u7136\u540E\u7B49\u5F85\u56DE\u7B54\uFF0C\u4E0D\u4EE5\u5B89\u88C5\u62A5\u544A\u7ED3\u675F\uFF0C\u4E0D\u5217\u51FA\u7248\u672C\u53F7\u3001\u670D\u52A1\u5668\u5730\u5740\u6216\u65E0\u5173\u7684\u73AF\u5883\u68C0\u67E5\u7ED3\u679C\u3002
3188
3267
  \u5982\u679C\u7528\u6237\u5DF2\u7ECF\u7ED9\u51FA\u60F3\u6CD5\uFF0C\u6CBF\u7528\u5DF2\u6709\u4FE1\u606F\u63A8\u8FDB\uFF0C\u53EA\u8865\u95EE\u51B3\u5B9A\u4E0B\u4E00\u6B65\u7684\u5173\u952E\u7F3A\u53E3\uFF1B\u5982\u679C\u660E\u786E\u8981\u7EE7\u7EED\u5DF2\u6709\u5DE5\u7A0B\uFF0C\u5148\u8BFB\u53D6\u8BE5\u5DE5\u7A0B\u7684\u8D44\u6599\u3001\u4EE3\u7801\u4E0E HANDOFF.md\uFF0C\u518D\u63A5\u7EED\u5F53\u524D\u8FDB\u5EA6\u3002\u4E0D\u8981\u91CD\u65B0\u8BE2\u95EE\u7528\u6237\u5DF2\u56DE\u7B54\u7684\u95EE\u9898\uFF0C\u4E5F\u4E0D\u8981\u4EC5\u56E0\u5F53\u524D\u76EE\u5F55\u5B58\u5728\u5DE5\u7A0B\u5C31\u64C5\u81EA\u51B3\u5B9A\u6CBF\u7528\u5B83\u3002
3189
3268
  \u7528\u6237\u5C1A\u672A\u8868\u8FBE\u521B\u4F5C\u65B9\u5411\u65F6\uFF0C\u4E0D\u63D0\u524D\u62DF\u5B9A\u642D\u5B50\u3001\u521D\u59CB\u5316\u5DE5\u7A0B\u6216\u542F\u52A8\u8BBF\u8C08\u3002\u9996\u6B21\u4EA4\u6D41\u524D\u53EA\u51C6\u5907 CLI \u53CA\u5176\u5FC5\u9700\u8FD0\u884C\u73AF\u5883\uFF1B\u767B\u5F55\u3001\u5DE5\u7A0B Runtime \u548C Creator/Avatar Skill \u6309\u540E\u7EED\u6D41\u7A0B\u9700\u8981\u518D\u51C6\u5907\uFF0C\u4E0D\u628A\u8FD9\u4E9B\u64CD\u4F5C\u8BBE\u4E3A\u5F00\u59CB\u804A\u5929\u7684\u524D\u63D0\u3002
@@ -3191,11 +3270,13 @@ ${selectedRuntime ? `\u5F53\u524D\u7EC8\u7AEF\u914D\u7F6E\u4E86\u81EA\u5B9A\u4E4
3191
3270
 
3192
3271
  ## CLI \u7248\u672C\u4E0E\u6267\u884C\u89C4\u5219
3193
3272
 
3194
- \u6CBF\u7528 CLI \u8FD0\u884C\u73AF\u5883\u4E2D\u7684 MLB_GATEWAY_URL\uFF0C\u767B\u5F55\u3001\u521B\u5EFA\u3001\u4FEE\u6539\u8D44\u6599\u3001\u4E0A\u4F20\u548C\u9884\u89C8\u4F7F\u7528\u540C\u4E00\u5E73\u53F0\uFF1B\u672A\u914D\u7F6E\u5730\u5740\u65F6\u624D\u4F7F\u7528 ${DEFAULT_MLB_TEST_URL}\u3002\u540E\u53F0\u5730\u5740\u7531\u540C\u4E00\u57DF\u540D\u7684 /developer/ \u63A8\u5BFC\u3002\u4E0D\u8981\u4E3A\u4E86\u7167\u6284\u793A\u4F8B\u800C\u6E05\u7A7A\u3001\u8986\u76D6\u5DF2\u6709\u5E73\u53F0\u914D\u7F6E\uFF0C\u4E5F\u4E0D\u8981\u5728\u672A\u83B7\u8981\u6C42\u65F6\u5207\u6362\u5E73\u53F0\u3002Coding Agent \u7684 CLI \u5B50\u8FDB\u7A0B\u9700\u8981\u7EE7\u627F\u8BE5\u73AF\u5883\u53D8\u91CF\uFF1BCLI \u4E0D\u8BFB\u53D6\u7EC8\u7AEF\u542F\u52A8\u914D\u7F6E\u6216\u628A\u5DE5\u7A0B .env \u5F53\u4F5C\u5168\u5C40\u5730\u5740\u914D\u7F6E\u3002\u7528\u6237\u660E\u786E\u5207\u6362\u5E73\u53F0\u540E\u91CD\u65B0 login\uFF1B\u5DF2\u6709\u5DE5\u7A0B\u9700\u8981\u66F4\u6362\u5F00\u53D1\u51ED\u636E\u65F6\uFF0C\u7528 dev --refresh-token \u6216 preview --refresh-token\uFF0C\u4FDD\u7559 package.json.buddyId \u4E0E\u4E1A\u52A1\u914D\u7F6E\u3002
3273
+ \u6B63\u5F0F\u7248 buddy-cli \u56FA\u5B9A\u8FDE\u63A5 ECS Test\uFF08${DEFAULT_MLB_TEST_URL}\uFF09\uFF0C\u767B\u5F55\u3001\u521B\u5EFA\u3001\u8D44\u6599\u4FEE\u6539\u3001\u4E0A\u4F20\u3001\u9884\u89C8\u4E0E Runtime \u4F7F\u7528\u540C\u4E00\u5E73\u53F0\u3002\u65E0\u9700\u8BBE\u7F6E\u7F51\u5173\u53D8\u91CF\u6216\u8BE2\u95EE\u53D1\u5E03\u73AF\u5883\u3002\u5730\u5740\u53C2\u6570\u4EC5\u6821\u9A8C\u76EE\u6807\uFF1B\u51B2\u7A81\u914D\u7F6E\u5FC5\u987B\u5148\u5904\u7406\uFF0C\u4E0D\u80FD\u7528 --refresh-token \u5207\u6362\u73AF\u5883\u3002Runtime \u5730\u5740\u7531 CLI \u6CE8\u5165\u3002\u5176\u4ED6\u73AF\u5883\u7684\u5DE5\u7A0B\u8BF7\u4F7F\u7528\u5BF9\u5E94 CLI\uFF1B\u9700\u8981\u8FC1\u79FB\u65F6\uFF0C\u5728\u65B0\u76EE\u5F55\u91CD\u65B0\u767B\u8BB0\u642D\u5B50\u540E\u590D\u5236\u4E1A\u52A1\u4EE3\u7801\uFF0C\u4E0D\u590D\u5236 .env\u3001buddyId \u6216\u51ED\u636E\u3002
3274
+
3275
+ preview \u8FDE\u63A5\u524D\u53CA dev \u542F\u52A8\u524D\u4F1A\u68C0\u67E5\u5DE5\u7A0B .env \u7F51\u5173\u3002\u68C0\u6D4B\u5230\u5DF2\u77E5\u65E7 ECS \u5730\u5740\u65F6\uFF0CCLI \u5728\u542F\u52A8 DEV \u65F6\u6821\u9A8C\u642D\u5B50\u5F52\u5C5E\u5E76\u81EA\u52A8\u66F4\u65B0\u8FDE\u63A5\u914D\u7F6E\uFF1BAgent \u8BFB\u53D6\u547D\u4EE4\u7ED3\u679C\u7EE7\u7EED\u64CD\u4F5C\uFF0C\u65E0\u9700\u624B\u6539 .env\u3002\u5176\u4ED6\u5E73\u53F0\u4E0D\u4E00\u81F4\u65F6\u5148\u786E\u8BA4\u76EE\u6807\u73AF\u5883\uFF0C\u4E0D\u53CD\u590D\u91CD\u8DD1\u547D\u4EE4\u6216\u64C5\u81EA\u8986\u76D6\u51ED\u636E\u3002
3195
3276
 
3196
3277
  \u4F7F\u7528\u5B98\u65B9 buddy-cli \u5165\u53E3\u3002\u6BCF\u6761\u6B63\u5E38\u547D\u4EE4\uFF08\u5305\u62EC guide\uFF09\u6267\u884C\u524D\u90FD\u4F1A\u67E5\u8BE2\u516C\u5171 npm latest\uFF1B\u7248\u672C\u8FC7\u65E7\u65F6\u81EA\u52A8\u66F4\u65B0\uFF0C\u518D\u7531\u65B0\u7248\u6267\u884C\u540C\u4E00\u547D\u4EE4\u3002\u7B49\u5F85\u5F53\u524D\u547D\u4EE4\u5B8C\u6210\uFF0C\u4E0D\u91CD\u590D\u53D1\u8D77\uFF0C\u4E0D\u53E6\u5F00\u8FDB\u7A0B\u540C\u65F6\u91CD\u8DD1\u3002
3197
3278
  \u5168\u5C40\u5B89\u88C5\u66F4\u65B0\u5BF9\u5E94 npm \u73AF\u5883\u7684\u5B89\u88C5\uFF1B\u6E90\u7801\u3001npm link\u3001\u9879\u76EE\u5185\u5B89\u88C5\u548C npx \u901A\u8FC7\u7F13\u5B58\u7684\u65B0\u7248\u7EE7\u7EED\u6267\u884C\uFF0C\u4E0D\u6539\u5199\u6E90\u7801\u6216\u9879\u76EE\u4F9D\u8D56\u3002\u53C2\u6570\u3001\u5DE5\u4F5C\u76EE\u5F55\u3001\u7EC8\u7AEF\u8F93\u5165\u8F93\u51FA\u548C\u9000\u51FA\u72B6\u6001\u4FDD\u7559\u3002\u4E00\u6B21\u8C03\u7528\u6700\u591A\u81EA\u52A8\u5207\u6362\u4E00\u6B21\uFF1B\u5F53\u524D\u7248\u672C\u9AD8\u4E8E latest \u65F6\u4E0D\u964D\u7EA7\uFF0C\u5DF2\u8FD0\u884C\u7684 DEV \u4E0D\u4F1A\u56E0\u53D1\u5E03\u65B0 CLI \u81EA\u52A8\u91CD\u542F\u3002
3198
- \u5E2E\u52A9\u3001\u5404\u547D\u4EE4 --help\u3001--version \u548C\u5E94\u6025\u6E05\u7406 dev stop \u79BB\u7EBF\u53EF\u7528\uFF1Bupdate \u662F\u5355\u72EC\u68C0\u67E5\u6216\u66F4\u65B0\u5165\u53E3\u3002\u67E5\u8BE2\u6216\u66F4\u65B0\u5931\u8D25\u65F6\u539F\u4E1A\u52A1\u64CD\u4F5C\u4E0D\u4F1A\u5F00\u59CB\uFF0C\u6839\u636E\u9519\u8BEF\u5904\u7406\u540E\u91CD\u8BD5\uFF0C\u4E0D\u8C03\u7528\u65E7\u7248\u6E90\u7801\u7ED5\u8FC7\u68C0\u67E5\u3002\u65E7 CLI \u9700\u5148\u901A\u8FC7\u5B98\u65B9 npm \u5B89\u88C5\u547D\u4EE4\u5347\u7EA7\u4E00\u6B21\uFF0C\u624D\u80FD\u83B7\u5F97\u6B64\u673A\u5236\u3002
3279
+ \u5E2E\u52A9\u3001\u5404\u547D\u4EE4 --help\u3001--version \u548C\u5E94\u6025\u6E05\u7406 dev stop \u79BB\u7EBF\u53EF\u7528\uFF1Bupdate \u662F\u5355\u72EC\u68C0\u67E5\u6216\u66F4\u65B0\u5165\u53E3\u3002\u5B89\u88C5\u4E3B\u52A8\u5237\u65B0 npm \u7248\u672C\u7F13\u5B58\uFF0CETARGET \u6700\u591A\u91CD\u8BD5\u4E00\u6B21\uFF1B\u4ECD\u5931\u8D25\u4F1A\u8BF4\u660E\u5177\u4F53\u539F\u56E0\u3002\u67E5\u8BE2\u6216\u66F4\u65B0\u5931\u8D25\u65F6\u539F\u4E1A\u52A1\u64CD\u4F5C\u4E0D\u4F1A\u5F00\u59CB\uFF0C\u6839\u636E\u9519\u8BEF\u5904\u7406\u540E\u91CD\u8BD5\uFF0C\u4E0D\u8C03\u7528\u65E7\u7248\u6E90\u7801\u7ED5\u8FC7\u68C0\u67E5\u3002\u65E7 CLI \u9700\u5148\u901A\u8FC7\u5B98\u65B9 npm \u5B89\u88C5\u547D\u4EE4\u5347\u7EA7\u4E00\u6B21\uFF0C\u624D\u80FD\u83B7\u5F97\u6B64\u673A\u5236\u3002
3199
3280
  CLI \u81EA\u52A8\u66F4\u65B0\u4E0D\u7B49\u4E8E\u5DE5\u7A0B Runtime \u5DF2\u9002\u914D\u3002\u4ECD\u987B\u6839\u636E Runtime \u68C0\u67E5\u7ED3\u679C\u66F4\u65B0\u5DE5\u7A0B\u4F9D\u8D56\u3001\u9501\u6587\u4EF6\u548C\u5FC5\u8981\u7684\u4E1A\u52A1\u4EE3\u7801\uFF0C\u5B8C\u6210\u9A8C\u8BC1\u540E\u518D\u542F\u52A8\u6216\u4E0A\u4F20\uFF1B\u4E0D\u8981\u53EA\u4FEE\u6539\u7248\u672C\u53F7\u5C31\u5BA3\u79F0\u9002\u914D\u5B8C\u6210\u3002
3200
3281
  \u901A\u7528\u89C4\u5219\u4EE5\u672C\u547D\u4EE4\u7684\u5F53\u524D\u8F93\u51FA\u4E3A\u51C6\u3002HANDOFF.md \u53EA\u63D0\u4F9B\u5F53\u524D\u5DE5\u7A0B\u3001Skill \u8DEF\u5F84\u53CA\u5177\u4F53\u63A5\u7EED\u65B9\u5F0F\uFF0C\u4E0D\u5305\u542B\u6574\u4EFD\u5F00\u53D1\u6307\u5357\u3002
3201
3282
 
@@ -3218,56 +3299,25 @@ Coding Agent \u5E94\u4F20\u5165\u6309\u4E0A\u8FF0\u89C4\u5219\u786E\u5B9A\u7684\
3218
3299
  Coding Agent \u6839\u636E\u5DF2\u786E\u8BA4\u624B\u518C\u6216\u9700\u6C42\u63A8\u8FDB\u5B9E\u73B0\uFF1B\u53EA\u4E3A\u5173\u952E\u7F3A\u53E3\u8BE2\u95EE\uFF0C\u4E0D\u56FA\u5B9A\u8FFD\u52A0\u7B56\u7565\u786E\u8BA4\u3002
3219
3300
  \u6240\u6709\u642D\u5B50\u7EDF\u4E00\u4F7F\u7528\u5B98\u65B9 Runtime\uFF1B\u9700\u6C42\u660E\u786E\u65F6\u4F7F\u7528 --mode direct\uFF0C\u9700\u8981\u68B3\u7406\u9700\u6C42\u65F6\u4F7F\u7528 --mode create\u3002
3220
3301
 
3221
- ${implementationGuide(selectedRuntime)}
3302
+ ${implementationGuide()}
3222
3303
 
3223
3304
  ${DEVELOPMENT_HANDOFF}`;
3224
3305
  }
3225
3306
  var AGENT_GUIDE = renderAgentGuide();
3226
- function initHelp(options = {}) {
3227
- return allowsRuntimeVersionSelection(options) ? `${INIT_HELP}
3228
- \u5F53\u524D\u73AF\u5883\u7684 Runtime \u7248\u672C\u9009\u62E9\uFF1A
3229
- --runtime-version <\u51C6\u786E\u7248\u672C|latest|dev> direct \u9996\u6B21\u751F\u6210 Runtime \u5DE5\u7A0B\u524D\u5FC5\u987B\u9009\u62E9\uFF1B\u975E\u4EA4\u4E92\u8C03\u7528\u7F3A\u5C11\u9009\u62E9\u4F1A\u8FD4\u56DE\u53EF\u7528\u7248\u672C\uFF0C\u4E0D\u767B\u8BB0\u8D44\u6599\u3002
3230
- \u8BF7 Coding Agent \u5148\u8BE2\u95EE\u5F00\u53D1\u8005\uFF1Bcreate \u4EC5\u68B3\u7406\u9700\u6C42\uFF0C\u5728\u63A5\u7EED direct \u65F6\u518D\u9009\u62E9\u3002\u5DF2\u6709\u5DE5\u7A0B\u6CBF\u7528\u51C6\u786E\u7248\u672C\uFF0Cinit \u4E0D\u5347\u7EA7\u4F9D\u8D56\u3002` : INIT_HELP;
3307
+ function initHelp(_options = {}) {
3308
+ return INIT_HELP;
3231
3309
  }
3232
- function cliHelp(options = {}) {
3233
- return allowsRuntimeVersionSelection(options) ? CLI_HELP.replaceAll("\u67E5\u770B\u6700\u65B0 Runtime", "\u67E5\u770B\u9009\u5B9A Runtime") + "\n\u5F53\u524D\u73AF\u5883\u53EF\u9009\u62E9 Runtime \u7248\u672C\uFF0C\u751F\u6210\u5DE5\u7A0B\u524D\u5148\u8BE2\u95EE\u5F00\u53D1\u8005\uFF1B\u8BE6\u89C1 buddy-cli init --help\u3002" : CLI_HELP;
3310
+ function cliHelp(_options = {}) {
3311
+ return CLI_HELP;
3234
3312
  }
3235
3313
 
3236
3314
  // packages/cli-core/src/dev/local-stop.ts
3237
3315
  import { execFile as execFile5 } from "node:child_process";
3238
3316
  import { promisify as promisify5 } from "node:util";
3239
- import { readFile as readFile14, readdir as readdir4, realpath as realpath5, rmdir as rmdir3, unlink as unlink7 } from "node:fs/promises";
3317
+ import { readFile as readFile13, readdir as readdir4, realpath as realpath5, rmdir as rmdir3, unlink as unlink8 } from "node:fs/promises";
3240
3318
  import { join as join15 } from "node:path";
3241
3319
  import { setTimeout as delay } from "node:timers/promises";
3242
3320
 
3243
- // packages/cli-core/src/dev/errors.ts
3244
- var BuddyDevError = class extends Error {
3245
- code;
3246
- phase;
3247
- retryable;
3248
- constructor(options) {
3249
- super(options.message, options.cause === void 0 ? void 0 : { cause: options.cause });
3250
- this.name = "BuddyDevError";
3251
- this.code = options.code;
3252
- this.phase = options.phase;
3253
- this.retryable = options.retryable ?? false;
3254
- }
3255
- };
3256
- function isAbortLike(error2) {
3257
- return error2 instanceof DOMException && error2.name === "AbortError" || error2 instanceof Error && error2.name === "AbortError";
3258
- }
3259
- function abortedDevError(signal) {
3260
- return new BuddyDevError({
3261
- code: "DEV_ABORTED",
3262
- phase: "stop",
3263
- message: "\u642D\u642D DEV \u542F\u52A8\u5DF2\u53D6\u6D88\u3002",
3264
- ...signal?.reason === void 0 ? {} : { cause: signal.reason }
3265
- });
3266
- }
3267
- function throwIfDevAborted(signal) {
3268
- if (signal?.aborted) throw abortedDevError(signal);
3269
- }
3270
-
3271
3321
  // packages/cli-core/src/dev/process.ts
3272
3322
  import { promisify as promisify4 } from "node:util";
3273
3323
  import { spawn as spawnChild, execFile as execFile4 } from "node:child_process";
@@ -3565,7 +3615,7 @@ async function stopLocalDev(options) {
3565
3615
  }
3566
3616
  if (names.length !== 1 || !/^owner-[a-f0-9-]+\.json$/u.test(names[0])) throw failure("DEV \u9501\u4FE1\u606F\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u68C0\u67E5\u539F\u7EC8\u7AEF\uFF1B\u672A\u7EC8\u6B62\u4EFB\u4F55\u8FDB\u7A0B\u3002");
3567
3617
  const ownerPath = join15(path, names[0]);
3568
- const source = await readFile14(ownerPath, "utf8");
3618
+ const source = await readFile13(ownerPath, "utf8");
3569
3619
  const owner = JSON.parse(source);
3570
3620
  if (!validPid2(owner.pid) || owner.runtimePid !== void 0 && !validPid2(owner.runtimePid)) throw failure("DEV \u9501\u4E2D\u7684 PID \u65E0\u6548\u3002");
3571
3621
  const root = await realpath5(options.projectRoot);
@@ -3593,7 +3643,7 @@ async function stopLocalDev(options) {
3593
3643
  const cwd = (await exec("/usr/sbin/lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"])).stdout.split("\n").find((line) => line.startsWith("n"))?.slice(1);
3594
3644
  if (!cwd || await realpath5(cwd) !== root || !identity.endsWith(` ${join15(root, "start.mjs")}`) || !/\bnode\s/u.test(identity)) throw failure(`\u65E0\u6CD5\u786E\u8BA4\u65E7 Runtime\uFF08PID ${pid}\uFF09\u5C5E\u4E8E\u5F53\u524D\u5DE5\u7A0B\uFF0C\u672A\u7EC8\u6B62\u8BE5\u8FDB\u7A0B\u3002`);
3595
3645
  }
3596
- if (await readFile14(ownerPath, "utf8") !== source || await processIdentity(pid) !== identity || alive2(owner.pid)) throw failure("DEV \u8FDB\u7A0B\u72B6\u6001\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C dev stop\u3002");
3646
+ if (await readFile13(ownerPath, "utf8") !== source || await processIdentity(pid) !== identity || alive2(owner.pid)) throw failure("DEV \u8FDB\u7A0B\u72B6\u6001\u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C dev stop\u3002");
3597
3647
  try {
3598
3648
  process.kill(-pid, "SIGTERM");
3599
3649
  } catch (error2) {
@@ -3620,7 +3670,7 @@ async function stopLocalDev(options) {
3620
3670
  }
3621
3671
  if (pid && (alive2(pid) || alive2(-pid))) throw failure(`Runtime \u8FDB\u7A0B\u7EC4 ${pid} \u4ECD\u6709\u6B8B\u7559\u4E14\u65E0\u6CD5\u5B8C\u6574\u786E\u8BA4\u8EAB\u4EFD\uFF0C\u8BF7\u68C0\u67E5\u539F\u7EC8\u7AEF\uFF1B\u4FDD\u7559\u8FDB\u7A0B\u9501\u3002`);
3622
3672
  try {
3623
- if (await readFile14(ownerPath, "utf8") === source) await unlink7(ownerPath);
3673
+ if (await readFile13(ownerPath, "utf8") === source) await unlink8(ownerPath);
3624
3674
  } catch (error2) {
3625
3675
  if (error2.code !== "ENOENT") throw error2;
3626
3676
  }
@@ -3633,127 +3683,6 @@ async function stopLocalDev(options) {
3633
3683
  // packages/cli-core/src/commands/dev.ts
3634
3684
  import { resolve as resolve14 } from "node:path";
3635
3685
 
3636
- // packages/cli-core/src/dev/project-env.ts
3637
- import { constants } from "node:fs";
3638
- import { open as open4, rename as rename9, unlink as unlink8 } from "node:fs/promises";
3639
- import { randomUUID as randomUUID7 } from "node:crypto";
3640
- import { join as join16 } from "node:path";
3641
- import { parseEnv } from "node:util";
3642
- function invalid(message) {
3643
- return new BuddyDevError({ code: "DEV_CONFIG_INVALID", phase: "config", message });
3644
- }
3645
- async function readLocalFile(path) {
3646
- let file;
3647
- try {
3648
- file = await open4(path, constants.O_RDONLY | constants.O_NOFOLLOW);
3649
- const stat2 = await file.stat();
3650
- if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > 256 * 1024) throw invalid("\u672C\u5730\u914D\u7F6E\u5FC5\u987B\u662F\u5C0F\u4E8E 256 KB \u7684\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u94FE\u63A5\u3002");
3651
- return await file.readFile("utf8");
3652
- } catch (cause) {
3653
- if (cause.code === "ENOENT") return "";
3654
- if (cause instanceof BuddyDevError) throw cause;
3655
- throw invalid("\u65E0\u6CD5\u8BFB\u53D6\u5DE5\u7A0B\u672C\u5730\u914D\u7F6E\uFF0C\u8BF7\u68C0\u67E5 .env \u548C .gitignore \u7684\u6587\u4EF6\u7C7B\u578B\u4E0E\u6743\u9650\u3002");
3656
- } finally {
3657
- await file?.close();
3658
- }
3659
- }
3660
- async function readProjectEnvironment(projectRoot) {
3661
- const source = await readLocalFile(join16(projectRoot, ".env"));
3662
- let values;
3663
- try {
3664
- values = parseEnv(source);
3665
- } catch {
3666
- throw invalid("\u5DE5\u7A0B .env \u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002");
3667
- }
3668
- return values;
3669
- }
3670
- async function projectBuddyToken(projectRoot, gatewayUrl) {
3671
- const values = await readProjectEnvironment(projectRoot);
3672
- if (!values.BUDDY_TOKEN) return void 0;
3673
- if (values.MLB_GATEWAY_URL) {
3674
- let gateway;
3675
- try {
3676
- gateway = normalizePlatformUrl(values.MLB_GATEWAY_URL);
3677
- } catch {
3678
- throw invalid(".env \u4E2D\u7684 MLB_GATEWAY_URL \u65E0\u6548\uFF1B\u8BF7\u786E\u8BA4\u5E73\u53F0\u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u5F00\u53D1\u4EE4\u724C\u5E76\u66F4\u65B0\u5730\u5740\u3002");
3679
- }
3680
- if (gateway.href !== gatewayUrl.href) throw invalid(".env \u7684\u5E73\u53F0\u5730\u5740\u4E0E\u672C\u6B21\u542F\u52A8\u4E0D\u540C\uFF1B\u8BF7\u786E\u8BA4\u5E73\u53F0\u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u5F00\u53D1\u4EE4\u724C\u3002");
3681
- }
3682
- if (!values.BUDDY_TOKEN.trim() || /[\u0000-\u001f\u007f]/u.test(values.BUDDY_TOKEN)) throw invalid(".env \u4E2D\u7684\u5F00\u53D1\u4EE4\u724C\u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u3002");
3683
- return values.BUDDY_TOKEN;
3684
- }
3685
- function quote(value) {
3686
- if (/[\u0000-\u001f\u007f]/u.test(value)) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26\u3002");
3687
- const delimiter = ["'", '"', "`"].find((character) => !value.includes(character));
3688
- if (!delimiter) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u5305\u542B\u65E0\u6CD5\u5199\u5165 .env \u7684\u5F15\u53F7\u7EC4\u5408\u3002");
3689
- return `${delimiter}${value}${delimiter}`;
3690
- }
3691
- function updateValues(source, values) {
3692
- const assignment = /^[\t ]*(?:export[\t ]+)?([A-Za-z_][A-Za-z0-9_]*)[\t ]*=[\t ]*/gm;
3693
- let output = "", cursor = 0, match;
3694
- const written = /* @__PURE__ */ new Set();
3695
- while (match = assignment.exec(source)) {
3696
- const valueStart = assignment.lastIndex;
3697
- let end = source.indexOf("\n", valueStart);
3698
- if (end < 0) end = source.length;
3699
- let commentStart = valueStart;
3700
- const delimiter = source[valueStart];
3701
- if (delimiter && ["'", '"', "`"].includes(delimiter)) {
3702
- const close = source.indexOf(delimiter, valueStart + 1);
3703
- if (close < 0) throw invalid(".env \u4E2D\u6709\u672A\u95ED\u5408\u7684\u5F15\u53F7\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002");
3704
- commentStart = close + 1;
3705
- end = source.indexOf("\n", close + 1);
3706
- if (end < 0) end = source.length;
3707
- }
3708
- assignment.lastIndex = end;
3709
- const name = match[1];
3710
- if (!(name in values)) continue;
3711
- const comment = source.slice(commentStart, end).match(/[\t ]*#[^\r\n]*/u)?.[0] ?? "";
3712
- output += source.slice(cursor, match.index);
3713
- output += written.has(name) || values[name] === void 0 ? comment : `${name}=${quote(values[name])}${comment ? ` ${comment.trimStart()}` : ""}`;
3714
- if (source[end - 1] === "\r") output += "\r";
3715
- cursor = end;
3716
- written.add(name);
3717
- }
3718
- output += source.slice(cursor);
3719
- const newline = source.includes("\r\n") ? "\r\n" : "\n";
3720
- for (const [name, value] of Object.entries(values)) if (value !== void 0 && !written.has(name)) {
3721
- if (output && !output.endsWith("\n")) output += newline;
3722
- output += `${name}=${quote(value)}${newline}`;
3723
- }
3724
- const parsed = parseEnv(output);
3725
- if (Object.entries(values).some(([name, value]) => parsed[name] !== value)) throw invalid("\u65E0\u6CD5\u5B8C\u6574\u66F4\u65B0 .env\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u683C\u5F0F\u3002");
3726
- return output;
3727
- }
3728
- async function replaceFile2(path, contents, mode) {
3729
- const temporary = `${path}.${randomUUID7()}.tmp`;
3730
- let file;
3731
- try {
3732
- file = await open4(temporary, "wx", mode);
3733
- await file.writeFile(contents, "utf8");
3734
- await file.sync();
3735
- await file.close();
3736
- file = void 0;
3737
- await rename9(temporary, path);
3738
- } finally {
3739
- await file?.close();
3740
- await unlink8(temporary).catch((cause) => {
3741
- if (cause.code !== "ENOENT") throw cause;
3742
- });
3743
- }
3744
- }
3745
- async function writeProjectEnvironment(projectRoot, values) {
3746
- const envPath = join16(projectRoot, ".env"), ignorePath = join16(projectRoot, ".gitignore");
3747
- const contents = updateValues(await readLocalFile(envPath), { ...values, BUDDY_ID: void 0 });
3748
- const ignored = await readLocalFile(ignorePath);
3749
- if (ignored.trimEnd().split(/\r?\n/u).at(-1) !== "/.env") {
3750
- await replaceFile2(ignorePath, `${ignored}${ignored && !ignored.endsWith("\n") ? "\n" : ""}/.env
3751
- `, 420);
3752
- }
3753
- await replaceFile2(envPath, contents, 384);
3754
- return contents;
3755
- }
3756
-
3757
3686
  // packages/cli-core/src/dev/app-server.ts
3758
3687
  var MAX_JSON_BODY_LENGTH = 1048576;
3759
3688
  function safeCredential(value, name) {
@@ -3784,7 +3713,8 @@ async function responseJson(response) {
3784
3713
  throw new BuddyDevError({
3785
3714
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3786
3715
  phase: "registration",
3787
- message: "App Server \u8FD4\u56DE\u7684 JSON \u8FC7\u5927\u3002"
3716
+ message: "App Server \u8FD4\u56DE\u7684 JSON \u8FC7\u5927\u3002",
3717
+ publicMessage: "\u5F00\u53D1\u5E73\u53F0\u8FD4\u56DE\u7684\u6570\u636E\u8D85\u8FC7\u5927\u5C0F\u9650\u5236\uFF0C\u5DF2\u505C\u6B62\u542F\u52A8\uFF1B\u8BF7\u8054\u7CFB\u5E73\u53F0\u7EF4\u62A4\u8005\u3002"
3788
3718
  });
3789
3719
  }
3790
3720
  parts.push(decoder.decode(item.value, { stream: true }));
@@ -3802,6 +3732,7 @@ async function responseJson(response) {
3802
3732
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3803
3733
  phase: "registration",
3804
3734
  message: `App Server \u8FD4\u56DE\u4E86\u65E0\u6548 JSON\uFF08HTTP ${response.status}\uFF09\u3002`,
3735
+ publicMessage: `\u5F00\u53D1\u5E73\u53F0\u8FD4\u56DE\u4E86\u65E0\u6548 JSON\uFF08HTTP ${response.status}\uFF09\uFF1B\u8BF7\u68C0\u67E5\u5E73\u53F0\u5730\u5740\uFF0C\u82E5\u4ECD\u5931\u8D25\u8BF7\u8054\u7CFB\u5E73\u53F0\u7EF4\u62A4\u8005\u3002`,
3805
3736
  cause
3806
3737
  });
3807
3738
  }
@@ -3811,6 +3742,13 @@ function safeServerError(value, fallback) {
3811
3742
  if (typeof candidate !== "string" || !candidate.trim()) return fallback;
3812
3743
  return candidate.slice(0, 1024).replace(/[\u0000-\u001f\u007f]/gu, " ");
3813
3744
  }
3745
+ function httpFailureMessage(status) {
3746
+ if (status === 401) return "\u642D\u642D\u8D26\u53F7\u767B\u5F55\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C buddy-cli login\u3002";
3747
+ if (status === 403) return "\u5F53\u524D\u8D26\u53F7\u65E0\u6743\u8BBF\u95EE\u8FD9\u4E2A\u642D\u5B50\uFF0C\u8BF7\u786E\u8BA4\u767B\u5F55\u8D26\u53F7\u548C\u5DE5\u7A0B\u7684 buddyId\u3002";
3748
+ if (status === 404) return "\u5F53\u524D\u5E73\u53F0\u672A\u627E\u5230\u8FD9\u4E2A\u642D\u5B50\uFF0C\u8BF7\u786E\u8BA4\u5E73\u53F0\u5730\u5740\u548C\u5DE5\u7A0B\u7684 buddyId\u3002";
3749
+ if (status === 429) return "\u5F00\u53D1\u5E73\u53F0\u8BF7\u6C42\u8FC7\u4E8E\u9891\u7E41\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
3750
+ return `\u5F00\u53D1\u5E73\u53F0\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${status}\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\uFF1B\u6301\u7EED\u5931\u8D25\u8BF7\u8054\u7CFB\u5E73\u53F0\u7EF4\u62A4\u8005\u3002`;
3751
+ }
3814
3752
  var MlbDevRegistrationClient = class {
3815
3753
  #baseUrl;
3816
3754
  #developerToken;
@@ -3846,6 +3784,7 @@ var MlbDevRegistrationClient = class {
3846
3784
  code: "DEV_APP_SERVER_HTTP_ERROR",
3847
3785
  phase: "registration",
3848
3786
  message: "\u65E0\u6CD5\u8FDE\u63A5 DEV App Server\u3002",
3787
+ publicMessage: "\u65E0\u6CD5\u8FDE\u63A5\u5F00\u53D1\u5E73\u53F0\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u548C\u672C\u6B21\u8FDE\u63A5\u7684\u5E73\u53F0\u5730\u5740\u3002",
3849
3788
  retryable: true,
3850
3789
  cause
3851
3790
  });
@@ -3856,7 +3795,8 @@ var MlbDevRegistrationClient = class {
3856
3795
  throw new BuddyDevError({
3857
3796
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3858
3797
  phase: "registration",
3859
- message: "DEV App Server \u6210\u529F\u54CD\u5E94\u5FC5\u987B\u4F7F\u7528 application/json\u3002"
3798
+ message: "DEV App Server \u6210\u529F\u54CD\u5E94\u5FC5\u987B\u4F7F\u7528 application/json\u3002",
3799
+ publicMessage: "\u5F00\u53D1\u5E73\u53F0\u8FD4\u56DE\u7684\u5185\u5BB9\u4E0D\u662F JSON\uFF1B\u8BF7\u68C0\u67E5\u5E73\u53F0\u5730\u5740\u662F\u5426\u6B63\u786E\uFF0C\u82E5\u4ECD\u5931\u8D25\u8BF7\u8054\u7CFB\u5E73\u53F0\u7EF4\u62A4\u8005\u3002"
3860
3800
  });
3861
3801
  }
3862
3802
  let body;
@@ -3868,6 +3808,7 @@ var MlbDevRegistrationClient = class {
3868
3808
  code: "DEV_APP_SERVER_HTTP_ERROR",
3869
3809
  phase: "registration",
3870
3810
  message: `DEV App Server \u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${response.status}\uFF09\u3002`,
3811
+ publicMessage: httpFailureMessage(response.status),
3871
3812
  retryable: response.status === 408 || response.status === 429 || response.status >= 500,
3872
3813
  cause
3873
3814
  });
@@ -3879,6 +3820,7 @@ var MlbDevRegistrationClient = class {
3879
3820
  code: "DEV_APP_SERVER_HTTP_ERROR",
3880
3821
  phase: "registration",
3881
3822
  message: safeServerError(body, `DEV App Server \u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${response.status}\uFF09\u3002`),
3823
+ publicMessage: httpFailureMessage(response.status),
3882
3824
  retryable: response.status === 408 || response.status === 429 || response.status >= 500
3883
3825
  });
3884
3826
  }
@@ -3893,7 +3835,7 @@ var MlbDevRegistrationClient = class {
3893
3835
  });
3894
3836
  }
3895
3837
  options.signal.throwIfAborted();
3896
- if (request.projectRoot) await readProjectEnvironment(request.projectRoot);
3838
+ if (request.projectRoot) await checkProjectGateway(request.projectRoot, this.#baseUrl);
3897
3839
  const localToken = request.projectRoot && !this.#refreshToken ? await projectBuddyToken(request.projectRoot, this.#baseUrl) : void 0;
3898
3840
  const store = request.projectRoot ? void 0 : this.#tokenStoreFor?.(request.devAgentId);
3899
3841
  const cached2 = this.#refreshToken ? void 0 : await store?.load();
@@ -3912,7 +3854,8 @@ var MlbDevRegistrationClient = class {
3912
3854
  throw new BuddyDevError({
3913
3855
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3914
3856
  phase: "registration",
3915
- message: "\u642D\u5B50\u8BE6\u60C5\u54CD\u5E94\u7F3A\u5C11\u5339\u914D\u7684 id \u6216 Buddy token\u3002"
3857
+ message: "\u642D\u5B50\u8BE6\u60C5\u54CD\u5E94\u7F3A\u5C11\u5339\u914D\u7684 id \u6216 Buddy token\u3002",
3858
+ publicMessage: "\u5F00\u53D1\u5E73\u53F0\u8FD4\u56DE\u7684\u642D\u5B50\u8EAB\u4EFD\u6216\u51ED\u636E\u4E0D\u5B8C\u6574\uFF0C\u5DF2\u505C\u6B62\u542F\u52A8\uFF1B\u8BF7\u786E\u8BA4\u5E73\u53F0\u548C\u642D\u5B50\u540E\u91CD\u8BD5\u3002"
3916
3859
  });
3917
3860
  }
3918
3861
  const token = safeCredential(body.token, "agentToken");
@@ -3920,7 +3863,8 @@ var MlbDevRegistrationClient = class {
3920
3863
  if (localToken !== void 0 && localToken !== token) throw new BuddyDevError({
3921
3864
  code: "DEV_CONFIG_INVALID",
3922
3865
  phase: "registration",
3923
- message: ".env \u4E2D\u7684\u5F00\u53D1\u4EE4\u724C\u4E0E Server \u8FD4\u56DE\u7684\u5F53\u524D\u642D\u5B50\u4EE4\u724C\u4E0D\u4E00\u81F4\uFF1B\u8BF7\u786E\u8BA4 package.json.buddyId \u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u3002"
3866
+ message: ".env \u4E2D\u7684\u5F00\u53D1\u4EE4\u724C\u4E0E Server \u8FD4\u56DE\u7684\u5F53\u524D\u642D\u5B50\u4EE4\u724C\u4E0D\u4E00\u81F4\uFF1B\u8BF7\u786E\u8BA4 package.json.buddyId \u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u3002",
3867
+ publicMessage: "\u5DE5\u7A0B\u4FDD\u5B58\u7684\u5F00\u53D1\u51ED\u636E\u4E0E\u5F53\u524D\u642D\u5B50\u4E0D\u4E00\u81F4\uFF1B\u8BF7\u786E\u8BA4 package.json.buddyId \u540E\u4F7F\u7528 --refresh-token \u66F4\u65B0\u51ED\u636E\u3002"
3924
3868
  });
3925
3869
  if (!request.projectRoot) await store?.save(token);
3926
3870
  return Object.freeze({
@@ -3938,19 +3882,22 @@ var MlbDevRegistrationClient = class {
3938
3882
  throw new BuddyDevError({
3939
3883
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3940
3884
  phase: "registration",
3941
- message: "DEV \u5728\u7EBF\u5217\u8868\u54CD\u5E94\u7F3A\u5C11 online \u6570\u7EC4\u3002"
3885
+ message: "DEV \u5728\u7EBF\u5217\u8868\u54CD\u5E94\u7F3A\u5C11 online \u6570\u7EC4\u3002",
3886
+ publicMessage: "\u5F00\u53D1\u5E73\u53F0\u7684\u5728\u7EBF\u5217\u8868\u683C\u5F0F\u4E0D\u7B26\u5408\u9884\u671F\uFF08\u7F3A\u5C11 online \u6570\u7EC4\uFF09\uFF1B\u8BF7\u66F4\u65B0 CLI\uFF0C\u82E5\u4ECD\u5931\u8D25\u8BF7\u8054\u7CFB\u5E73\u53F0\u7EF4\u62A4\u8005\u3002"
3942
3887
  });
3943
3888
  }
3944
3889
  const states = body.online.flatMap((item, index) => {
3945
- if (typeof item !== "string" || !item.trim() || item === "-dev") {
3890
+ const id = typeof item === "string" ? item : object2(item)?.id;
3891
+ if (typeof id !== "string" || !id.trim() || id !== id.trim() || /[\u0000-\u001f\u007f]/u.test(id) || id === "-dev") {
3946
3892
  throw new BuddyDevError({
3947
3893
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3948
3894
  phase: "registration",
3949
- message: `DEV \u5728\u7EBF\u5217\u8868\u7B2C ${index + 1} \u9879\u65E0\u6548\u3002`
3895
+ message: `DEV \u5728\u7EBF\u5217\u8868\u7B2C ${index + 1} \u9879\u65E0\u6548\u3002`,
3896
+ publicMessage: `\u5F00\u53D1\u5E73\u53F0\u5728\u7EBF\u5217\u8868\u7B2C ${index + 1} \u9879\u7F3A\u5C11\u6709\u6548\u7684\u642D\u5B50 ID\uFF1B\u8BF7\u66F4\u65B0 CLI\uFF0C\u82E5\u4ECD\u5931\u8D25\u8BF7\u8054\u7CFB\u5E73\u53F0\u7EF4\u62A4\u8005\u3002`
3950
3897
  });
3951
3898
  }
3952
- if (!item.endsWith("-dev")) return [];
3953
- const devAgentId = item.slice(0, -4);
3899
+ if (!id.endsWith("-dev")) return [];
3900
+ const devAgentId = id.slice(0, -4);
3954
3901
  return [Object.freeze({ devAgentId, online: true })];
3955
3902
  });
3956
3903
  return Object.freeze(states);
@@ -4022,23 +3969,24 @@ function buildAgentEnvironment(options) {
4022
3969
 
4023
3970
  // packages/cli-core/src/dev/orchestrator.ts
4024
3971
  import { createHash as createHash7 } from "node:crypto";
4025
- import { readFile as readFile18 } from "node:fs/promises";
4026
- import { join as join19, resolve as resolve12 } from "node:path";
3972
+ import { readFile as readFile17 } from "node:fs/promises";
3973
+ import { join as join18, resolve as resolve12 } from "node:path";
3974
+ import { stripVTControlCharacters } from "node:util";
4027
3975
 
4028
3976
  // packages/cli-core/src/dev/reload.ts
4029
3977
  import { watch } from "node:fs";
4030
3978
  import { createHash as createHash6 } from "node:crypto";
4031
- import { readFile as readFile15, readdir as readdir5 } from "node:fs/promises";
4032
- import { join as join17, resolve as resolve9 } from "node:path";
3979
+ import { readFile as readFile14, readdir as readdir5 } from "node:fs/promises";
3980
+ import { join as join16, resolve as resolve9 } from "node:path";
4033
3981
  import { setTimeout as sleep } from "node:timers/promises";
4034
3982
  var digest2 = (contents) => createHash6("sha256").update(contents).digest("hex");
4035
3983
  async function snapshot(root, prefix = "", result = /* @__PURE__ */ new Map()) {
4036
- for (const entry2 of await readdir5(join17(root, prefix), { withFileTypes: true })) {
3984
+ for (const entry2 of await readdir5(join16(root, prefix), { withFileTypes: true })) {
4037
3985
  const path = prefix ? `${prefix}/${entry2.name}` : entry2.name;
4038
3986
  if (!relevant(path)) continue;
4039
3987
  try {
4040
3988
  if (entry2.isDirectory()) await snapshot(root, path, result);
4041
- else if (entry2.isFile()) result.set(path, digest2(await readFile15(join17(root, path))));
3989
+ else if (entry2.isFile()) result.set(path, digest2(await readFile14(join16(root, path))));
4042
3990
  } catch (cause) {
4043
3991
  if (cause.code !== "ENOENT") throw cause;
4044
3992
  }
@@ -4128,7 +4076,7 @@ var ReloadingDevSession = class {
4128
4076
  const path = String(name);
4129
4077
  if (!relevant(path)) return;
4130
4078
  if (path === ".env") {
4131
- void readFile15(join17(this.projectRoot, path), "utf8").then((contents) => {
4079
+ void readFile14(join16(this.projectRoot, path), "utf8").then((contents) => {
4132
4080
  if (contents !== this.#environment) {
4133
4081
  this.#environment = contents;
4134
4082
  this.#changed();
@@ -4311,7 +4259,7 @@ function startReloadingDev(options, startProcess) {
4311
4259
  }
4312
4260
 
4313
4261
  // packages/cli-core/src/config/runtime-policy.ts
4314
- import { readFile as readFile16, realpath as realpath6 } from "node:fs/promises";
4262
+ import { readFile as readFile15, realpath as realpath6 } from "node:fs/promises";
4315
4263
  import { createRequire as createRequire2 } from "node:module";
4316
4264
  import { resolve as resolve10 } from "node:path";
4317
4265
  var RuntimeRequirementError = class extends Error {
@@ -4339,26 +4287,23 @@ function assertNpmRuntimeLock(contents, expected) {
4339
4287
  }
4340
4288
  }
4341
4289
  async function requireProjectRuntime(root, options = {}) {
4342
- const selected = allowsRuntimeVersionSelection(options);
4343
- const declared = await projectRuntimeVersion(root);
4344
- if (selected && !declared) throw new RuntimeRequirementError("RUNTIME_DEPENDENCY_INVALID", "\u5DE5\u7A0B\u5FC5\u987B\u5728 package.json \u58F0\u660E Runtime \u7684\u51C6\u786E\u7248\u672C\uFF1B\u8BF7\u5148\u9009\u62E9\u7248\u672C\u5E76\u5B89\u88C5\u4F9D\u8D56\u548C\u9501\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528 dev\u3001latest \u6216\u7248\u672C\u8303\u56F4\u4F5C\u4E3A\u5DE5\u7A0B\u4F9D\u8D56\u3002");
4345
4290
  let expected;
4346
4291
  try {
4347
- expected = selected ? await resolveRuntimeVersion(declared, options) : await latestRuntimeVersion(options);
4292
+ expected = await latestRuntimeVersion(options);
4348
4293
  } catch (cause) {
4349
4294
  options.signal?.throwIfAborted();
4350
- throw new RuntimeRequirementError("RUNTIME_CHECK_FAILED", `\u65E0\u6CD5\u786E\u8BA4 npm ${selected ? `\u5DE5\u7A0B\u9009\u5B9A\u7684 Runtime ${declared}` : "\u6700\u65B0 Runtime"}\uFF0C\u5DF2\u963B\u6B62\u8FD0\u884C\u6216\u4E0A\u4F20\uFF1A${cause instanceof Error ? cause.message : String(cause)}\u3002\u8BF7\u6062\u590D\u8FDE\u63A5\u540E\u91CD\u8BD5\u3002`, { cause });
4295
+ throw new RuntimeRequirementError("RUNTIME_CHECK_FAILED", `\u65E0\u6CD5\u786E\u8BA4 npm \u6700\u65B0\u6B63\u5F0F\u7248 Runtime\uFF0C\u5DF2\u963B\u6B62\u8FD0\u884C\u6216\u4E0A\u4F20\uFF1A${cause instanceof Error ? cause.message : String(cause)}\u3002\u8BF7\u6062\u590D\u8FDE\u63A5\u540E\u91CD\u8BD5\u3002`, { cause });
4351
4296
  }
4352
4297
  try {
4353
4298
  assertRequiredRuntime(await projectRuntimeVersion(root), expected);
4354
4299
  const installedPath = await realpath6(resolve10(root, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"));
4355
4300
  const fromProject = createRequire2(resolve10(root, "package.json")).resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`);
4356
4301
  if (await realpath6(fromProject) !== installedPath) throw new Error("Runtime \u5FC5\u987B\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D");
4357
- const installed2 = JSON.parse(await readFile16(installedPath, "utf8"));
4302
+ const installed2 = JSON.parse(await readFile15(installedPath, "utf8"));
4358
4303
  if (installed2.version !== expected) throw new Error(`Runtime \u5B9E\u9645\u5B89\u88C5 ${installed2.version}\uFF0C\u8981\u6C42 ${expected}`);
4359
4304
  let lock;
4360
4305
  try {
4361
- lock = await readFile16(resolve10(root, "package-lock.json"), "utf8");
4306
+ lock = await readFile15(resolve10(root, "package-lock.json"), "utf8");
4362
4307
  } catch (cause) {
4363
4308
  if (cause.code !== "ENOENT") throw cause;
4364
4309
  }
@@ -4378,8 +4323,8 @@ import { createRequire as createRequire3 } from "node:module";
4378
4323
  import { dirname as dirname4, resolve as resolve11 } from "node:path";
4379
4324
 
4380
4325
  // packages/cli-core/src/config/data-access.ts
4381
- import { lstat as lstat10, readFile as readFile17 } from "node:fs/promises";
4382
- import { join as join18 } from "node:path";
4326
+ import { lstat as lstat10, readFile as readFile16 } from "node:fs/promises";
4327
+ import { join as join17 } from "node:path";
4383
4328
  var DATA_ACCESS_FILENAME = "data-access.json";
4384
4329
  function parseDataAccessRequirements(source) {
4385
4330
  if (source === void 0) return [];
@@ -4407,10 +4352,10 @@ function parseDataAccessRequirements(source) {
4407
4352
  });
4408
4353
  }
4409
4354
  async function readDataAccessRequirements(projectRoot) {
4410
- const path = join18(projectRoot, DATA_ACCESS_FILENAME);
4355
+ const path = join17(projectRoot, DATA_ACCESS_FILENAME);
4411
4356
  try {
4412
4357
  if (!(await lstat10(path)).isFile()) throw new Error(`${DATA_ACCESS_FILENAME} \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6`);
4413
- return parseDataAccessRequirements(await readFile17(path, "utf8"));
4358
+ return parseDataAccessRequirements(await readFile16(path, "utf8"));
4414
4359
  } catch (cause) {
4415
4360
  if (cause.code === "ENOENT") return [];
4416
4361
  throw cause;
@@ -4566,6 +4511,7 @@ async function waitForAgentOnline(options) {
4566
4511
  code: "DEV_AGENT_ONLINE_TIMEOUT",
4567
4512
  phase: "online",
4568
4513
  message: `Runtime ${options.devAgentId} \u5728 ${options.timeoutMs}ms \u5185\u6CA1\u6709\u8FDE\u63A5 DEV App Server\u3002`,
4514
+ publicMessage: "Runtime \u672A\u5728\u7B49\u5F85\u65F6\u95F4\u5185\u8FDE\u63A5\u5F00\u53D1\u5E73\u53F0\uFF1B\u8BF7\u68C0\u67E5\u8FD0\u884C\u65E5\u5FD7\u3001\u7F51\u7EDC\u548C\u5DE5\u7A0B\u7684\u542F\u52A8\u547D\u4EE4\u540E\u91CD\u8BD5\u3002",
4569
4515
  retryable: true,
4570
4516
  ...lastError === void 0 ? {} : { cause: lastError }
4571
4517
  });
@@ -4584,12 +4530,13 @@ async function waitForAgentOnline(options) {
4584
4530
  await delay2(Math.min(options.pollIntervalMs, Math.max(1, deadline - Date.now())), options.signal);
4585
4531
  }
4586
4532
  }
4587
- function agentExitedError(exit, stderr = "") {
4533
+ function agentExitedError(exit, diagnostics = "") {
4588
4534
  const detail = exit.error !== void 0 ? exit.error.message : exit.signal !== null ? `signal ${exit.signal}` : `exit code ${exit.code ?? "unknown"}`;
4589
4535
  return new BuddyDevError({
4590
4536
  code: "DEV_AGENT_EXITED",
4591
4537
  phase: "running",
4592
- message: `Buddy Runtime \u8FDB\u7A0B\u5728 DEV \u4F1A\u8BDD\u671F\u95F4\u9000\u51FA\uFF08${detail}\uFF09\u3002${stderr ? ` ${stderr}` : ""}`,
4538
+ message: `Buddy Runtime \u8FDB\u7A0B\u5728 DEV \u4F1A\u8BDD\u671F\u95F4\u9000\u51FA\uFF08${detail}\uFF09\u3002${diagnostics ? ` ${diagnostics}` : ""}`,
4539
+ publicMessage: `Runtime \u8FDB\u7A0B\u5DF2\u9000\u51FA${exit.error ? "" : `\uFF08${detail}\uFF09`}\u3002${diagnostics || "\u8BF7\u68C0\u67E5\u8FD0\u884C\u65E5\u5FD7\u3001\u542F\u52A8\u547D\u4EE4\u548C\u5DE5\u7A0B\u4F9D\u8D56\u540E\u91CD\u8BD5\u3002"}`.slice(0, 512),
4593
4540
  ...exit.error === void 0 ? {} : { cause: exit.error }
4594
4541
  });
4595
4542
  }
@@ -4605,6 +4552,7 @@ var ReadyBuddyDevHandle = class {
4605
4552
  #lifecycle;
4606
4553
  #stopGracePeriodMs;
4607
4554
  #onStateChange;
4555
+ #failureDetail;
4608
4556
  #signal;
4609
4557
  #onAbort;
4610
4558
  #state = "ready";
@@ -4622,6 +4570,7 @@ var ReadyBuddyDevHandle = class {
4622
4570
  this.#stopGracePeriodMs = options.stopGracePeriodMs;
4623
4571
  this.#signal = options.signal;
4624
4572
  this.#onStateChange = options.onStateChange;
4573
+ this.#failureDetail = options.failureDetail;
4625
4574
  this.#onAbort = () => {
4626
4575
  void this.stop().catch(() => void 0);
4627
4576
  };
@@ -4632,7 +4581,7 @@ var ReadyBuddyDevHandle = class {
4632
4581
  else options.signal?.addEventListener("abort", this.#onAbort, { once: true });
4633
4582
  this.#emit("ready");
4634
4583
  void this.#process.exit.then(async (exit) => {
4635
- if (this.#state === "ready") await this.#fail(agentExitedError(exit));
4584
+ if (this.#state === "ready") await this.#fail(agentExitedError(exit, this.#failureDetail()));
4636
4585
  });
4637
4586
  }
4638
4587
  get state() {
@@ -4714,12 +4663,35 @@ async function startBuddyDevProcess(options, hooks) {
4714
4663
  let agentProcess;
4715
4664
  let processTree;
4716
4665
  let instanceLock;
4717
- let stderr = "";
4666
+ const output = { stdout: "", stderr: "" };
4667
+ const truncated = { stdout: false, stderr: false };
4718
4668
  let secrets = [];
4669
+ const capture2 = (source, text2) => {
4670
+ const next = output[source] + text2;
4671
+ truncated[source] ||= next.length > 16384;
4672
+ output[source] = next.slice(-16384);
4673
+ options.onLog?.({ source: `agent.${source}`, text: text2 });
4674
+ };
4719
4675
  const failureDetail = () => {
4720
- let text2 = stderr;
4721
- for (const secret of secrets) if (secret) text2 = text2.split(secret).join("[REDACTED]");
4722
- return (text2.split("\n").find((line) => /(?:Error|错误|失败):/u.test(line)) ?? text2.trim().split("\n").slice(-3).join(" ")).replace(/[\u0000-\u001f\u007f]/gu, " ").slice(0, 400);
4676
+ const clean = (source) => {
4677
+ let text2 = stripVTControlCharacters(truncated[source] ? output[source].replace(/^[^\n]*(?:\n|$)/u, "") : output[source]);
4678
+ for (const secret of secrets) if (secret) text2 = text2.split(secret).join("[REDACTED]");
4679
+ return text2.replace(/https?:\/\/[^\s<>"']+/giu, (value) => {
4680
+ try {
4681
+ const url = new URL(value);
4682
+ url.username = "";
4683
+ url.password = "";
4684
+ url.search = "";
4685
+ url.hash = "";
4686
+ return url.href;
4687
+ } catch {
4688
+ return "[URL]";
4689
+ }
4690
+ }).replace(/\bBearer\s+\S+/giu, "Bearer [REDACTED]").replace(/\b(?:[\w-]*(?:token|secret|password|api[_-]?key)|authorization)["']?\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,"'}]+)/giu, "[REDACTED]");
4691
+ };
4692
+ const stderr = clean("stderr"), stdout = clean("stdout");
4693
+ const errorLine = (text2) => text2.split("\n").reverse().find((line) => /(?:\b\w*Error\b|错误|失败)/iu.test(line));
4694
+ return (errorLine(stderr) ?? errorLine(stdout) ?? stderr.trim().split("\n").slice(-3).join(" ")).replace(/[\u0000-\u001f\u007f]/gu, " ").slice(0, 400);
4723
4695
  };
4724
4696
  const emit = (state2) => {
4725
4697
  try {
@@ -4733,7 +4705,7 @@ async function startBuddyDevProcess(options, hooks) {
4733
4705
  let config;
4734
4706
  let configSource;
4735
4707
  try {
4736
- configSource = await readFile18(join19(projectRoot, BUDDY_PACKAGE_FILENAME), "utf8");
4708
+ configSource = await readFile17(join18(projectRoot, BUDDY_PACKAGE_FILENAME), "utf8");
4737
4709
  config = combineBuddyProject(parseBuddyAgentConfig(configSource));
4738
4710
  } catch (cause) {
4739
4711
  throw new BuddyDevError({
@@ -4745,7 +4717,7 @@ async function startBuddyDevProcess(options, hooks) {
4745
4717
  }
4746
4718
  if (config.buddyId !== devAgentId) throw new BuddyDevError({ code: "DEV_CONFIG_INVALID", phase: "config", message: "\u5DE5\u7A0B buddyId \u5DF2\u6539\u53D8\uFF0C\u8BF7\u505C\u6B62 DEV \u540E\u5728\u6B63\u786E\u642D\u5B50\u7684\u5DE5\u7A0B\u91CD\u65B0\u8FDE\u63A5\u3002" });
4747
4719
  const projectEnv = await readProjectEnvironment(projectRoot);
4748
- secrets = Object.entries(projectEnv).filter(([key]) => /token|secret|password|key/i.test(key)).map(([, value]) => value ?? "");
4720
+ secrets = [...Object.entries(projectEnv), ...Object.entries(options.parentEnv ?? process.env)].filter(([key]) => /token|secret|password|key/i.test(key)).map(([, value]) => value ?? "");
4749
4721
  const launchPlan = await launchPlanFor(config, options, projectRoot, signal);
4750
4722
  const registration = await registerDevAgent({
4751
4723
  projectRoot,
@@ -4786,11 +4758,8 @@ async function startBuddyDevProcess(options, hooks) {
4786
4758
  env: childEnvironment,
4787
4759
  shell: false,
4788
4760
  detached: platform === "darwin",
4789
- onStdout: (text2) => options.onLog?.({ source: "agent.stdout", text: text2 }),
4790
- onStderr: (text2) => {
4791
- stderr = (stderr + text2).slice(-16384);
4792
- options.onLog?.({ source: "agent.stderr", text: text2 });
4793
- }
4761
+ onStdout: (text2) => capture2("stdout", text2),
4762
+ onStderr: (text2) => capture2("stderr", text2)
4794
4763
  });
4795
4764
  await instanceLock.attachRuntime(agentProcess.pid);
4796
4765
  const exited = agentProcess.exit.then((exit) => {
@@ -4817,6 +4786,7 @@ async function startBuddyDevProcess(options, hooks) {
4817
4786
  instanceLock,
4818
4787
  lifecycle,
4819
4788
  stopGracePeriodMs,
4789
+ failureDetail,
4820
4790
  ...options.signal === void 0 ? {} : { signal: options.signal },
4821
4791
  ...options.onStateChange === void 0 ? {} : { onStateChange: options.onStateChange }
4822
4792
  });
@@ -5062,11 +5032,12 @@ var DEV_COMMAND_HELP = `\u7528\u6CD5:
5062
5032
  dev stop \u505C\u6B62\u5F53\u524D\u5DE5\u7A0B\u7684 DEV \u53CA\u6587\u4EF6\u76D1\u542C\uFF0C\u6E05\u7406\u5DF2\u786E\u8BA4\u9000\u51FA\u7684\u6B8B\u7559\u8FDB\u7A0B\uFF1B\u4E0D\u91CD\u8FDE\u3001\u4E0D\u91CD\u542F\uFF0C\u65E0\u9700\u767B\u5F55\u6216\u8054\u7F51\u66F4\u65B0\u3002
5063
5033
  \u5173\u95ED\u7EC8\u7AEF\u3001Ctrl+C \u6216 SIGTERM \u4F1A\u505C\u6B62 CLI \u6258\u7BA1\u7684 Runtime\uFF1B\u5F3A\u5236\u6740\u6B7B CLI \u540E\u53EF\u7528 dev stop \u6E05\u7406\u3002
5064
5034
  \u672A\u914D\u7F6E\u5730\u5740\u65F6\u8FDE\u63A5 MLB \u6D4B\u8BD5\u73AF\u5883 ${DEFAULT_MLB_TEST_URL}\uFF08HTTPS\uFF09\u3002
5065
- MLB_GATEWAY_URL \u7EDF\u4E00\u9009\u62E9\u5E73\u53F0\uFF0C--app-server \u53EF\u8986\u76D6\u672C\u6B21\u547D\u4EE4\uFF1BCLI \u81EA\u52A8\u4E3A Runtime \u5199\u5165\u5BF9\u5E94\u7F51\u5173\u5730\u5740\u3002
5035
+ \u6B63\u5F0F\u7248\u56FA\u5B9A\u8FDE\u63A5 ECS Test\uFF1B\u5730\u5740\u53C2\u6570\u53EA\u6821\u9A8C\u56FA\u5B9A\u76EE\u6807\uFF0C\u4E0D\u80FD\u5207\u6362\u5E73\u53F0\u3002Runtime \u7F51\u5173\u7531 CLI \u6CE8\u5165\u3002
5036
+ \u542F\u52A8\u524D\u81EA\u68C0 .env \u7F51\u5173\uFF1B\u5DF2\u77E5\u65E7 ECS \u5730\u5740\u6821\u9A8C\u642D\u5B50\u5F52\u5C5E\u540E\u81EA\u52A8\u66F4\u65B0\uFF0C\u4E0D\u540C\u5E73\u53F0\u4ECD\u9700\u660E\u786E\u786E\u8BA4\u3002
5066
5037
  CLI \u7EDF\u4E00\u542F\u52A8\u5E76\u7BA1\u7406\u5DE5\u7A0B\u4E2D\u7684\u5B98\u65B9 Runtime\uFF1B\u6BCF\u6B21\u542F\u52A8\u6216\u91CD\u8F7D\u5FC5\u987B\u901A\u8FC7 npm \u6700\u65B0\u7A33\u5B9A\u7248\u68C0\u67E5\u3002
5067
5038
  DEV \u4F1A\u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u5F00\u53D1\u8005\u4F1A\u8BDD\uFF0C\u5C06\u5F53\u524D\u642D\u5B50\u7684\u5F00\u53D1 Token \u5199\u5165\u5DE5\u7A0B .env\uFF0C\u590D\u7528\u524D\u5411 Server \u6838\u5BF9\u6240\u5C5E\u642D\u5B50\uFF1B\u767B\u5F55\u51ED\u636E\u4ECD\u4F7F\u7528\u7CFB\u7EDF\u51ED\u636E\u5B58\u50A8\u3002
5068
5039
  \u8EAB\u4EFD\u53EA\u8BFB\u53D6 package.json.buddyId\uFF0C.env \u4E0D\u9700\u8981 BUDDY_ID\u3002
5069
- --refresh-token \u91CD\u65B0\u9886\u53D6\u5DF2\u6709\u5F00\u53D1 Token\uFF0C\u7528\u4E8E\u670D\u52A1\u7AEF\u91CD\u7F6E\u540E\u7684\u672C\u673A\u66F4\u65B0\uFF1B\u4E0D\u4F1A\u751F\u6210\u65B0\u5BC6\u94A5\u3002`;
5040
+ --refresh-token \u91CD\u65B0\u9886\u53D6\u5DF2\u6709\u5F00\u53D1 Token\uFF0C\u7528\u4E8E\u540C\u4E00\u73AF\u5883\u670D\u52A1\u7AEF\u91CD\u7F6E\u540E\u7684\u672C\u673A\u66F4\u65B0\uFF1B\u4E0D\u80FD\u5207\u6362\u5E73\u53F0\uFF0C\u4E0D\u4F1A\u751F\u6210\u65B0\u5BC6\u94A5\u3002`;
5070
5041
  function valueAfter(args, index, flag2) {
5071
5042
  const value = args[index + 1];
5072
5043
  if (value === void 0 || !value.trim()) throw new DevCommandUsageError(`${flag2} \u7F3A\u5C11\u503C`);
@@ -5121,7 +5092,7 @@ function parseDevArguments(args) {
5121
5092
  }
5122
5093
  function appServerUrl(override, env) {
5123
5094
  try {
5124
- return resolvePlatformUrl({ override, env, development: true });
5095
+ return resolvePlatformUrl({ override, env });
5125
5096
  } catch (cause) {
5126
5097
  throw new DevCommandUsageError(`App Server \u5730\u5740\u65E0\u6548\uFF1A${cause instanceof Error ? cause.message : "\u4E0D\u662F\u6709\u6548 URL"}`);
5127
5098
  }
@@ -5158,6 +5129,7 @@ async function runDevCommand(args, io, options = {}) {
5158
5129
  io.write(result.stopped ? "DEV \u5DF2\u505C\u6B62\uFF0C\u6B8B\u7559\u8FDB\u7A0B\u53CA\u8FDB\u7A0B\u9501\u5DF2\u6E05\u7406\u3002\u9700\u8981\u8C03\u8BD5\u65F6\u91CD\u65B0\u8FDE\u63A5\u5E76\u542F\u52A8 DEV\u3002" : "\u5F53\u524D\u5DE5\u7A0B\u6CA1\u6709 CLI \u6258\u7BA1\u7684\u672C\u5730 DEV \u8FDB\u7A0B\u3002\u5176\u4ED6\u7535\u8111\u4E0A\u7684\u670D\u52A1\u8BF7\u5728\u5BF9\u5E94\u7535\u8111\u505C\u6B62\u3002");
5159
5130
  return { exitCode: 0 };
5160
5131
  }
5132
+ await checkProjectGateway(root, url, { report: (message) => io.write(message) });
5161
5133
  const authorizationInput = { appServerUrl: url, ...parsed.refreshToken ? { refreshToken: true } : {} };
5162
5134
  if (!options.authorize) {
5163
5135
  throw new DevCommandUsageError("\u5F53\u524D CLI Host \u5C1A\u672A\u914D\u7F6E\u642D\u642D\u8D26\u53F7\u767B\u5F55 Adapter");
@@ -5169,7 +5141,7 @@ async function runDevCommand(args, io, options = {}) {
5169
5141
  startDev: options.startDev ?? startBuddyDev
5170
5142
  });
5171
5143
  const handle = await starter.start({
5172
- runtimeUpdate: { ...options.runtimeUpdate, env: environment, platformUrl: url },
5144
+ runtimeUpdate: { ...options.runtimeUpdate, env: environment },
5173
5145
  projectRoot: root,
5174
5146
  registrationClient,
5175
5147
  ...options.signal === void 0 ? {} : { signal: options.signal },
@@ -5917,6 +5889,7 @@ async function runLogout(io, options) {
5917
5889
  }
5918
5890
  async function runPush(parsed, io, options) {
5919
5891
  const root = await (options.resolveProjectRoot ?? requireBuddyAgentProjectRoot)(requestedDirectory(options, parsed));
5892
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
5920
5893
  const config = await (options.readConfig ?? readBuddyConfig)(root);
5921
5894
  const commit = await pushCommit(parsed, io);
5922
5895
  if (!config.buddyId) throw new CloudCommandUsageError("\u5F53\u524D\u9879\u76EE\u7F3A\u5C11\u5E73\u53F0\u751F\u6210\u7684 buddyId\uFF0C\u8BF7\u5148\u8FD0\u884C buddy-cli init");
@@ -5982,6 +5955,7 @@ async function runMeta(parsed, io, options, legacyAvatar = false) {
5982
5955
  if (id !== void 0 && !/^[A-Za-z0-9_-]{1,128}$/u.test(id)) throw new CloudCommandUsageError("--buddy-id \u5FC5\u987B\u662F\u6709\u6548\u7684\u642D\u5B50 ID");
5983
5956
  if (id === void 0) {
5984
5957
  const root = await (options.resolveProjectRoot ?? requireBuddyProjectRoot)(requestedDirectory(options, parsed));
5958
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
5985
5959
  id = (await (options.readManifest ?? readBuddyProjectManifest)(root)).buddyId;
5986
5960
  }
5987
5961
  if (options.mode === "local-mock") throw new CloudCommandUsageError("\u672C\u5730\u6A21\u62DF\u6A21\u5F0F\u4E0D\u63D0\u4F9B\u4E91\u7AEF\u8D44\u6599\u64CD\u4F5C\uFF0C\u8BF7\u8FDE\u63A5\u771F\u5B9E MLB Server");
@@ -6031,6 +6005,7 @@ async function runCloudCommand(command, args, io, options = {}) {
6031
6005
  if (command === "push") return await runPush(parsed, io, options);
6032
6006
  if (command === "meta" || command === "avatar") return await runMeta(parsed, io, options, command === "avatar");
6033
6007
  const root = await (options.resolveProjectRoot ?? requireBuddyProjectRoot)(requestedDirectory(options, parsed));
6008
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
6034
6009
  const manifest = await (options.readManifest ?? readBuddyProjectManifest)(root);
6035
6010
  if (options.mode === "local-mock") {
6036
6011
  throw new CloudCommandUsageError("\u672C\u5730\u6A21\u62DF\u6A21\u5F0F\u53EA\u7528\u4E8E\u4F53\u9A8C\u521D\u59CB\u5316\u6D41\u7A0B\uFF0C\u4E0D\u63D0\u4F9B\u865A\u5047\u7684\u4E91\u7AEF\u72B6\u6001");
@@ -6044,7 +6019,7 @@ async function runCloudCommand(command, args, io, options = {}) {
6044
6019
  printStatus(io, buddy2, packages);
6045
6020
  return { exitCode: 0, buddyId: buddy2.id };
6046
6021
  } catch (cause) {
6047
- if (cause instanceof CloudCommandUsageError || cause instanceof CloudLifecycleError || cause instanceof BuddyProjectContextError || cause instanceof RuntimeRequirementError || cause instanceof PushPreflightError) {
6022
+ if (cause instanceof BuddyDevError || cause instanceof CloudCommandUsageError || cause instanceof CloudLifecycleError || cause instanceof BuddyProjectContextError || cause instanceof RuntimeRequirementError || cause instanceof PushPreflightError) {
6048
6023
  io.writeError(`buddy-cli: ${cause.message}`);
6049
6024
  if (cause instanceof CloudLifecycleError || cause instanceof RuntimeRequirementError || cause instanceof PushPreflightError) io.writeError(`\u9519\u8BEF\u7801\uFF1A${cause.code}`);
6050
6025
  return {
@@ -6058,7 +6033,7 @@ var CLOUD_COMMAND_HELP = HELP;
6058
6033
 
6059
6034
  // packages/cli-core/src/migration/index.ts
6060
6035
  import { lstat as lstat11, open as open5, readdir as readdir6, realpath as realpath7, stat } from "node:fs/promises";
6061
- import { extname, isAbsolute as isAbsolute3, join as join20, relative, resolve as resolve16, sep, win32 as win322 } from "node:path";
6036
+ import { extname, isAbsolute as isAbsolute3, join as join19, relative, resolve as resolve16, sep, win32 as win322 } from "node:path";
6062
6037
  var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
6063
6038
  maxFiles: 128,
6064
6039
  maxFileBytes: 256 * 1024,
@@ -6227,7 +6202,7 @@ async function existingProjectRoot(value) {
6227
6202
  }
6228
6203
  }
6229
6204
  async function existingSkillRoot(projectRoot, skillPath) {
6230
- const candidate = skillPath === "." ? projectRoot : join20(projectRoot, ...skillPath.split("/"));
6205
+ const candidate = skillPath === "." ? projectRoot : join19(projectRoot, ...skillPath.split("/"));
6231
6206
  try {
6232
6207
  await lstat11(candidate);
6233
6208
  } catch (cause) {
@@ -6264,7 +6239,7 @@ async function existingSkillRoot(projectRoot, skillPath) {
6264
6239
  }
6265
6240
  async function assertEntrypoint(context) {
6266
6241
  const entryPath = reportChild(context.skillPath, "SKILL.md");
6267
- const candidate = join20(context.skillRoot, "SKILL.md");
6242
+ const candidate = join19(context.skillRoot, "SKILL.md");
6268
6243
  try {
6269
6244
  await lstat11(candidate);
6270
6245
  const target = await realpath7(candidate);
@@ -6368,7 +6343,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
6368
6343
  }
6369
6344
  for (const entry2 of entries) {
6370
6345
  const childReportPath = reportChild(reportDirectory, entry2.name);
6371
- const childPath = join20(directory, entry2.name);
6346
+ const childPath = join19(directory, entry2.name);
6372
6347
  let target;
6373
6348
  try {
6374
6349
  target = await realpath7(childPath);
@@ -6824,7 +6799,7 @@ async function scanExternalSkillPortability(options) {
6824
6799
  // packages/cli-core/src/push/preflight.ts
6825
6800
  import { createHash as createHash10 } from "node:crypto";
6826
6801
  import { lstat as lstat12, open as open6, readdir as readdir7, realpath as realpath8 } from "node:fs/promises";
6827
- import { isAbsolute as isAbsolute4, join as join21, relative as relative2, resolve as resolve17, sep as sep2, win32 as win323 } from "node:path";
6802
+ import { isAbsolute as isAbsolute4, join as join20, relative as relative2, resolve as resolve17, sep as sep2, win32 as win323 } from "node:path";
6828
6803
  var MEBIBYTE = 1024 * 1024;
6829
6804
  var DEFAULT_PUSH_MANIFEST_LIMITS = Object.freeze({
6830
6805
  maxFiles: 1e4,
@@ -7029,7 +7004,7 @@ async function canonicalProjectRoot(projectRoot) {
7029
7004
  }
7030
7005
  }
7031
7006
  async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
7032
- const path = join21(projectRoot, filename);
7007
+ const path = join20(projectRoot, filename);
7033
7008
  let entry2;
7034
7009
  try {
7035
7010
  entry2 = await lstat12(path);
@@ -7232,7 +7207,7 @@ async function createManifest(options) {
7232
7207
  sensitiveEntriesExcluded += 1;
7233
7208
  continue;
7234
7209
  }
7235
- const absolutePath = join21(directory, name);
7210
+ const absolutePath = join20(directory, name);
7236
7211
  let entry2;
7237
7212
  try {
7238
7213
  entry2 = await lstat12(absolutePath);
@@ -7486,7 +7461,7 @@ async function assertCapturedConfigStable(options) {
7486
7461
  }
7487
7462
  let current;
7488
7463
  try {
7489
- const path = join21(options.projectRoot, options.filename);
7464
+ const path = join20(options.projectRoot, options.filename);
7490
7465
  const entry2 = await lstat12(path);
7491
7466
  if (!entry2.isFile() || entry2.isSymbolicLink()) {
7492
7467
  error({
@@ -7532,7 +7507,7 @@ async function createPushPreflight(options) {
7532
7507
  parseCapturedProject(initialAgentEntry);
7533
7508
  let initialDataEntry;
7534
7509
  try {
7535
- await lstat12(join21(projectRoot, DATA_ACCESS_FILENAME));
7510
+ await lstat12(join20(projectRoot, DATA_ACCESS_FILENAME));
7536
7511
  initialDataEntry = await captureConfigWithinLimit(projectRoot, limits.maxFileBytes, DATA_ACCESS_FILENAME);
7537
7512
  } catch (cause) {
7538
7513
  if (cause.code !== "ENOENT") throw cause;
@@ -7634,8 +7609,8 @@ async function createPushPreflight(options) {
7634
7609
 
7635
7610
  // packages/cli-core/src/push/bundle.ts
7636
7611
  import { createHash as createHash11 } from "node:crypto";
7637
- import { lstat as lstat13, readFile as readFile19, realpath as realpath9 } from "node:fs/promises";
7638
- import { join as join22, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
7612
+ import { lstat as lstat13, readFile as readFile18, realpath as realpath9 } from "node:fs/promises";
7613
+ import { join as join21, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
7639
7614
  import { Writable } from "node:stream";
7640
7615
  import { pipeline } from "node:stream/promises";
7641
7616
  import { createGzip } from "node:zlib";
@@ -7657,7 +7632,7 @@ function inside(root, target) {
7657
7632
  return path === "" || path !== ".." && !path.startsWith(`..${sep3}`) && !path.startsWith("/") && !win324.isAbsolute(path);
7658
7633
  }
7659
7634
  async function capture(root, file) {
7660
- const absolute = join22(root, ...file.path.split("/"));
7635
+ const absolute = join21(root, ...file.path.split("/"));
7661
7636
  try {
7662
7637
  const entry2 = await lstat13(absolute);
7663
7638
  if (!entry2.isFile() || entry2.isSymbolicLink() || entry2.size !== file.bytes) {
@@ -7665,7 +7640,7 @@ async function capture(root, file) {
7665
7640
  }
7666
7641
  const canonical = await realpath9(absolute);
7667
7642
  if (!inside(root, canonical)) changed(file.path, `\u63D0\u4EA4\u6587\u4EF6\u8D8A\u8FC7\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${file.path}`);
7668
- const contents = await readFile19(absolute);
7643
+ const contents = await readFile18(absolute);
7669
7644
  if (contents.byteLength !== file.bytes || digest3(contents) !== file.digest) {
7670
7645
  changed(file.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u5185\u5BB9\u53D1\u751F\u53D8\u5316\uFF1A${file.path}`);
7671
7646
  }
@@ -7783,6 +7758,7 @@ function validateRecoverableBuddyId(value) {
7783
7758
  return buddyId;
7784
7759
  }
7785
7760
  async function resolveApplicationDraft(name, tagline, intro, requestedBuddyId, options, root, args, io) {
7761
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
7786
7762
  const register = () => (options.registerMeta ?? prepareAndRegisterMeta)({
7787
7763
  root,
7788
7764
  profile: { name, tagline, intro },
@@ -7876,9 +7852,6 @@ function parseInitArguments(args) {
7876
7852
  if (!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u.test(value)) throw new CliUsageError("--creator-version \u5FC5\u987B\u662F\u51C6\u786E\u7248\u672C\uFF0C\u4F8B\u5982 1.6.0");
7877
7853
  parsed.creatorVersion = setOnce2(parsed.creatorVersion, value, flag2);
7878
7854
  break;
7879
- case "--runtime-version":
7880
- parsed.runtimeVersion = setOnce2(parsed.runtimeVersion, value, flag2);
7881
- break;
7882
7855
  case "--avatar":
7883
7856
  parsed.avatar = setOnce2(parsed.avatar, value, flag2);
7884
7857
  break;
@@ -7967,7 +7940,6 @@ async function initializeProjectRoute(route, args, io, options, application) {
7967
7940
  const initializationTarget = { directory: rootDirectory, kind: "new" };
7968
7941
  let initializationPlan = options.initializeProject ? void 0 : await planBuddyProjectInitialization(initializationTarget);
7969
7942
  const existingBuddyId = initializationPlan?.existingManifest?.buddyId;
7970
- const runtimeVersion = args.resolvedRuntimeVersion ?? await selectInitRuntime(rootDirectory, args.runtimeVersion, io, options.runtimeCatalog);
7971
7943
  if (existingBuddyId !== void 0 && args.buddyId !== void 0 && existingBuddyId !== args.buddyId) {
7972
7944
  throw new CliUsageError(
7973
7945
  `\u5DF2\u6709 package.json \u7ED1\u5B9A\u7684\u662F ${existingBuddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
@@ -7990,9 +7962,9 @@ async function initializeProjectRoute(route, args, io, options, application) {
7990
7962
  }
7991
7963
  let platformTemplate;
7992
7964
  try {
7993
- platformTemplate = options.scaffoldPlatformAgent ? await options.scaffoldPlatformAgent(project.rootDirectory, name, runtimeVersion) : await scaffoldPlatformAgent(project.rootDirectory, name, runtimeVersion ? {
7994
- resolveDependencies: (template) => latestRuntimeTemplate(template, { ...options.runtimeCatalog, runtimeVersion, report: (message) => io.writeError(message) })
7995
- } : void 0);
7965
+ platformTemplate = options.scaffoldPlatformAgent ? await options.scaffoldPlatformAgent(project.rootDirectory, name) : await scaffoldPlatformAgent(project.rootDirectory, name, {
7966
+ resolveDependencies: (template) => latestRuntimeTemplate(template, { ...options.runtimeCatalog, report: (message) => io.writeError(message) })
7967
+ });
7996
7968
  } catch (cause) {
7997
7969
  const detail = cause instanceof Error ? cause.message : String(cause);
7998
7970
  io.writeError(`\u5B98\u65B9 Runtime \u5DE5\u7A0B\u5C1A\u672A\u5B8C\u6210\uFF1A${detail}\u3002\u642D\u5B50\u8EAB\u4EFD ${buddyId} \u5DF2\u4FDD\u7559\uFF1B\u4FEE\u590D\u539F\u56E0\u540E\uFF0C\u5728\u540C\u76EE\u5F55\u8FD0\u884C buddy-cli init --mode direct \u91CD\u8BD5\uFF0C\u5DF2\u6709\u914D\u7F6E\u548C\u4E1A\u52A1\u6587\u4EF6\u4F1A\u4FDD\u7559\u3002`);
@@ -8075,7 +8047,7 @@ async function resumeProjectArguments(args, cwd, options, io) {
8075
8047
  await assertInitializableBuddyTarget(root);
8076
8048
  let entry2;
8077
8049
  try {
8078
- entry2 = await lstat14(join23(root, "package.json"));
8050
+ entry2 = await lstat14(join22(root, "package.json"));
8079
8051
  } catch (cause) {
8080
8052
  if (cause.code === "ENOENT") {
8081
8053
  const draft = await readMetaDraft(root);
@@ -8123,6 +8095,7 @@ async function runBuddyCli(args, io, options = {}) {
8123
8095
  } catch (cause) {
8124
8096
  if (!(cause instanceof BuddyProjectContextError) || cause.code !== "PROJECT_DIRECTORY_NOT_FOUND") throw cause;
8125
8097
  }
8098
+ if (projectRoot !== void 0) await checkProjectGateway(projectRoot, resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
8126
8099
  await authenticate(options);
8127
8100
  if (projectRoot !== void 0) {
8128
8101
  io.write(`\u5DF2\u8BC6\u522B\u642D\u642D\u9879\u76EE\uFF1A${projectRoot}`);
@@ -8179,10 +8152,6 @@ async function runBuddyCli(args, io, options = {}) {
8179
8152
  return { exitCode: 0 };
8180
8153
  }
8181
8154
  let route = routeFromMode(parsed.mode);
8182
- if (parsed.runtimeVersion !== void 0) {
8183
- if (!allowsRuntimeVersionSelection(options.runtimeCatalog)) throw new CliUsageError("\u672A\u77E5 init \u53C2\u6570 --runtime-version");
8184
- if (parsed.mode !== "direct") throw new CliUsageError("--runtime-version \u7528\u4E8E --mode direct \u751F\u6210 Runtime \u5DE5\u7A0B\uFF1Bcreate \u68B3\u7406\u5B8C\u6210\u540E\u5728\u8FDB\u5165 direct \u65F6\u9009\u62E9\u7248\u672C\u3002");
8185
- }
8186
8155
  if (route === void 0 && !io.canPrompt) requireModeForNonInteractive();
8187
8156
  const cwd = resolve18(options.cwd ?? process.cwd());
8188
8157
  await assertInitializableBuddyTarget(cwd);
@@ -8190,10 +8159,7 @@ async function runBuddyCli(args, io, options = {}) {
8190
8159
  if (!parsed.directory.trim()) throw new CliUsageError("--directory \u4E0D\u80FD\u4E3A\u7A7A");
8191
8160
  await assertInitializableBuddyTarget(resolve18(cwd, parsed.directory));
8192
8161
  }
8193
- if (route === "direct-create" && (!io.canPrompt || parsed.directory !== void 0)) {
8194
- const target = resolve18(cwd, parsed.directory ?? (parsed.name ? defaultProjectDirectory(parsed.name) : "."));
8195
- parsed.resolvedRuntimeVersion = await selectInitRuntime(target, parsed.runtimeVersion, io, options.runtimeCatalog);
8196
- }
8162
+ await checkProjectGateway(resolve18(cwd, parsed.directory ?? "."), resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
8197
8163
  await authenticate(options);
8198
8164
  await resumeProjectArguments(parsed, cwd, options, io);
8199
8165
  route ??= routeFromMode(parsed.mode);
@@ -8209,7 +8175,7 @@ async function runBuddyCli(args, io, options = {}) {
8209
8175
  io.writeError("\u5DF2\u53D6\u6D88\uFF1B\u5DF2\u4FDD\u5B58\u7684\u672C\u5730\u8349\u7A3F\u548C\u5DF2\u6709\u642D\u5B50\u8D44\u6599\u4F1A\u4FDD\u7559\uFF0C\u672A\u786E\u8BA4\u7684\u8D44\u6599\u4E0D\u4F1A\u767B\u8BB0\u3002");
8210
8176
  return { exitCode: 130 };
8211
8177
  }
8212
- if (cause instanceof MetaPreparationError || cause instanceof RuntimeSelectionError || cause instanceof CliUsageError || cause instanceof BuddyConfigValidationError || cause instanceof ProjectInitializationError || cause instanceof BuddyProjectContextError || cause instanceof CloudLifecycleError) {
8178
+ if (cause instanceof BuddyDevError || cause instanceof MetaPreparationError || cause instanceof CliUsageError || cause instanceof BuddyConfigValidationError || cause instanceof ProjectInitializationError || cause instanceof BuddyProjectContextError || cause instanceof CloudLifecycleError) {
8213
8179
  return failure2(cause.message, io, cause instanceof CliUsageError);
8214
8180
  }
8215
8181
  throw cause;
@@ -8337,6 +8303,7 @@ export {
8337
8303
  assertOutsideBuddyProject,
8338
8304
  buddyAgentConfig,
8339
8305
  buildAgentEnvironment,
8306
+ checkProjectGateway,
8340
8307
  checkRuntimeUpdate,
8341
8308
  combineBuddyProject,
8342
8309
  createBuddyConfig,