@my-life-buddies/cli 0.21.1 → 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,68 +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 isLegacyEcsGateway(value) {
145
- try {
146
- const url = new URL(value);
147
- 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);
148
- } catch {
149
- return false;
150
- }
151
- }
152
- function normalizePlatformUrl(value) {
153
- const url = new URL(value);
154
- if (url.username || url.password || url.search || url.hash) {
155
- throw new TypeError("\u5E73\u53F0\u5730\u5740\u4E0D\u80FD\u5305\u542B credentials\u3001query \u6216 fragment");
156
- }
157
- if (url.protocol !== "https:" && !(url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname))) {
158
- throw new TypeError(`\u5E73\u53F0\u5730\u5740\u5FC5\u987B\u4F7F\u7528 HTTPS\uFF1BHTTP \u4EC5\u5141\u8BB8\u672C\u673A\u5F00\u53D1`);
159
- }
160
- if (!url.pathname.endsWith("/")) url.pathname += "/";
161
- return url;
162
- }
163
- function resolvePlatformUrl(options = {}) {
164
- const env = options.env ?? process.env;
165
- 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;
166
- const selected = options.override ?? env.MLB_GATEWAY_URL ?? legacy ?? DEFAULT_MLB_TEST_URL;
167
- const url = normalizePlatformUrl(isLegacyEcsGateway(selected) ? DEFAULT_MLB_TEST_URL : selected);
168
- 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");
169
- return url;
170
- }
171
- function resolveDeveloperWebUrl(platformUrl, override) {
172
- const url = normalizePlatformUrl(override ?? new URL("/developer/", platformUrl));
173
- if (url.origin !== platformUrl.origin) {
174
- 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");
175
- }
176
- return url;
177
- }
178
- function allowsRuntimeVersionSelection(options = {}) {
179
- const env = options.env ?? process.env;
180
- if (!env.MLB_GATEWAY_URL?.trim()) return false;
181
- const configured = resolvePlatformUrl({ env });
182
- return configured.origin !== new URL(DEFAULT_MLB_TEST_URL).origin && (options.platformUrl === void 0 || options.platformUrl.origin === configured.origin);
183
- }
184
-
185
342
  // packages/cli-core/src/config/runtime-update.ts
186
343
  async function projectRuntimeVersion(root) {
187
344
  try {
188
- return runtimeDependencyVersion(JSON.parse(await readFile2(join2(root, "package.json"), "utf8")));
345
+ return runtimeDependencyVersion(JSON.parse(await readFile2(join3(root, "package.json"), "utf8")));
189
346
  } catch (cause) {
190
347
  if (cause.code === "ENOENT") return void 0;
191
348
  throw cause;
192
349
  }
193
350
  }
194
- async function runtimeVersionStatus(project, latest, selected = false) {
351
+ async function runtimeVersionStatus(project, latest) {
195
352
  const current = project ? await projectRuntimeVersion(project) : void 0;
196
- if (selected) return {
197
- projectRuntimeVersion: current ?? null,
198
- latestRuntimeVersion: null,
199
- selectedRuntimeVersion: latest,
200
- versionStatus: !project ? "no_project" : current === latest ? "selected" : "unconfigured",
201
- adaptationRequired: !!project && current !== latest
202
- };
203
353
  let versionStatus;
204
354
  if (!project) versionStatus = "no_project";
205
355
  else if (!current) versionStatus = "unconfigured";
@@ -219,10 +369,6 @@ async function runtimeVersionStatus(project, latest, selected = false) {
219
369
  }
220
370
  function reportRuntimeVersion(status, report) {
221
371
  if (status.versionStatus === "no_project") return;
222
- if (status.selectedRuntimeVersion !== void 0) {
223
- 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`);
224
- return;
225
- }
226
372
  report(`Runtime \u7248\u672C\uFF1A\u5DE5\u7A0B ${status.projectRuntimeVersion ?? "\u672A\u9501\u5B9A\u51C6\u786E\u7248\u672C"}\uFF0Cnpm \u6700\u65B0 ${status.latestRuntimeVersion}\u3002`);
227
373
  if (status.adaptationRequired) {
228
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");
@@ -232,69 +378,13 @@ function reportRuntimeVersion(status, report) {
232
378
  async function checkRuntimeUpdate(root, report, options = {}) {
233
379
  options.signal?.throwIfAborted();
234
380
  try {
235
- if (allowsRuntimeVersionSelection(options)) {
236
- const current = await projectRuntimeVersion(root);
237
- if (!current) {
238
- 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");
239
- return;
240
- }
241
- const selected = await resolveRuntimeVersion(current, options);
242
- reportRuntimeVersion(await runtimeVersionStatus(root, selected, true), report);
243
- options.signal?.throwIfAborted();
244
- return;
245
- }
246
381
  const latest = await latestRuntimeVersion(options);
247
382
  const status = await runtimeVersionStatus(root, latest);
248
383
  options.signal?.throwIfAborted();
249
384
  reportRuntimeVersion(status, report);
250
385
  } catch (cause) {
251
386
  options.signal?.throwIfAborted();
252
- 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`);
253
- }
254
- }
255
-
256
- // packages/cli-core/src/init/runtime-selection.ts
257
- import { readFile as readFile3 } from "node:fs/promises";
258
- import { join as join3 } from "node:path";
259
- var RuntimeSelectionError = class extends Error {
260
- };
261
- async function selectInitRuntime(root, requested, io, options = {}) {
262
- if (!allowsRuntimeVersionSelection(options)) {
263
- if (requested !== void 0) throw new RuntimeSelectionError("\u672A\u77E5 init \u53C2\u6570 --runtime-version");
264
- return void 0;
265
- }
266
- let pkg;
267
- try {
268
- pkg = JSON.parse(await readFile3(join3(root, "package.json"), "utf8"));
269
- } catch (cause) {
270
- if (cause.code !== "ENOENT") throw cause;
271
- }
272
- const existing = runtimeDependencyVersion(pkg);
273
- if (pkg?.dependencies?.[BUDDY_RUNTIME_PACKAGE] !== void 0) {
274
- 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");
275
- 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`);
276
- return existing;
277
- }
278
- try {
279
- let selector = requested;
280
- if (!selector) {
281
- if (!io.canPrompt) throw new RuntimeSelectionError(await runtimeSelectionPrompt(options));
282
- const releases = await runtimeReleaseChoices(options);
283
- selector = await io.select("\u8FD9\u4E2A\u642D\u5B50\u4F7F\u7528\u54EA\u4E2A Runtime \u7248\u672C\uFF1F", [
284
- { value: releases.latest, label: `\u6700\u65B0\u7A33\u5B9A\u7248 ${releases.latest}\uFF08\u63A8\u8350\uFF09` },
285
- ...releases.dev ? [{ value: releases.dev, label: `\u6700\u65B0\u6D4B\u8BD5\u7248 ${releases.dev}` }] : [],
286
- { value: "other", label: "\u6307\u5B9A\u5176\u4ED6\u5DF2\u53D1\u5E03\u7248\u672C" }
287
- ]);
288
- if (selector === "other") {
289
- io.write(`\u53EF\u7528\u7248\u672C\uFF1A${releases.versions.join("\u3001")}`);
290
- selector = (await io.input("\u8F93\u5165 Runtime \u7684\u51C6\u786E\u7248\u672C")).trim();
291
- }
292
- }
293
- return await resolveRuntimeVersion(selector, options);
294
- } catch (cause) {
295
- options.signal?.throwIfAborted();
296
- if (cause instanceof RuntimeSelectionError || cause instanceof Error && cause.name === "PromptCancelledError") throw cause;
297
- 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`);
298
388
  }
299
389
  }
300
390
 
@@ -302,13 +392,13 @@ async function selectInitRuntime(root, requested, io, options = {}) {
302
392
  import { resolve as resolve6 } from "node:path";
303
393
 
304
394
  // packages/cli-core/src/config/runtime-catalog.ts
305
- import { readFile as readFile4, realpath } from "node:fs/promises";
395
+ import { readFile as readFile3, realpath } from "node:fs/promises";
306
396
  import { createRequire } from "node:module";
307
397
  import { resolve } from "node:path";
308
398
  import { pathToFileURL } from "node:url";
309
399
  async function loadRuntime(projectRoot) {
310
400
  const packagePath = resolve(projectRoot, "package.json");
311
- const expected = runtimeDependencyVersion(JSON.parse(await readFile4(packagePath, "utf8")));
401
+ const expected = runtimeDependencyVersion(JSON.parse(await readFile3(packagePath, "utf8")));
312
402
  if (!expected) throw new Error(`package.json \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C`);
313
403
  const projectRequire = createRequire(packagePath);
314
404
  let runtimePath;
@@ -317,7 +407,7 @@ async function loadRuntime(projectRoot) {
317
407
  if (await realpath(projectRequire.resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`)) !== installedPath) {
318
408
  throw new Error("Runtime \u5FC5\u987B\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D");
319
409
  }
320
- const installed2 = JSON.parse(await readFile4(installedPath, "utf8"));
410
+ const installed2 = JSON.parse(await readFile3(installedPath, "utf8"));
321
411
  if (installed2.version !== expected) throw new Error(`\u5DF2\u5B89\u88C5 ${installed2.version}\uFF0C\u5DE5\u7A0B\u8981\u6C42 ${expected}`);
322
412
  runtimePath = projectRequire.resolve(BUDDY_RUNTIME_PACKAGE);
323
413
  } catch (cause) {
@@ -368,7 +458,7 @@ async function validateRuntimeDatasets(projectRoot, requirements = []) {
368
458
  }
369
459
 
370
460
  // packages/cli-core/src/project-context.ts
371
- 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";
372
462
  import { dirname, join as join10, resolve as resolve5 } from "node:path";
373
463
 
374
464
  // packages/cli-core/src/config/index.ts
@@ -376,13 +466,13 @@ import {
376
466
  link,
377
467
  lstat as lstat6,
378
468
  mkdir as mkdir6,
379
- open as open3,
380
- readFile as readFile10,
469
+ open as open4,
470
+ readFile as readFile9,
381
471
  readdir as readdir3,
382
- rename as rename6,
383
- unlink as unlink4
472
+ rename as rename7,
473
+ unlink as unlink5
384
474
  } from "node:fs/promises";
385
- import { randomUUID as randomUUID4 } from "node:crypto";
475
+ import { randomUUID as randomUUID5 } from "node:crypto";
386
476
  import { isAbsolute as isAbsolute2, join as join9, resolve as resolve4, win32 } from "node:path";
387
477
  import { isDeepStrictEqual } from "node:util";
388
478
  import { Ajv2020 } from "ajv/dist/2020.js";
@@ -407,13 +497,13 @@ var buddy_package_schema_default = {
407
497
  };
408
498
 
409
499
  // packages/cli-core/src/init/meta.ts
410
- import { createHash, randomUUID as randomUUID2 } from "node:crypto";
411
- 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";
412
502
  import { join as join6, resolve as resolve2 } from "node:path";
413
503
 
414
504
  // packages/cli-core/src/init/skill-package.ts
415
505
  import { execFile as execFile2 } from "node:child_process";
416
- 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";
417
507
  import { homedir as homedir2 } from "node:os";
418
508
  import { isAbsolute, join as join4 } from "node:path";
419
509
  import { promisify as promisify2 } from "node:util";
@@ -436,9 +526,9 @@ function checkProtocol(definition3, pkg) {
436
526
  }
437
527
  async function installed(definition3, root, version) {
438
528
  if (!(await lstat2(root)).isDirectory()) throw new Error(`${definition3.label} \u7F13\u5B58\u4E0D\u80FD\u4F7F\u7528\u7B26\u53F7\u94FE\u63A5\u3002`);
439
- const pkg = JSON.parse(await readFile5(join4(root, "package.json"), "utf8"));
529
+ const pkg = JSON.parse(await readFile4(join4(root, "package.json"), "utf8"));
440
530
  checkProtocol(definition3, pkg);
441
- const meta2 = JSON.parse(await readFile5(join4(root, "version.json"), "utf8"));
531
+ const meta2 = JSON.parse(await readFile4(join4(root, "version.json"), "utf8"));
442
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`);
443
533
  for (const file of definition3.requiredFiles) {
444
534
  const path = join4(root, file);
@@ -454,7 +544,7 @@ async function cached(definition3, root, lock) {
454
544
  }
455
545
  const skill = join4(root, "node_modules", definition3.name);
456
546
  try {
457
- 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"));
458
548
  const entry2 = record2.packages?.[`node_modules/${definition3.name}`];
459
549
  if (entry2?.version !== lock.version || entry2.integrity !== lock.integrity) throw new Error("\u7F13\u5B58\u6821\u9A8C\u8BB0\u5F55\u4E0D\u5339\u914D");
460
550
  await installed(definition3, skill, lock.version);
@@ -471,7 +561,7 @@ async function resolveSkillPackage(definition3, previous, options = {}) {
471
561
  if (local) {
472
562
  if (!isAbsolute(local)) throw new Error(`${definition3.pathEnvironment} \u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002`);
473
563
  const root = await realpath2(local);
474
- const pkg2 = JSON.parse(await readFile5(join4(root, "package.json"), "utf8"));
564
+ const pkg2 = JSON.parse(await readFile4(join4(root, "package.json"), "utf8"));
475
565
  await installed(definition3, root, pkg2.version);
476
566
  options.report?.(`\u4F7F\u7528\u672C\u5730 ${definition3.label} Skill ${pkg2.version}\uFF1A${root}`);
477
567
  return { root, lock: { source: "local", path: root, version: pkg2.version, protocolVersion: 1 } };
@@ -532,7 +622,7 @@ async function resolveSkillPackage(definition3, previous, options = {}) {
532
622
  await cached(definition3, temporary, lock);
533
623
  options.signal?.throwIfAborted();
534
624
  try {
535
- await rename2(temporary, destination);
625
+ await rename3(temporary, destination);
536
626
  } catch (error2) {
537
627
  if (!["EEXIST", "ENOTEMPTY"].includes(error2.code ?? "")) throw error2;
538
628
  }
@@ -556,11 +646,11 @@ var definition = {
556
646
  var resolveAvatarSkill = (previous, options = {}) => resolveSkillPackage(definition, previous, options);
557
647
 
558
648
  // packages/cli-core/src/cloud/avatar.ts
559
- import { open } from "node:fs/promises";
649
+ import { open as open2 } from "node:fs/promises";
560
650
  import { basename } from "node:path";
561
651
  var MAX_BUDDY_AVATAR_BYTES = 5 * 1024 * 1024;
562
652
  async function readBuddyAvatarFile(path) {
563
- const file = await open(path, "r");
653
+ const file = await open2(path, "r");
564
654
  try {
565
655
  const stat2 = await file.stat();
566
656
  if (!stat2.isFile()) throw new Error("\u5934\u50CF\u5FC5\u987B\u662F\u666E\u901A\u56FE\u7247\u6587\u4EF6");
@@ -583,8 +673,8 @@ async function readBuddyAvatarFile(path) {
583
673
  }
584
674
 
585
675
  // packages/cli-core/src/process-lock.ts
586
- import { randomUUID } from "node:crypto";
587
- 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";
588
678
  import { join as join5 } from "node:path";
589
679
  function alive(pid) {
590
680
  try {
@@ -607,8 +697,8 @@ async function acquireProcessLock(options) {
607
697
  const root = options.directory;
608
698
  const key = options.key;
609
699
  const path = join5(root, key);
610
- const ownerName = `owner-${randomUUID()}.json`;
611
- const candidate = join5(root, `.pending-${randomUUID()}`);
700
+ const ownerName = `owner-${randomUUID2()}.json`;
701
+ const candidate = join5(root, `.pending-${randomUUID2()}`);
612
702
  const owner = { ...options.ownerData, pid: process.pid };
613
703
  await mkdir3(root, { recursive: true, mode: 448 });
614
704
  await mkdir3(candidate, { mode: 448 });
@@ -616,7 +706,7 @@ async function acquireProcessLock(options) {
616
706
  try {
617
707
  for (let attempt = 0; ; attempt++) {
618
708
  try {
619
- await rename3(candidate, path);
709
+ await rename4(candidate, path);
620
710
  break;
621
711
  } catch (error2) {
622
712
  if (!["EEXIST", "ENOTEMPTY"].includes(code(error2) ?? "")) throw error2;
@@ -634,14 +724,14 @@ async function acquireProcessLock(options) {
634
724
  const previousPath = join5(path, names[0]);
635
725
  let previous;
636
726
  try {
637
- previous = JSON.parse(await readFile6(previousPath, "utf8"));
727
+ previous = JSON.parse(await readFile5(previousPath, "utf8"));
638
728
  } catch (error2) {
639
729
  if (code(error2) === "ENOENT") continue;
640
730
  throw options.busyError();
641
731
  }
642
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();
643
733
  try {
644
- await unlink(previousPath);
734
+ await unlink2(previousPath);
645
735
  } catch (error2) {
646
736
  if (code(error2) === "ENOENT") continue;
647
737
  throw error2;
@@ -651,25 +741,25 @@ async function acquireProcessLock(options) {
651
741
  });
652
742
  }
653
743
  } finally {
654
- await unlink(join5(candidate, ownerName)).catch(() => void 0);
744
+ await unlink2(join5(candidate, ownerName)).catch(() => void 0);
655
745
  await rmdir(candidate).catch(() => void 0);
656
746
  }
657
747
  let released = false;
658
748
  return {
659
749
  async attachRuntime(pid) {
660
750
  if (!validPid(pid)) throw new TypeError("Runtime PID is invalid");
661
- const temporary = join5(root, `.update-${randomUUID()}`);
751
+ const temporary = join5(root, `.update-${randomUUID2()}`);
662
752
  try {
663
753
  await writeFile3(temporary, JSON.stringify({ ...owner, ...await options.runtimeData?.(pid), runtimePid: pid }), { mode: 384, flag: "wx" });
664
- await rename3(temporary, join5(path, ownerName));
754
+ await rename4(temporary, join5(path, ownerName));
665
755
  } finally {
666
- await unlink(temporary).catch(() => void 0);
756
+ await unlink2(temporary).catch(() => void 0);
667
757
  }
668
758
  },
669
759
  async release() {
670
760
  if (released) return;
671
761
  released = true;
672
- await unlink(join5(path, ownerName)).catch((error2) => {
762
+ await unlink2(join5(path, ownerName)).catch((error2) => {
673
763
  if (code(error2) !== "ENOENT") throw error2;
674
764
  });
675
765
  await rmdir(path).catch((error2) => {
@@ -704,16 +794,16 @@ async function localFile(path) {
704
794
  const item = await entry(path);
705
795
  if (!item) return void 0;
706
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}`);
707
- return readFile7(path);
797
+ return readFile6(path);
708
798
  }
709
799
  async function save(path, content) {
710
800
  await localFile(path);
711
- const temporary = `${path}.${randomUUID2()}.tmp`;
801
+ const temporary = `${path}.${randomUUID3()}.tmp`;
712
802
  try {
713
803
  await writeFile4(temporary, content, { flag: "wx", mode: 384 });
714
- await rename4(temporary, path);
804
+ await rename5(temporary, path);
715
805
  } finally {
716
- await unlink2(temporary).catch((e) => {
806
+ await unlink3(temporary).catch((e) => {
717
807
  if (e.code !== "ENOENT") throw e;
718
808
  });
719
809
  }
@@ -921,9 +1011,9 @@ import { lstat as lstat5 } from "node:fs/promises";
921
1011
  import { join as join8 } from "node:path";
922
1012
 
923
1013
  // packages/cli-core/src/init/scaffold.ts
924
- 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";
925
1015
  import { resolve as resolve3 } from "node:path";
926
- import { randomUUID as randomUUID3 } from "node:crypto";
1016
+ import { randomUUID as randomUUID4 } from "node:crypto";
927
1017
 
928
1018
  // packages/cli-core/src/config/models.ts
929
1019
  var MODEL_IDS = Object.freeze([
@@ -936,7 +1026,7 @@ var DEFAULT_MODEL_ID = "kimi-k2.6";
936
1026
 
937
1027
  // packages/cli-core/src/init/runtime-template.ts
938
1028
  import { execFile as execFile3 } from "node:child_process";
939
- 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";
940
1030
  import { tmpdir } from "node:os";
941
1031
  import { join as join7 } from "node:path";
942
1032
  import { promisify as promisify3 } from "node:util";
@@ -947,8 +1037,8 @@ async function latestRuntimeTemplate(template, options) {
947
1037
  let temporaryRoot;
948
1038
  try {
949
1039
  options.signal?.throwIfAborted();
950
- options.report(options.runtimeVersion ? `\u6B63\u5728\u786E\u8BA4 Runtime ${options.runtimeVersion}\u2026` : "\u6B63\u5728\u67E5\u8BE2\u516C\u5171 npm \u7684\u6700\u65B0 Runtime\u2026");
951
- 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);
952
1042
  let result = template;
953
1043
  if (version !== bundledVersion) {
954
1044
  temporaryRoot = await mkdtemp3(join7(tmpdir(), "buddy-runtime-template-"));
@@ -976,8 +1066,8 @@ async function latestRuntimeTemplate(template, options) {
976
1066
  "--fetch-timeout=20000"
977
1067
  ], { cwd: temporaryRoot, signal: options.signal, timeout: 6e4 });
978
1068
  result = {
979
- packageJson: await readFile8(join7(temporaryRoot, "package.json"), "utf8"),
980
- 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")
981
1071
  };
982
1072
  }
983
1073
  const pkg = JSON.parse(result.packageJson);
@@ -987,12 +1077,12 @@ async function latestRuntimeTemplate(template, options) {
987
1077
  throw new Error("\u751F\u6210\u7684 Runtime \u7248\u672C\u4E0E\u4F9D\u8D56\u9501\u6587\u4EF6\u4E0D\u4E00\u81F4");
988
1078
  }
989
1079
  options.signal?.throwIfAborted();
990
- 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`);
991
1081
  return result;
992
1082
  } catch (cause) {
993
1083
  if (options.signal?.aborted) throw new Error("Runtime \u7248\u672C\u9009\u62E9\u5DF2\u53D6\u6D88");
994
1084
  const reason = cause instanceof Error && !cause.message.includes("Command failed") ? cause.message : "npm \u672A\u5B8C\u6210\u9501\u6587\u4EF6\u751F\u6210";
995
- 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 });
996
1086
  } finally {
997
1087
  if (temporaryRoot) await rm3(temporaryRoot, { recursive: true, force: true });
998
1088
  }
@@ -1082,7 +1172,7 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1082
1172
  const path = resolve3(projectRoot, BUDDY_PLATFORM_AGENT_ENTRY);
1083
1173
  const packagePath = resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
1084
1174
  if (!(await lstat4(packagePath)).isFile()) throw new Error("package.json \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6");
1085
- const originalPackage = await readFile9(packagePath, "utf8");
1175
+ const originalPackage = await readFile8(packagePath, "utf8");
1086
1176
  const projectPackage = parseBuddyProjectManifest(originalPackage);
1087
1177
  const isIdentityDraft = Object.keys(projectPackage).every((key) => key === "buddyId");
1088
1178
  const hasAlternateLockfile = (await Promise.all(["pnpm-lock.yaml", "yarn.lock"].map(async (name2) => {
@@ -1099,12 +1189,12 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1099
1189
  const files = [
1100
1190
  { path, content: platformAgentTemplate(name) },
1101
1191
  { path: resolve3(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate(options.model) },
1102
- { path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile9(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
1103
- ...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") }],
1104
1194
  { path: resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() },
1105
1195
  { path: resolve3(projectRoot, "data-access.json"), content: '{\n "requirements": []\n}\n' },
1106
1196
  { path: resolve3(projectRoot, ".gitignore"), content: "node_modules/\n/.env\n" },
1107
- { 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" }
1108
1198
  ];
1109
1199
  const handles = [];
1110
1200
  const createdDirectories = [];
@@ -1123,7 +1213,7 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1123
1213
  }
1124
1214
  for (const file of files) {
1125
1215
  try {
1126
- 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) });
1127
1217
  } catch (cause) {
1128
1218
  if (cause.code !== "EEXIST") throw cause;
1129
1219
  if (!(await lstat4(file.path)).isFile()) {
@@ -1143,8 +1233,8 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1143
1233
  lockFile.content = template.packageLock;
1144
1234
  }
1145
1235
  if (lockFile && (isIdentityDraft || handles.some((file) => file.path === lockFile.path))) {
1146
- const packageContents = isIdentityDraft ? packageFile.content : await readFile9(packageFile.path, "utf8");
1147
- 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");
1148
1238
  const declared = JSON.parse(packageContents).dependencies ?? {};
1149
1239
  const locked = JSON.parse(lockContents).packages?.[""]?.dependencies ?? {};
1150
1240
  if (JSON.stringify(Object.entries(declared).sort()) !== JSON.stringify(Object.entries(locked).sort())) {
@@ -1157,19 +1247,19 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1157
1247
  await handle.sync();
1158
1248
  }
1159
1249
  if (isIdentityDraft) {
1160
- const temporary = `${packagePath}.${randomUUID3()}.tmp`;
1161
- const handle = await open2(temporary, "wx", 384);
1250
+ const temporary = `${packagePath}.${randomUUID4()}.tmp`;
1251
+ const handle = await open3(temporary, "wx", 384);
1162
1252
  try {
1163
1253
  await handle.writeFile(packageFile.content, "utf8");
1164
1254
  await handle.sync();
1165
1255
  await handle.close();
1166
- if (!(await lstat4(packagePath)).isFile() || await readFile9(packagePath, "utf8") !== originalPackage) {
1256
+ if (!(await lstat4(packagePath)).isFile() || await readFile8(packagePath, "utf8") !== originalPackage) {
1167
1257
  throw new Error("\u8865\u9F50\u5DE5\u7A0B\u65F6 package.json \u5DF2\u6539\u53D8\uFF0C\u8BF7\u91CD\u8BD5");
1168
1258
  }
1169
- await rename5(temporary, packagePath);
1259
+ await rename6(temporary, packagePath);
1170
1260
  } finally {
1171
1261
  await handle.close().catch(() => void 0);
1172
- await unlink3(temporary).catch((cause) => {
1262
+ await unlink4(temporary).catch((cause) => {
1173
1263
  if (cause.code !== "ENOENT") throw cause;
1174
1264
  });
1175
1265
  }
@@ -1177,7 +1267,7 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
1177
1267
  return Object.freeze({ path, created: isIdentityDraft || handles.length > 0 || createdDirectories.length > 0 });
1178
1268
  } catch (cause) {
1179
1269
  await Promise.all(handles.map(({ handle }) => handle.close().catch(() => void 0)));
1180
- 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)));
1181
1271
  for (const directory of createdDirectories.reverse()) {
1182
1272
  await rmdir2(directory).catch(() => void 0);
1183
1273
  }
@@ -1345,7 +1435,7 @@ async function unlinkMatchingFile(targetPath, expectedIdentity) {
1345
1435
  if (!entry2.isFile() || entry2.isSymbolicLink() || entryIdentity(entry2) !== expectedIdentity) {
1346
1436
  return false;
1347
1437
  }
1348
- await unlink4(targetPath);
1438
+ await unlink5(targetPath);
1349
1439
  return true;
1350
1440
  } catch (cause) {
1351
1441
  return cause.code === "ENOENT";
@@ -1388,7 +1478,7 @@ async function readExistingManifest(agentConfigPath) {
1388
1478
  );
1389
1479
  }
1390
1480
  try {
1391
- return parseBuddyProjectManifest(await readFile10(agentConfigPath, "utf8"));
1481
+ return parseBuddyProjectManifest(await readFile9(agentConfigPath, "utf8"));
1392
1482
  } catch (cause) {
1393
1483
  throw new ProjectInitializationError(
1394
1484
  "TARGET_CHANGED",
@@ -1474,12 +1564,12 @@ async function publishNewFile(options) {
1474
1564
  let publishedHandle;
1475
1565
  const temporaryPath = join9(
1476
1566
  options.rootDirectory,
1477
- `.${options.temporaryLabel}.${process.pid}.${randomUUID4()}.tmp`
1567
+ `.${options.temporaryLabel}.${process.pid}.${randomUUID5()}.tmp`
1478
1568
  );
1479
1569
  let temporaryIdentity;
1480
1570
  let publishedIdentity;
1481
1571
  try {
1482
- temporaryHandle = await open3(temporaryPath, "wx");
1572
+ temporaryHandle = await open4(temporaryPath, "wx");
1483
1573
  temporaryIdentity = entryIdentity(await temporaryHandle.stat());
1484
1574
  await temporaryHandle.writeFile(options.contents, "utf8");
1485
1575
  await temporaryHandle.sync();
@@ -1502,7 +1592,7 @@ async function publishNewFile(options) {
1502
1592
  if (fallbackBeforeOpen.kind !== "directory" || fallbackBeforeOpen.identity !== options.directoryIdentity) {
1503
1593
  throw targetChanged({ rootDirectory: options.rootDirectory });
1504
1594
  }
1505
- publishedHandle = await open3(options.targetPath, "wx");
1595
+ publishedHandle = await open4(options.targetPath, "wx");
1506
1596
  publishedIdentity = entryIdentity(await publishedHandle.stat());
1507
1597
  const fallbackRoot = await pathState(options.rootDirectory);
1508
1598
  if (fallbackRoot.kind !== "directory" || fallbackRoot.identity !== options.directoryIdentity) {
@@ -1516,7 +1606,7 @@ async function publishNewFile(options) {
1516
1606
  const afterPublish = await pathState(options.rootDirectory);
1517
1607
  const publishedFileIdentity = await fileIdentity(options.targetPath);
1518
1608
  const temporaryFileIdentity = await fileIdentity(temporaryPath);
1519
- const publishedContents = publishedFileIdentity ? await readFile10(options.targetPath, "utf8") : void 0;
1609
+ const publishedContents = publishedFileIdentity ? await readFile9(options.targetPath, "utf8") : void 0;
1520
1610
  if (afterPublish.kind !== "directory" || afterPublish.identity !== options.directoryIdentity || !publishedIdentity || publishedFileIdentity !== publishedIdentity || temporaryFileIdentity !== temporaryIdentity || publishedContents !== options.contents) {
1521
1611
  if (afterPublish.kind === "directory" && afterPublish.identity === options.directoryIdentity && publishedIdentity) {
1522
1612
  await unlinkMatchingFile(options.targetPath, publishedIdentity);
@@ -1545,9 +1635,9 @@ async function publishNewFile(options) {
1545
1635
  async function replaceExistingFile(options) {
1546
1636
  const temporaryPath = join9(
1547
1637
  options.rootDirectory,
1548
- `.${options.temporaryLabel}.${process.pid}.${randomUUID4()}.tmp`
1638
+ `.${options.temporaryLabel}.${process.pid}.${randomUUID5()}.tmp`
1549
1639
  );
1550
- const handle = await open3(temporaryPath, "wx", 384);
1640
+ const handle = await open4(temporaryPath, "wx", 384);
1551
1641
  try {
1552
1642
  await handle.writeFile(options.contents, "utf8");
1553
1643
  await handle.sync();
@@ -1557,12 +1647,12 @@ async function replaceExistingFile(options) {
1557
1647
  try {
1558
1648
  const root = await pathState(options.rootDirectory);
1559
1649
  if (root.kind !== "directory" || root.identity !== options.directoryIdentity || await fileIdentity(options.targetPath) !== options.expectedFileIdentity) throw targetChanged({ rootDirectory: options.rootDirectory });
1560
- await rename6(temporaryPath, options.targetPath);
1561
- if (await readFile10(options.targetPath, "utf8") !== options.contents) {
1650
+ await rename7(temporaryPath, options.targetPath);
1651
+ if (await readFile9(options.targetPath, "utf8") !== options.contents) {
1562
1652
  throw targetChanged({ rootDirectory: options.rootDirectory });
1563
1653
  }
1564
1654
  } finally {
1565
- await unlink4(temporaryPath).catch((cause) => {
1655
+ await unlink5(temporaryPath).catch((cause) => {
1566
1656
  if (cause.code !== "ENOENT") throw cause;
1567
1657
  });
1568
1658
  }
@@ -1684,11 +1774,11 @@ async function initializeBuddyProject(options) {
1684
1774
  }
1685
1775
  async function readBuddyProjectManifest(projectRoot) {
1686
1776
  const rootDirectory = resolve4(projectRoot);
1687
- return parseBuddyProjectManifest(await readFile10(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8"));
1777
+ return parseBuddyProjectManifest(await readFile9(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8"));
1688
1778
  }
1689
1779
  async function readBuddyAgentConfig(projectRoot) {
1690
1780
  const rootDirectory = resolve4(projectRoot);
1691
- const source = await readFile10(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8");
1781
+ const source = await readFile9(resolve4(rootDirectory, BUDDY_PACKAGE_FILENAME), "utf8");
1692
1782
  return parseBuddyAgentConfig(source);
1693
1783
  }
1694
1784
  async function readBuddyConfig(projectRoot) {
@@ -1755,7 +1845,7 @@ async function searchUp(startDirectory) {
1755
1845
  if (await projectFileState(directory, BUDDY_PACKAGE_FILENAME) === "valid") {
1756
1846
  let pkg;
1757
1847
  try {
1758
- pkg = JSON.parse(await readFile11(join10(directory, BUDDY_PACKAGE_FILENAME), "utf8"));
1848
+ pkg = JSON.parse(await readFile10(join10(directory, BUDDY_PACKAGE_FILENAME), "utf8"));
1759
1849
  } catch (cause) {
1760
1850
  throw new BuddyProjectContextError("PROJECT_CONFIG_INVALID", `\u65E0\u6CD5\u89E3\u6790 ${join10(directory, BUDDY_PACKAGE_FILENAME)}`, directory, { cause });
1761
1851
  }
@@ -1874,20 +1964,6 @@ async function assertInitializableBuddyTarget(target) {
1874
1964
  // packages/cli-core/src/commands/runtime-source.ts
1875
1965
  async function runtimeCatalogSource(directory, options = {}) {
1876
1966
  const project = await findBuddyProjectRoot(directory);
1877
- if (allowsRuntimeVersionSelection(options)) {
1878
- const declared = project ? await projectRuntimeVersion(project) : void 0;
1879
- if (declared && options.runtimeVersion !== void 0 && options.runtimeVersion !== declared) {
1880
- 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`);
1881
- }
1882
- const requested = declared ?? options.runtimeVersion;
1883
- if (!requested) throw new Error(await runtimeSelectionPrompt(options));
1884
- const selected = await resolveRuntimeVersion(requested, options);
1885
- const root2 = await cachedRuntimeRoot(selected, options);
1886
- const version2 = await runtimeVersionStatus(project, selected, true);
1887
- if (options.report) reportRuntimeVersion(version2, options.report);
1888
- return { root: root2, source: "npm", version: version2 };
1889
- }
1890
- if (options.runtimeVersion !== void 0) throw new Error("\u5F53\u524D\u5E73\u53F0\u7684\u80FD\u529B\u76EE\u5F55\u4F7F\u7528\u6700\u65B0\u7A33\u5B9A\u7248");
1891
1967
  const root = await (options.latestRuntimeRoot?.() ?? cachedLatestRuntimeRoot(options));
1892
1968
  const latest = await projectRuntimeVersion(root);
1893
1969
  if (!latest) throw new Error("npm Runtime \u7F13\u5B58\u7F3A\u5C11\u51C6\u786E\u7248\u672C");
@@ -1903,28 +1979,24 @@ var MODELS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli models [--directory <\u9879\u
1903
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`;
1904
1980
  async function runModelsCommand(args, io, cwd, options = {}) {
1905
1981
  try {
1906
- const selected = allowsRuntimeVersionSelection(options);
1907
- const help = selected ? `\u7528\u6CD5: buddy-cli models [--directory <\u9879\u76EE\u76EE\u5F55>] [--runtime-version <\u51C6\u786E\u7248\u672C|latest|dev>] [--json]
1908
- \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;
1909
1983
  if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
1910
1984
  io.write(help);
1911
1985
  return { exitCode: 0 };
1912
1986
  }
1913
1987
  let directory;
1914
1988
  let json2 = false;
1915
- let runtimeVersion;
1916
1989
  for (let i = 0; i < args.length; i++) {
1917
1990
  if (args[i] === "--json" && !json2) json2 = true;
1918
1991
  else if (args[i] === "--directory" && directory === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) directory = args[++i];
1919
- else if (selected && args[i] === "--runtime-version" && runtimeVersion === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) runtimeVersion = args[++i];
1920
1992
  else throw new Error(`models \u53C2\u6570\u65E0\u6548\uFF1A${args[i]}
1921
1993
  ${help}`);
1922
1994
  }
1923
- 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 });
1924
1996
  const catalog = await readRuntimeModelCatalog(root);
1925
1997
  if (json2) io.write(JSON.stringify({ source, ...catalog, ...version }, null, 2));
1926
1998
  else {
1927
- 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`);
1928
2000
  for (const id of catalog.models) io.write(`- ${id}`);
1929
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");
1930
2002
  }
@@ -1946,28 +2018,24 @@ var DATASETS_COMMAND_HELP = `\u7528\u6CD5: buddy-cli datasets [--directory <\u98
1946
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`;
1947
2019
  async function runDatasetsCommand(args, io, cwd, options = {}) {
1948
2020
  try {
1949
- const selected = allowsRuntimeVersionSelection(options);
1950
- const help = selected ? `\u7528\u6CD5: buddy-cli datasets [--directory <\u9879\u76EE\u76EE\u5F55>] [--runtime-version <\u51C6\u786E\u7248\u672C|latest|dev>] [--json]
1951
- \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;
1952
2022
  if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
1953
2023
  io.write(help);
1954
2024
  return { exitCode: 0 };
1955
2025
  }
1956
2026
  let directory;
1957
2027
  let json2 = false;
1958
- let runtimeVersion;
1959
2028
  for (let i = 0; i < args.length; i++) {
1960
2029
  if (args[i] === "--json" && !json2) json2 = true;
1961
2030
  else if (args[i] === "--directory" && directory === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) directory = args[++i];
1962
- else if (selected && args[i] === "--runtime-version" && runtimeVersion === void 0 && args[i + 1]?.trim() && !args[i + 1].startsWith("--")) runtimeVersion = args[++i];
1963
2031
  else throw new Error(`datasets \u53C2\u6570\u65E0\u6548\uFF1A${args[i]}
1964
2032
  ${help}`);
1965
2033
  }
1966
- 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 });
1967
2035
  const catalog = await readRuntimeDataCatalog(root);
1968
2036
  if (json2) io.write(JSON.stringify({ source, ...catalog, ...version }, null, 2));
1969
2037
  else {
1970
- 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`);
1971
2039
  for (const item of catalog.datasets) io.write(`- ${item.id} \u2014 ${item.title}\uFF08${item.source}\uFF0CSchema ${item.schemaVersion}\uFF09`);
1972
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");
1973
2041
  }
@@ -1979,8 +2047,8 @@ ${help}`);
1979
2047
  }
1980
2048
 
1981
2049
  // packages/cli-core/src/commands/knowledge.ts
1982
- import { createHash as createHash2, randomUUID as randomUUID5 } from "node:crypto";
1983
- 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";
1984
2052
  import { dirname as dirname2, join as join11, resolve as resolve8 } from "node:path";
1985
2053
  var MANIFEST = "knowledge-manifest.json";
1986
2054
  var INDEX = "resources/knowledge/index.md";
@@ -2039,7 +2107,7 @@ async function read(root, path) {
2039
2107
  });
2040
2108
  if (!entry2) return void 0;
2041
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}`);
2042
- return readFile12(full);
2110
+ return readFile11(full);
2043
2111
  }
2044
2112
  async function requiredRead(root, path) {
2045
2113
  const bytes = await read(root, path);
@@ -2049,12 +2117,12 @@ async function requiredRead(root, path) {
2049
2117
  async function atomicWrite(root, path, value) {
2050
2118
  const full = await safePath(root, path);
2051
2119
  await mkdir7(dirname2(full), { recursive: true });
2052
- const temporary = `${full}.${randomUUID5()}.tmp`;
2120
+ const temporary = `${full}.${randomUUID6()}.tmp`;
2053
2121
  await writeFile6(temporary, value, { flag: "wx", mode: 384 });
2054
2122
  try {
2055
- await rename7(temporary, full);
2123
+ await rename8(temporary, full);
2056
2124
  } finally {
2057
- await unlink5(temporary).catch((error2) => {
2125
+ await unlink6(temporary).catch((error2) => {
2058
2126
  if (!missing(error2)) throw error2;
2059
2127
  });
2060
2128
  }
@@ -2225,7 +2293,7 @@ async function syncKnowledge(root, planPath) {
2225
2293
  if (current && hash2(current) !== hash2(content) && hash2(current) !== expected.get(path)) conflicts.push(path);
2226
2294
  }
2227
2295
  if (conflicts.length) {
2228
- const directory = `.buddy/knowledge/conflicts/${randomUUID5()}`;
2296
+ const directory = `.buddy/knowledge/conflicts/${randomUUID6()}`;
2229
2297
  for (const [path, content] of files) await atomicWrite(root, `${directory}/${path}`, content);
2230
2298
  await atomicWrite(root, `${directory}/${MANIFEST}`, json(next));
2231
2299
  return { status: "conflict", conflicts, candidateDirectory: directory, written: [] };
@@ -2292,11 +2360,11 @@ ${KNOWLEDGE_HELP}`);
2292
2360
  }
2293
2361
 
2294
2362
  // packages/cli-core/src/index.ts
2295
- import { join as join23, resolve as resolve18 } from "node:path";
2363
+ import { join as join22, resolve as resolve18 } from "node:path";
2296
2364
 
2297
2365
  // packages/cli-core/src/init/creator.ts
2298
- import { createHash as createHash3, randomUUID as randomUUID6 } from "node:crypto";
2299
- 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";
2300
2368
  import { dirname as dirname3, join as join13 } from "node:path";
2301
2369
 
2302
2370
  // packages/cli-core/src/init/creator-package.ts
@@ -2548,26 +2616,26 @@ async function safeRead(path) {
2548
2616
  if (!entry2.isFile() || entry2.size > MAX_LOCAL_FILE_BYTES) {
2549
2617
  throw new CreatorPreparationError(`\u521B\u4F5C\u6587\u4EF6\u4E0D\u662F\u666E\u901A\u6587\u4EF6\u6216\u8D85\u51FA\u5927\u5C0F\u9650\u5236\uFF1A${path}`);
2550
2618
  }
2551
- return readFile13(path);
2619
+ return readFile12(path);
2552
2620
  }
2553
2621
  async function writeOnce(path, bytes) {
2554
- const temporary = `${path}.${randomUUID6()}.tmp`;
2622
+ const temporary = `${path}.${randomUUID7()}.tmp`;
2555
2623
  await writeFile7(temporary, bytes, { flag: "wx", mode: 384 });
2556
2624
  try {
2557
2625
  await link2(temporary, path).catch((cause) => {
2558
2626
  if (cause.code !== "EEXIST") throw cause;
2559
2627
  });
2560
2628
  } finally {
2561
- await unlink6(temporary);
2629
+ await unlink7(temporary);
2562
2630
  }
2563
2631
  }
2564
- async function replaceFile(path, content) {
2565
- const temporary = `${path}.${randomUUID6()}.tmp`;
2632
+ async function replaceFile2(path, content) {
2633
+ const temporary = `${path}.${randomUUID7()}.tmp`;
2566
2634
  try {
2567
2635
  await writeFile7(temporary, content, { flag: "wx", mode: 384 });
2568
- await rename8(temporary, path);
2636
+ await rename9(temporary, path);
2569
2637
  } finally {
2570
- await unlink6(temporary).catch((error2) => {
2638
+ await unlink7(temporary).catch((error2) => {
2571
2639
  if (error2.code !== "ENOENT") throw error2;
2572
2640
  });
2573
2641
  }
@@ -2632,7 +2700,7 @@ async function prepareCreatorSkill(context, io, options = {}) {
2632
2700
  await writeOnce(sessionPath, JSON.stringify({
2633
2701
  schemaVersion: 1,
2634
2702
  platformBuddyId: context.buddyId,
2635
- creationKey: randomUUID6()
2703
+ creationKey: randomUUID7()
2636
2704
  }, null, 2) + "\n");
2637
2705
  const session = JSON.parse((await safeRead(sessionPath)).toString("utf8"));
2638
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)) {
@@ -2692,9 +2760,9 @@ async function prepareCreatorSkill(context, io, options = {}) {
2692
2760
  }
2693
2761
  await writeOnce(join13(root, `HANDOFF.${hash3(existing).slice(0, 12)}.bak.md`), existing);
2694
2762
  }
2695
- await replaceFile(lockPath, JSON.stringify({ ...selected.lock, ...existing ? { handoffSha256: hash3(existing) } : {} }, null, 2) + "\n");
2696
- await replaceFile(handoffPath, handoff2);
2697
- 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");
2698
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")}`);
2699
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`);
2700
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");
@@ -2759,7 +2827,7 @@ function validateBuddyMetaUpdate(meta2) {
2759
2827
 
2760
2828
  // packages/cli-core/src/init/implementation-guide.ts
2761
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";
2762
- function implementationGuide(selectedRuntime = false) {
2830
+ function implementationGuide() {
2763
2831
  return `## \u4ECE\u9700\u6C42\u624B\u518C\u843D\u5B9E\u5230\u4EE3\u7801
2764
2832
 
2765
2833
  ${IMPLEMENTATION_GUIDE_SUMMARY}
@@ -2786,12 +2854,14 @@ ${KNOWLEDGE_GUIDE}
2786
2854
 
2787
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
2788
2856
 
2789
- 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
2790
2858
 
2791
2859
  ### \u672C\u5730\u8C03\u8BD5\u7684\u9000\u51FA\u548C\u6E05\u7406
2792
2860
 
2793
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
2794
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
+
2795
2865
  ### \u4E3B\u52A8\u63D0\u9192\u4E0E\u6570\u636E\u6743\u9650
2796
2866
 
2797
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
@@ -2843,14 +2913,16 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
2843
2913
 
2844
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
2845
2915
 
2846
- \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
2847
2917
 
2848
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
2849
2919
 
2850
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
2851
2921
 
2852
- ${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"}
2853
- ${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
+
2854
2926
 
2855
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
2856
2928
 
@@ -2971,7 +3043,8 @@ var LoopbackBrowserLoginAdapter = class {
2971
3043
  #fetch;
2972
3044
  constructor(options) {
2973
3045
  this.#platformUrl = normalizePlatformUrl(options.platformUrl);
2974
- 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");
2975
3048
  this.#openBrowser = options.openBrowser ?? openExternalUrl;
2976
3049
  this.#onLoginUrl = options.onLoginUrl;
2977
3050
  this.#timeoutMs = positive(options.timeoutMs, DEFAULT_LOGIN_TIMEOUT_MS, "timeoutMs");
@@ -3142,10 +3215,11 @@ var CLI_HELP = `\u642D\u642D Developer Platform CLI
3142
3215
  --version \u67E5\u770B\u5F53\u524D CLI \u7248\u672C
3143
3216
 
3144
3217
  \u76F4\u63A5\u8FD0\u884C buddy-cli \u53EF\u8BC6\u522B\u5F53\u524D\u5DE5\u7A0B\u6216\u5F15\u5BFC\u521B\u5EFA\u3002
3145
- \u9ED8\u8BA4\u5E73\u53F0\uFF1A${DEFAULT_MLB_TEST_URL}\uFF1B\u5F00\u53D1\u8005\u540E\u53F0\uFF1A${DEFAULT_DEVELOPER_WEB_URL}\u3002
3146
- \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
3147
- \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
3148
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
3149
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
3150
3224
  \u53C2\u6570\u4E0E\u793A\u4F8B: buddy-cli <\u547D\u4EE4> --help\uFF0C\u4F8B\u5982 buddy-cli init --help\u3002
3151
3225
  Coding Agent \u5F00\u59CB\u5DE5\u4F5C\u524D\u8BF7\u8BFB\u53D6 buddy-cli guide\u3002`;
@@ -3177,9 +3251,9 @@ var GUIDE_HELP = `\u7528\u6CD5: buddy-cli guide
3177
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
3178
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`;
3179
3253
  function agentGuide(options = {}) {
3180
- return renderAgentGuide(allowsRuntimeVersionSelection(options));
3254
+ return renderAgentGuide();
3181
3255
  }
3182
- function renderAgentGuide(selectedRuntime = false) {
3256
+ function renderAgentGuide() {
3183
3257
  return `# Coding Agent \u5F00\u53D1\u6307\u5F15
3184
3258
 
3185
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
@@ -3188,11 +3262,7 @@ Skill \u7684\u5177\u4F53\u6D41\u7A0B\u8BFB\u53D6 HANDOFF.md \u4E2D\u7684\u6587\u
3188
3262
  ## \u51C6\u5907\u5B8C\u6210\u540E\uFF0C\u5F00\u59CB\u521B\u4F5C\u5BF9\u8BDD
3189
3263
 
3190
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
3191
- ${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
3192
- \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
3193
- \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
3194
- \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
3195
- ` : ""}
3265
+
3196
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
3197
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
3198
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
@@ -3200,7 +3270,7 @@ ${selectedRuntime ? `\u5F53\u524D\u7EC8\u7AEF\u914D\u7F6E\u4E86\u81EA\u5B9A\u4E4
3200
3270
 
3201
3271
  ## CLI \u7248\u672C\u4E0E\u6267\u884C\u89C4\u5219
3202
3272
 
3203
- \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
3204
3274
 
3205
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
3206
3276
 
@@ -3229,59 +3299,25 @@ Coding Agent \u5E94\u4F20\u5165\u6309\u4E0A\u8FF0\u89C4\u5219\u786E\u5B9A\u7684\
3229
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
3230
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
3231
3301
 
3232
- ${implementationGuide(selectedRuntime)}
3302
+ ${implementationGuide()}
3233
3303
 
3234
3304
  ${DEVELOPMENT_HANDOFF}`;
3235
3305
  }
3236
3306
  var AGENT_GUIDE = renderAgentGuide();
3237
- function initHelp(options = {}) {
3238
- return allowsRuntimeVersionSelection(options) ? `${INIT_HELP}
3239
- \u5F53\u524D\u73AF\u5883\u7684 Runtime \u7248\u672C\u9009\u62E9\uFF1A
3240
- --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
3241
- \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;
3242
3309
  }
3243
- function cliHelp(options = {}) {
3244
- 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;
3245
3312
  }
3246
3313
 
3247
3314
  // packages/cli-core/src/dev/local-stop.ts
3248
3315
  import { execFile as execFile5 } from "node:child_process";
3249
3316
  import { promisify as promisify5 } from "node:util";
3250
- 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";
3251
3318
  import { join as join15 } from "node:path";
3252
3319
  import { setTimeout as delay } from "node:timers/promises";
3253
3320
 
3254
- // packages/cli-core/src/dev/errors.ts
3255
- var BuddyDevError = class extends Error {
3256
- /** Only explicitly safe, developer-facing explanations may be shown in Preview. */
3257
- publicMessage;
3258
- code;
3259
- phase;
3260
- retryable;
3261
- constructor(options) {
3262
- super(options.message, options.cause === void 0 ? void 0 : { cause: options.cause });
3263
- this.name = "BuddyDevError";
3264
- this.publicMessage = options.publicMessage;
3265
- this.code = options.code;
3266
- this.phase = options.phase;
3267
- this.retryable = options.retryable ?? false;
3268
- }
3269
- };
3270
- function isAbortLike(error2) {
3271
- return error2 instanceof DOMException && error2.name === "AbortError" || error2 instanceof Error && error2.name === "AbortError";
3272
- }
3273
- function abortedDevError(signal) {
3274
- return new BuddyDevError({
3275
- code: "DEV_ABORTED",
3276
- phase: "stop",
3277
- message: "\u642D\u642D DEV \u542F\u52A8\u5DF2\u53D6\u6D88\u3002",
3278
- ...signal?.reason === void 0 ? {} : { cause: signal.reason }
3279
- });
3280
- }
3281
- function throwIfDevAborted(signal) {
3282
- if (signal?.aborted) throw abortedDevError(signal);
3283
- }
3284
-
3285
3321
  // packages/cli-core/src/dev/process.ts
3286
3322
  import { promisify as promisify4 } from "node:util";
3287
3323
  import { spawn as spawnChild, execFile as execFile4 } from "node:child_process";
@@ -3579,7 +3615,7 @@ async function stopLocalDev(options) {
3579
3615
  }
3580
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");
3581
3617
  const ownerPath = join15(path, names[0]);
3582
- const source = await readFile14(ownerPath, "utf8");
3618
+ const source = await readFile13(ownerPath, "utf8");
3583
3619
  const owner = JSON.parse(source);
3584
3620
  if (!validPid2(owner.pid) || owner.runtimePid !== void 0 && !validPid2(owner.runtimePid)) throw failure("DEV \u9501\u4E2D\u7684 PID \u65E0\u6548\u3002");
3585
3621
  const root = await realpath5(options.projectRoot);
@@ -3607,7 +3643,7 @@ async function stopLocalDev(options) {
3607
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);
3608
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`);
3609
3645
  }
3610
- 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");
3611
3647
  try {
3612
3648
  process.kill(-pid, "SIGTERM");
3613
3649
  } catch (error2) {
@@ -3634,7 +3670,7 @@ async function stopLocalDev(options) {
3634
3670
  }
3635
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`);
3636
3672
  try {
3637
- if (await readFile14(ownerPath, "utf8") === source) await unlink7(ownerPath);
3673
+ if (await readFile13(ownerPath, "utf8") === source) await unlink8(ownerPath);
3638
3674
  } catch (error2) {
3639
3675
  if (error2.code !== "ENOENT") throw error2;
3640
3676
  }
@@ -3644,140 +3680,6 @@ async function stopLocalDev(options) {
3644
3680
  return { stopped: true };
3645
3681
  }
3646
3682
 
3647
- // packages/cli-core/src/dev/project-env.ts
3648
- import { constants } from "node:fs";
3649
- import { open as open4, rename as rename9, unlink as unlink8 } from "node:fs/promises";
3650
- import { randomUUID as randomUUID7 } from "node:crypto";
3651
- import { join as join16 } from "node:path";
3652
- import { parseEnv } from "node:util";
3653
- function invalid(message) {
3654
- return new BuddyDevError({ code: "DEV_CONFIG_INVALID", phase: "config", message, publicMessage: message });
3655
- }
3656
- async function readLocalFile(path) {
3657
- let file;
3658
- try {
3659
- file = await open4(path, constants.O_RDONLY | constants.O_NOFOLLOW);
3660
- const stat2 = await file.stat();
3661
- 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");
3662
- return await file.readFile("utf8");
3663
- } catch (cause) {
3664
- if (cause.code === "ENOENT") return "";
3665
- if (cause instanceof BuddyDevError) throw cause;
3666
- 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");
3667
- } finally {
3668
- await file?.close();
3669
- }
3670
- }
3671
- async function readProjectEnvironment(projectRoot) {
3672
- const source = await readLocalFile(join16(projectRoot, ".env"));
3673
- let values;
3674
- try {
3675
- values = parseEnv(source);
3676
- } catch {
3677
- throw invalid("\u5DE5\u7A0B .env \u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002");
3678
- }
3679
- return values;
3680
- }
3681
- function gatewayNeedsRefresh(value, gatewayUrl) {
3682
- if (value) {
3683
- if (isLegacyEcsGateway(value)) {
3684
- if (gatewayUrl.href === `${DEFAULT_MLB_TEST_URL}/`) return true;
3685
- throw invalid(".env \u4FDD\u5B58\u7684\u662F\u65E7\u516C\u5171\u73AF\u5883\u5730\u5740\uFF0C\u4E0E\u672C\u6B21\u5E73\u53F0\u4E0D\u540C\uFF1B\u8BF7\u786E\u8BA4\u76EE\u6807\u5E73\u53F0\u540E\u4F7F\u7528 --refresh-token \u66F4\u65B0\u8FDE\u63A5\u914D\u7F6E\u3002");
3686
- }
3687
- let gateway;
3688
- try {
3689
- gateway = normalizePlatformUrl(value);
3690
- } catch {
3691
- 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");
3692
- }
3693
- if (gateway.href !== gatewayUrl.href) throw invalid(".env \u7684\u5E73\u53F0\u5730\u5740\u4E0E\u672C\u6B21\u542F\u52A8\u4E0D\u540C\uFF1B\u8BF7\u786E\u8BA4\u76EE\u6807\u5E73\u53F0\uFF0C\u6216\u5728\u660E\u786E\u5207\u6362\u5E73\u53F0\u65F6\u4F7F\u7528 --refresh-token \u66F4\u65B0\u8FDE\u63A5\u914D\u7F6E\u3002");
3694
- }
3695
- return false;
3696
- }
3697
- async function checkProjectGateway(projectRoot, gatewayUrl, options = {}) {
3698
- const values = await readProjectEnvironment(projectRoot);
3699
- if (!options.refreshToken && gatewayNeedsRefresh(values.MLB_GATEWAY_URL, gatewayUrl)) {
3700
- 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");
3701
- }
3702
- }
3703
- async function projectBuddyToken(projectRoot, gatewayUrl) {
3704
- const values = await readProjectEnvironment(projectRoot);
3705
- if (gatewayNeedsRefresh(values.MLB_GATEWAY_URL, gatewayUrl) || !values.BUDDY_TOKEN) return void 0;
3706
- 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");
3707
- return values.BUDDY_TOKEN;
3708
- }
3709
- function quote(value) {
3710
- if (/[\u0000-\u001f\u007f]/u.test(value)) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26\u3002");
3711
- const delimiter = ["'", '"', "`"].find((character) => !value.includes(character));
3712
- if (!delimiter) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u5305\u542B\u65E0\u6CD5\u5199\u5165 .env \u7684\u5F15\u53F7\u7EC4\u5408\u3002");
3713
- return `${delimiter}${value}${delimiter}`;
3714
- }
3715
- function updateValues(source, values) {
3716
- const assignment = /^[\t ]*(?:export[\t ]+)?([A-Za-z_][A-Za-z0-9_]*)[\t ]*=[\t ]*/gm;
3717
- let output = "", cursor = 0, match;
3718
- const written = /* @__PURE__ */ new Set();
3719
- while (match = assignment.exec(source)) {
3720
- const valueStart = assignment.lastIndex;
3721
- let end = source.indexOf("\n", valueStart);
3722
- if (end < 0) end = source.length;
3723
- let commentStart = valueStart;
3724
- const delimiter = source[valueStart];
3725
- if (delimiter && ["'", '"', "`"].includes(delimiter)) {
3726
- const close = source.indexOf(delimiter, valueStart + 1);
3727
- if (close < 0) throw invalid(".env \u4E2D\u6709\u672A\u95ED\u5408\u7684\u5F15\u53F7\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002");
3728
- commentStart = close + 1;
3729
- end = source.indexOf("\n", close + 1);
3730
- if (end < 0) end = source.length;
3731
- }
3732
- assignment.lastIndex = end;
3733
- const name = match[1];
3734
- if (!(name in values)) continue;
3735
- const comment = source.slice(commentStart, end).match(/[\t ]*#[^\r\n]*/u)?.[0] ?? "";
3736
- output += source.slice(cursor, match.index);
3737
- output += written.has(name) || values[name] === void 0 ? comment : `${name}=${quote(values[name])}${comment ? ` ${comment.trimStart()}` : ""}`;
3738
- if (source[end - 1] === "\r") output += "\r";
3739
- cursor = end;
3740
- written.add(name);
3741
- }
3742
- output += source.slice(cursor);
3743
- const newline = source.includes("\r\n") ? "\r\n" : "\n";
3744
- for (const [name, value] of Object.entries(values)) if (value !== void 0 && !written.has(name)) {
3745
- if (output && !output.endsWith("\n")) output += newline;
3746
- output += `${name}=${quote(value)}${newline}`;
3747
- }
3748
- const parsed = parseEnv(output);
3749
- 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");
3750
- return output;
3751
- }
3752
- async function replaceFile2(path, contents, mode) {
3753
- const temporary = `${path}.${randomUUID7()}.tmp`;
3754
- let file;
3755
- try {
3756
- file = await open4(temporary, "wx", mode);
3757
- await file.writeFile(contents, "utf8");
3758
- await file.sync();
3759
- await file.close();
3760
- file = void 0;
3761
- await rename9(temporary, path);
3762
- } finally {
3763
- await file?.close();
3764
- await unlink8(temporary).catch((cause) => {
3765
- if (cause.code !== "ENOENT") throw cause;
3766
- });
3767
- }
3768
- }
3769
- async function writeProjectEnvironment(projectRoot, values) {
3770
- const envPath = join16(projectRoot, ".env"), ignorePath = join16(projectRoot, ".gitignore");
3771
- const contents = updateValues(await readLocalFile(envPath), { ...values, BUDDY_ID: void 0 });
3772
- const ignored = await readLocalFile(ignorePath);
3773
- if (ignored.trimEnd().split(/\r?\n/u).at(-1) !== "/.env") {
3774
- await replaceFile2(ignorePath, `${ignored}${ignored && !ignored.endsWith("\n") ? "\n" : ""}/.env
3775
- `, 420);
3776
- }
3777
- await replaceFile2(envPath, contents, 384);
3778
- return contents;
3779
- }
3780
-
3781
3683
  // packages/cli-core/src/commands/dev.ts
3782
3684
  import { resolve as resolve14 } from "node:path";
3783
3685
 
@@ -3811,7 +3713,8 @@ async function responseJson(response) {
3811
3713
  throw new BuddyDevError({
3812
3714
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3813
3715
  phase: "registration",
3814
- 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"
3815
3718
  });
3816
3719
  }
3817
3720
  parts.push(decoder.decode(item.value, { stream: true }));
@@ -3829,6 +3732,7 @@ async function responseJson(response) {
3829
3732
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3830
3733
  phase: "registration",
3831
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`,
3832
3736
  cause
3833
3737
  });
3834
3738
  }
@@ -3838,6 +3742,13 @@ function safeServerError(value, fallback) {
3838
3742
  if (typeof candidate !== "string" || !candidate.trim()) return fallback;
3839
3743
  return candidate.slice(0, 1024).replace(/[\u0000-\u001f\u007f]/gu, " ");
3840
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
+ }
3841
3752
  var MlbDevRegistrationClient = class {
3842
3753
  #baseUrl;
3843
3754
  #developerToken;
@@ -3884,7 +3795,8 @@ var MlbDevRegistrationClient = class {
3884
3795
  throw new BuddyDevError({
3885
3796
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3886
3797
  phase: "registration",
3887
- 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"
3888
3800
  });
3889
3801
  }
3890
3802
  let body;
@@ -3896,6 +3808,7 @@ var MlbDevRegistrationClient = class {
3896
3808
  code: "DEV_APP_SERVER_HTTP_ERROR",
3897
3809
  phase: "registration",
3898
3810
  message: `DEV App Server \u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${response.status}\uFF09\u3002`,
3811
+ publicMessage: httpFailureMessage(response.status),
3899
3812
  retryable: response.status === 408 || response.status === 429 || response.status >= 500,
3900
3813
  cause
3901
3814
  });
@@ -3907,7 +3820,7 @@ var MlbDevRegistrationClient = class {
3907
3820
  code: "DEV_APP_SERVER_HTTP_ERROR",
3908
3821
  phase: "registration",
3909
3822
  message: safeServerError(body, `DEV App Server \u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${response.status}\uFF09\u3002`),
3910
- publicMessage: response.status === 401 ? "\u642D\u642D\u8D26\u53F7\u767B\u5F55\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C buddy-cli login\u3002" : response.status === 403 ? "\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" : response.status === 404 ? "\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" : void 0,
3823
+ publicMessage: httpFailureMessage(response.status),
3911
3824
  retryable: response.status === 408 || response.status === 429 || response.status >= 500
3912
3825
  });
3913
3826
  }
@@ -3922,7 +3835,7 @@ var MlbDevRegistrationClient = class {
3922
3835
  });
3923
3836
  }
3924
3837
  options.signal.throwIfAborted();
3925
- if (request.projectRoot) await readProjectEnvironment(request.projectRoot);
3838
+ if (request.projectRoot) await checkProjectGateway(request.projectRoot, this.#baseUrl);
3926
3839
  const localToken = request.projectRoot && !this.#refreshToken ? await projectBuddyToken(request.projectRoot, this.#baseUrl) : void 0;
3927
3840
  const store = request.projectRoot ? void 0 : this.#tokenStoreFor?.(request.devAgentId);
3928
3841
  const cached2 = this.#refreshToken ? void 0 : await store?.load();
@@ -3969,19 +3882,22 @@ var MlbDevRegistrationClient = class {
3969
3882
  throw new BuddyDevError({
3970
3883
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3971
3884
  phase: "registration",
3972
- 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"
3973
3887
  });
3974
3888
  }
3975
3889
  const states = body.online.flatMap((item, index) => {
3976
- 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") {
3977
3892
  throw new BuddyDevError({
3978
3893
  code: "DEV_APP_SERVER_RESPONSE_INVALID",
3979
3894
  phase: "registration",
3980
- 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`
3981
3897
  });
3982
3898
  }
3983
- if (!item.endsWith("-dev")) return [];
3984
- const devAgentId = item.slice(0, -4);
3899
+ if (!id.endsWith("-dev")) return [];
3900
+ const devAgentId = id.slice(0, -4);
3985
3901
  return [Object.freeze({ devAgentId, online: true })];
3986
3902
  });
3987
3903
  return Object.freeze(states);
@@ -4053,23 +3969,24 @@ function buildAgentEnvironment(options) {
4053
3969
 
4054
3970
  // packages/cli-core/src/dev/orchestrator.ts
4055
3971
  import { createHash as createHash7 } from "node:crypto";
4056
- import { readFile as readFile18 } from "node:fs/promises";
4057
- 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";
4058
3975
 
4059
3976
  // packages/cli-core/src/dev/reload.ts
4060
3977
  import { watch } from "node:fs";
4061
3978
  import { createHash as createHash6 } from "node:crypto";
4062
- import { readFile as readFile15, readdir as readdir5 } from "node:fs/promises";
4063
- 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";
4064
3981
  import { setTimeout as sleep } from "node:timers/promises";
4065
3982
  var digest2 = (contents) => createHash6("sha256").update(contents).digest("hex");
4066
3983
  async function snapshot(root, prefix = "", result = /* @__PURE__ */ new Map()) {
4067
- for (const entry2 of await readdir5(join17(root, prefix), { withFileTypes: true })) {
3984
+ for (const entry2 of await readdir5(join16(root, prefix), { withFileTypes: true })) {
4068
3985
  const path = prefix ? `${prefix}/${entry2.name}` : entry2.name;
4069
3986
  if (!relevant(path)) continue;
4070
3987
  try {
4071
3988
  if (entry2.isDirectory()) await snapshot(root, path, result);
4072
- 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))));
4073
3990
  } catch (cause) {
4074
3991
  if (cause.code !== "ENOENT") throw cause;
4075
3992
  }
@@ -4159,7 +4076,7 @@ var ReloadingDevSession = class {
4159
4076
  const path = String(name);
4160
4077
  if (!relevant(path)) return;
4161
4078
  if (path === ".env") {
4162
- void readFile15(join17(this.projectRoot, path), "utf8").then((contents) => {
4079
+ void readFile14(join16(this.projectRoot, path), "utf8").then((contents) => {
4163
4080
  if (contents !== this.#environment) {
4164
4081
  this.#environment = contents;
4165
4082
  this.#changed();
@@ -4342,7 +4259,7 @@ function startReloadingDev(options, startProcess) {
4342
4259
  }
4343
4260
 
4344
4261
  // packages/cli-core/src/config/runtime-policy.ts
4345
- import { readFile as readFile16, realpath as realpath6 } from "node:fs/promises";
4262
+ import { readFile as readFile15, realpath as realpath6 } from "node:fs/promises";
4346
4263
  import { createRequire as createRequire2 } from "node:module";
4347
4264
  import { resolve as resolve10 } from "node:path";
4348
4265
  var RuntimeRequirementError = class extends Error {
@@ -4370,26 +4287,23 @@ function assertNpmRuntimeLock(contents, expected) {
4370
4287
  }
4371
4288
  }
4372
4289
  async function requireProjectRuntime(root, options = {}) {
4373
- const selected = allowsRuntimeVersionSelection(options);
4374
- const declared = await projectRuntimeVersion(root);
4375
- 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");
4376
4290
  let expected;
4377
4291
  try {
4378
- expected = selected ? await resolveRuntimeVersion(declared, options) : await latestRuntimeVersion(options);
4292
+ expected = await latestRuntimeVersion(options);
4379
4293
  } catch (cause) {
4380
4294
  options.signal?.throwIfAborted();
4381
- 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 });
4382
4296
  }
4383
4297
  try {
4384
4298
  assertRequiredRuntime(await projectRuntimeVersion(root), expected);
4385
4299
  const installedPath = await realpath6(resolve10(root, "node_modules", BUDDY_RUNTIME_PACKAGE, "package.json"));
4386
4300
  const fromProject = createRequire2(resolve10(root, "package.json")).resolve(`${BUDDY_RUNTIME_PACKAGE}/package.json`);
4387
4301
  if (await realpath6(fromProject) !== installedPath) throw new Error("Runtime \u5FC5\u987B\u5B89\u88C5\u5728\u5F53\u524D\u5DE5\u7A0B\u4E2D");
4388
- const installed2 = JSON.parse(await readFile16(installedPath, "utf8"));
4302
+ const installed2 = JSON.parse(await readFile15(installedPath, "utf8"));
4389
4303
  if (installed2.version !== expected) throw new Error(`Runtime \u5B9E\u9645\u5B89\u88C5 ${installed2.version}\uFF0C\u8981\u6C42 ${expected}`);
4390
4304
  let lock;
4391
4305
  try {
4392
- lock = await readFile16(resolve10(root, "package-lock.json"), "utf8");
4306
+ lock = await readFile15(resolve10(root, "package-lock.json"), "utf8");
4393
4307
  } catch (cause) {
4394
4308
  if (cause.code !== "ENOENT") throw cause;
4395
4309
  }
@@ -4409,8 +4323,8 @@ import { createRequire as createRequire3 } from "node:module";
4409
4323
  import { dirname as dirname4, resolve as resolve11 } from "node:path";
4410
4324
 
4411
4325
  // packages/cli-core/src/config/data-access.ts
4412
- import { lstat as lstat10, readFile as readFile17 } from "node:fs/promises";
4413
- 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";
4414
4328
  var DATA_ACCESS_FILENAME = "data-access.json";
4415
4329
  function parseDataAccessRequirements(source) {
4416
4330
  if (source === void 0) return [];
@@ -4438,10 +4352,10 @@ function parseDataAccessRequirements(source) {
4438
4352
  });
4439
4353
  }
4440
4354
  async function readDataAccessRequirements(projectRoot) {
4441
- const path = join18(projectRoot, DATA_ACCESS_FILENAME);
4355
+ const path = join17(projectRoot, DATA_ACCESS_FILENAME);
4442
4356
  try {
4443
4357
  if (!(await lstat10(path)).isFile()) throw new Error(`${DATA_ACCESS_FILENAME} \u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6`);
4444
- return parseDataAccessRequirements(await readFile17(path, "utf8"));
4358
+ return parseDataAccessRequirements(await readFile16(path, "utf8"));
4445
4359
  } catch (cause) {
4446
4360
  if (cause.code === "ENOENT") return [];
4447
4361
  throw cause;
@@ -4597,6 +4511,7 @@ async function waitForAgentOnline(options) {
4597
4511
  code: "DEV_AGENT_ONLINE_TIMEOUT",
4598
4512
  phase: "online",
4599
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",
4600
4515
  retryable: true,
4601
4516
  ...lastError === void 0 ? {} : { cause: lastError }
4602
4517
  });
@@ -4615,12 +4530,13 @@ async function waitForAgentOnline(options) {
4615
4530
  await delay2(Math.min(options.pollIntervalMs, Math.max(1, deadline - Date.now())), options.signal);
4616
4531
  }
4617
4532
  }
4618
- function agentExitedError(exit, stderr = "") {
4533
+ function agentExitedError(exit, diagnostics = "") {
4619
4534
  const detail = exit.error !== void 0 ? exit.error.message : exit.signal !== null ? `signal ${exit.signal}` : `exit code ${exit.code ?? "unknown"}`;
4620
4535
  return new BuddyDevError({
4621
4536
  code: "DEV_AGENT_EXITED",
4622
4537
  phase: "running",
4623
- 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),
4624
4540
  ...exit.error === void 0 ? {} : { cause: exit.error }
4625
4541
  });
4626
4542
  }
@@ -4636,6 +4552,7 @@ var ReadyBuddyDevHandle = class {
4636
4552
  #lifecycle;
4637
4553
  #stopGracePeriodMs;
4638
4554
  #onStateChange;
4555
+ #failureDetail;
4639
4556
  #signal;
4640
4557
  #onAbort;
4641
4558
  #state = "ready";
@@ -4653,6 +4570,7 @@ var ReadyBuddyDevHandle = class {
4653
4570
  this.#stopGracePeriodMs = options.stopGracePeriodMs;
4654
4571
  this.#signal = options.signal;
4655
4572
  this.#onStateChange = options.onStateChange;
4573
+ this.#failureDetail = options.failureDetail;
4656
4574
  this.#onAbort = () => {
4657
4575
  void this.stop().catch(() => void 0);
4658
4576
  };
@@ -4663,7 +4581,7 @@ var ReadyBuddyDevHandle = class {
4663
4581
  else options.signal?.addEventListener("abort", this.#onAbort, { once: true });
4664
4582
  this.#emit("ready");
4665
4583
  void this.#process.exit.then(async (exit) => {
4666
- if (this.#state === "ready") await this.#fail(agentExitedError(exit));
4584
+ if (this.#state === "ready") await this.#fail(agentExitedError(exit, this.#failureDetail()));
4667
4585
  });
4668
4586
  }
4669
4587
  get state() {
@@ -4745,12 +4663,35 @@ async function startBuddyDevProcess(options, hooks) {
4745
4663
  let agentProcess;
4746
4664
  let processTree;
4747
4665
  let instanceLock;
4748
- let stderr = "";
4666
+ const output = { stdout: "", stderr: "" };
4667
+ const truncated = { stdout: false, stderr: false };
4749
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
+ };
4750
4675
  const failureDetail = () => {
4751
- let text2 = stderr;
4752
- for (const secret of secrets) if (secret) text2 = text2.split(secret).join("[REDACTED]");
4753
- 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);
4754
4695
  };
4755
4696
  const emit = (state2) => {
4756
4697
  try {
@@ -4764,7 +4705,7 @@ async function startBuddyDevProcess(options, hooks) {
4764
4705
  let config;
4765
4706
  let configSource;
4766
4707
  try {
4767
- configSource = await readFile18(join19(projectRoot, BUDDY_PACKAGE_FILENAME), "utf8");
4708
+ configSource = await readFile17(join18(projectRoot, BUDDY_PACKAGE_FILENAME), "utf8");
4768
4709
  config = combineBuddyProject(parseBuddyAgentConfig(configSource));
4769
4710
  } catch (cause) {
4770
4711
  throw new BuddyDevError({
@@ -4776,7 +4717,7 @@ async function startBuddyDevProcess(options, hooks) {
4776
4717
  }
4777
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" });
4778
4719
  const projectEnv = await readProjectEnvironment(projectRoot);
4779
- 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 ?? "");
4780
4721
  const launchPlan = await launchPlanFor(config, options, projectRoot, signal);
4781
4722
  const registration = await registerDevAgent({
4782
4723
  projectRoot,
@@ -4817,11 +4758,8 @@ async function startBuddyDevProcess(options, hooks) {
4817
4758
  env: childEnvironment,
4818
4759
  shell: false,
4819
4760
  detached: platform === "darwin",
4820
- onStdout: (text2) => options.onLog?.({ source: "agent.stdout", text: text2 }),
4821
- onStderr: (text2) => {
4822
- stderr = (stderr + text2).slice(-16384);
4823
- options.onLog?.({ source: "agent.stderr", text: text2 });
4824
- }
4761
+ onStdout: (text2) => capture2("stdout", text2),
4762
+ onStderr: (text2) => capture2("stderr", text2)
4825
4763
  });
4826
4764
  await instanceLock.attachRuntime(agentProcess.pid);
4827
4765
  const exited = agentProcess.exit.then((exit) => {
@@ -4848,6 +4786,7 @@ async function startBuddyDevProcess(options, hooks) {
4848
4786
  instanceLock,
4849
4787
  lifecycle,
4850
4788
  stopGracePeriodMs,
4789
+ failureDetail,
4851
4790
  ...options.signal === void 0 ? {} : { signal: options.signal },
4852
4791
  ...options.onStateChange === void 0 ? {} : { onStateChange: options.onStateChange }
4853
4792
  });
@@ -5093,12 +5032,12 @@ var DEV_COMMAND_HELP = `\u7528\u6CD5:
5093
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
5094
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
5095
5034
  \u672A\u914D\u7F6E\u5730\u5740\u65F6\u8FDE\u63A5 MLB \u6D4B\u8BD5\u73AF\u5883 ${DEFAULT_MLB_TEST_URL}\uFF08HTTPS\uFF09\u3002
5096
- 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
5097
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
5098
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
5099
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
5100
5039
  \u8EAB\u4EFD\u53EA\u8BFB\u53D6 package.json.buddyId\uFF0C.env \u4E0D\u9700\u8981 BUDDY_ID\u3002
5101
- --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`;
5102
5041
  function valueAfter(args, index, flag2) {
5103
5042
  const value = args[index + 1];
5104
5043
  if (value === void 0 || !value.trim()) throw new DevCommandUsageError(`${flag2} \u7F3A\u5C11\u503C`);
@@ -5153,7 +5092,7 @@ function parseDevArguments(args) {
5153
5092
  }
5154
5093
  function appServerUrl(override, env) {
5155
5094
  try {
5156
- return resolvePlatformUrl({ override, env, development: true });
5095
+ return resolvePlatformUrl({ override, env });
5157
5096
  } catch (cause) {
5158
5097
  throw new DevCommandUsageError(`App Server \u5730\u5740\u65E0\u6548\uFF1A${cause instanceof Error ? cause.message : "\u4E0D\u662F\u6709\u6548 URL"}`);
5159
5098
  }
@@ -5190,7 +5129,7 @@ async function runDevCommand(args, io, options = {}) {
5190
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");
5191
5130
  return { exitCode: 0 };
5192
5131
  }
5193
- await checkProjectGateway(root, url, { refreshToken: parsed.refreshToken, report: (message) => io.write(message) });
5132
+ await checkProjectGateway(root, url, { report: (message) => io.write(message) });
5194
5133
  const authorizationInput = { appServerUrl: url, ...parsed.refreshToken ? { refreshToken: true } : {} };
5195
5134
  if (!options.authorize) {
5196
5135
  throw new DevCommandUsageError("\u5F53\u524D CLI Host \u5C1A\u672A\u914D\u7F6E\u642D\u642D\u8D26\u53F7\u767B\u5F55 Adapter");
@@ -5202,7 +5141,7 @@ async function runDevCommand(args, io, options = {}) {
5202
5141
  startDev: options.startDev ?? startBuddyDev
5203
5142
  });
5204
5143
  const handle = await starter.start({
5205
- runtimeUpdate: { ...options.runtimeUpdate, env: environment, platformUrl: url },
5144
+ runtimeUpdate: { ...options.runtimeUpdate, env: environment },
5206
5145
  projectRoot: root,
5207
5146
  registrationClient,
5208
5147
  ...options.signal === void 0 ? {} : { signal: options.signal },
@@ -5950,6 +5889,7 @@ async function runLogout(io, options) {
5950
5889
  }
5951
5890
  async function runPush(parsed, io, options) {
5952
5891
  const root = await (options.resolveProjectRoot ?? requireBuddyAgentProjectRoot)(requestedDirectory(options, parsed));
5892
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
5953
5893
  const config = await (options.readConfig ?? readBuddyConfig)(root);
5954
5894
  const commit = await pushCommit(parsed, io);
5955
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");
@@ -6015,6 +5955,7 @@ async function runMeta(parsed, io, options, legacyAvatar = false) {
6015
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");
6016
5956
  if (id === void 0) {
6017
5957
  const root = await (options.resolveProjectRoot ?? requireBuddyProjectRoot)(requestedDirectory(options, parsed));
5958
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
6018
5959
  id = (await (options.readManifest ?? readBuddyProjectManifest)(root)).buddyId;
6019
5960
  }
6020
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");
@@ -6064,6 +6005,7 @@ async function runCloudCommand(command, args, io, options = {}) {
6064
6005
  if (command === "push") return await runPush(parsed, io, options);
6065
6006
  if (command === "meta" || command === "avatar") return await runMeta(parsed, io, options, command === "avatar");
6066
6007
  const root = await (options.resolveProjectRoot ?? requireBuddyProjectRoot)(requestedDirectory(options, parsed));
6008
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeUpdate?.env }));
6067
6009
  const manifest = await (options.readManifest ?? readBuddyProjectManifest)(root);
6068
6010
  if (options.mode === "local-mock") {
6069
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");
@@ -6077,7 +6019,7 @@ async function runCloudCommand(command, args, io, options = {}) {
6077
6019
  printStatus(io, buddy2, packages);
6078
6020
  return { exitCode: 0, buddyId: buddy2.id };
6079
6021
  } catch (cause) {
6080
- 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) {
6081
6023
  io.writeError(`buddy-cli: ${cause.message}`);
6082
6024
  if (cause instanceof CloudLifecycleError || cause instanceof RuntimeRequirementError || cause instanceof PushPreflightError) io.writeError(`\u9519\u8BEF\u7801\uFF1A${cause.code}`);
6083
6025
  return {
@@ -6091,7 +6033,7 @@ var CLOUD_COMMAND_HELP = HELP;
6091
6033
 
6092
6034
  // packages/cli-core/src/migration/index.ts
6093
6035
  import { lstat as lstat11, open as open5, readdir as readdir6, realpath as realpath7, stat } from "node:fs/promises";
6094
- 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";
6095
6037
  var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
6096
6038
  maxFiles: 128,
6097
6039
  maxFileBytes: 256 * 1024,
@@ -6260,7 +6202,7 @@ async function existingProjectRoot(value) {
6260
6202
  }
6261
6203
  }
6262
6204
  async function existingSkillRoot(projectRoot, skillPath) {
6263
- const candidate = skillPath === "." ? projectRoot : join20(projectRoot, ...skillPath.split("/"));
6205
+ const candidate = skillPath === "." ? projectRoot : join19(projectRoot, ...skillPath.split("/"));
6264
6206
  try {
6265
6207
  await lstat11(candidate);
6266
6208
  } catch (cause) {
@@ -6297,7 +6239,7 @@ async function existingSkillRoot(projectRoot, skillPath) {
6297
6239
  }
6298
6240
  async function assertEntrypoint(context) {
6299
6241
  const entryPath = reportChild(context.skillPath, "SKILL.md");
6300
- const candidate = join20(context.skillRoot, "SKILL.md");
6242
+ const candidate = join19(context.skillRoot, "SKILL.md");
6301
6243
  try {
6302
6244
  await lstat11(candidate);
6303
6245
  const target = await realpath7(candidate);
@@ -6401,7 +6343,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
6401
6343
  }
6402
6344
  for (const entry2 of entries) {
6403
6345
  const childReportPath = reportChild(reportDirectory, entry2.name);
6404
- const childPath = join20(directory, entry2.name);
6346
+ const childPath = join19(directory, entry2.name);
6405
6347
  let target;
6406
6348
  try {
6407
6349
  target = await realpath7(childPath);
@@ -6857,7 +6799,7 @@ async function scanExternalSkillPortability(options) {
6857
6799
  // packages/cli-core/src/push/preflight.ts
6858
6800
  import { createHash as createHash10 } from "node:crypto";
6859
6801
  import { lstat as lstat12, open as open6, readdir as readdir7, realpath as realpath8 } from "node:fs/promises";
6860
- 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";
6861
6803
  var MEBIBYTE = 1024 * 1024;
6862
6804
  var DEFAULT_PUSH_MANIFEST_LIMITS = Object.freeze({
6863
6805
  maxFiles: 1e4,
@@ -7062,7 +7004,7 @@ async function canonicalProjectRoot(projectRoot) {
7062
7004
  }
7063
7005
  }
7064
7006
  async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
7065
- const path = join21(projectRoot, filename);
7007
+ const path = join20(projectRoot, filename);
7066
7008
  let entry2;
7067
7009
  try {
7068
7010
  entry2 = await lstat12(path);
@@ -7265,7 +7207,7 @@ async function createManifest(options) {
7265
7207
  sensitiveEntriesExcluded += 1;
7266
7208
  continue;
7267
7209
  }
7268
- const absolutePath = join21(directory, name);
7210
+ const absolutePath = join20(directory, name);
7269
7211
  let entry2;
7270
7212
  try {
7271
7213
  entry2 = await lstat12(absolutePath);
@@ -7519,7 +7461,7 @@ async function assertCapturedConfigStable(options) {
7519
7461
  }
7520
7462
  let current;
7521
7463
  try {
7522
- const path = join21(options.projectRoot, options.filename);
7464
+ const path = join20(options.projectRoot, options.filename);
7523
7465
  const entry2 = await lstat12(path);
7524
7466
  if (!entry2.isFile() || entry2.isSymbolicLink()) {
7525
7467
  error({
@@ -7565,7 +7507,7 @@ async function createPushPreflight(options) {
7565
7507
  parseCapturedProject(initialAgentEntry);
7566
7508
  let initialDataEntry;
7567
7509
  try {
7568
- await lstat12(join21(projectRoot, DATA_ACCESS_FILENAME));
7510
+ await lstat12(join20(projectRoot, DATA_ACCESS_FILENAME));
7569
7511
  initialDataEntry = await captureConfigWithinLimit(projectRoot, limits.maxFileBytes, DATA_ACCESS_FILENAME);
7570
7512
  } catch (cause) {
7571
7513
  if (cause.code !== "ENOENT") throw cause;
@@ -7667,8 +7609,8 @@ async function createPushPreflight(options) {
7667
7609
 
7668
7610
  // packages/cli-core/src/push/bundle.ts
7669
7611
  import { createHash as createHash11 } from "node:crypto";
7670
- import { lstat as lstat13, readFile as readFile19, realpath as realpath9 } from "node:fs/promises";
7671
- 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";
7672
7614
  import { Writable } from "node:stream";
7673
7615
  import { pipeline } from "node:stream/promises";
7674
7616
  import { createGzip } from "node:zlib";
@@ -7690,7 +7632,7 @@ function inside(root, target) {
7690
7632
  return path === "" || path !== ".." && !path.startsWith(`..${sep3}`) && !path.startsWith("/") && !win324.isAbsolute(path);
7691
7633
  }
7692
7634
  async function capture(root, file) {
7693
- const absolute = join22(root, ...file.path.split("/"));
7635
+ const absolute = join21(root, ...file.path.split("/"));
7694
7636
  try {
7695
7637
  const entry2 = await lstat13(absolute);
7696
7638
  if (!entry2.isFile() || entry2.isSymbolicLink() || entry2.size !== file.bytes) {
@@ -7698,7 +7640,7 @@ async function capture(root, file) {
7698
7640
  }
7699
7641
  const canonical = await realpath9(absolute);
7700
7642
  if (!inside(root, canonical)) changed(file.path, `\u63D0\u4EA4\u6587\u4EF6\u8D8A\u8FC7\u9879\u76EE\u6839\u76EE\u5F55\uFF1A${file.path}`);
7701
- const contents = await readFile19(absolute);
7643
+ const contents = await readFile18(absolute);
7702
7644
  if (contents.byteLength !== file.bytes || digest3(contents) !== file.digest) {
7703
7645
  changed(file.path, `\u63D0\u4EA4\u524D\u6587\u4EF6\u5185\u5BB9\u53D1\u751F\u53D8\u5316\uFF1A${file.path}`);
7704
7646
  }
@@ -7816,6 +7758,7 @@ function validateRecoverableBuddyId(value) {
7816
7758
  return buddyId;
7817
7759
  }
7818
7760
  async function resolveApplicationDraft(name, tagline, intro, requestedBuddyId, options, root, args, io) {
7761
+ await checkProjectGateway(root, resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
7819
7762
  const register = () => (options.registerMeta ?? prepareAndRegisterMeta)({
7820
7763
  root,
7821
7764
  profile: { name, tagline, intro },
@@ -7909,9 +7852,6 @@ function parseInitArguments(args) {
7909
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");
7910
7853
  parsed.creatorVersion = setOnce2(parsed.creatorVersion, value, flag2);
7911
7854
  break;
7912
- case "--runtime-version":
7913
- parsed.runtimeVersion = setOnce2(parsed.runtimeVersion, value, flag2);
7914
- break;
7915
7855
  case "--avatar":
7916
7856
  parsed.avatar = setOnce2(parsed.avatar, value, flag2);
7917
7857
  break;
@@ -8000,7 +7940,6 @@ async function initializeProjectRoute(route, args, io, options, application) {
8000
7940
  const initializationTarget = { directory: rootDirectory, kind: "new" };
8001
7941
  let initializationPlan = options.initializeProject ? void 0 : await planBuddyProjectInitialization(initializationTarget);
8002
7942
  const existingBuddyId = initializationPlan?.existingManifest?.buddyId;
8003
- const runtimeVersion = args.resolvedRuntimeVersion ?? await selectInitRuntime(rootDirectory, args.runtimeVersion, io, options.runtimeCatalog);
8004
7943
  if (existingBuddyId !== void 0 && args.buddyId !== void 0 && existingBuddyId !== args.buddyId) {
8005
7944
  throw new CliUsageError(
8006
7945
  `\u5DF2\u6709 package.json \u7ED1\u5B9A\u7684\u662F ${existingBuddyId}\uFF0C\u4E0E --buddy-id ${args.buddyId} \u4E0D\u4E00\u81F4`
@@ -8023,9 +7962,9 @@ async function initializeProjectRoute(route, args, io, options, application) {
8023
7962
  }
8024
7963
  let platformTemplate;
8025
7964
  try {
8026
- platformTemplate = options.scaffoldPlatformAgent ? await options.scaffoldPlatformAgent(project.rootDirectory, name, runtimeVersion) : await scaffoldPlatformAgent(project.rootDirectory, name, runtimeVersion ? {
8027
- resolveDependencies: (template) => latestRuntimeTemplate(template, { ...options.runtimeCatalog, runtimeVersion, report: (message) => io.writeError(message) })
8028
- } : 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
+ });
8029
7968
  } catch (cause) {
8030
7969
  const detail = cause instanceof Error ? cause.message : String(cause);
8031
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`);
@@ -8108,7 +8047,7 @@ async function resumeProjectArguments(args, cwd, options, io) {
8108
8047
  await assertInitializableBuddyTarget(root);
8109
8048
  let entry2;
8110
8049
  try {
8111
- entry2 = await lstat14(join23(root, "package.json"));
8050
+ entry2 = await lstat14(join22(root, "package.json"));
8112
8051
  } catch (cause) {
8113
8052
  if (cause.code === "ENOENT") {
8114
8053
  const draft = await readMetaDraft(root);
@@ -8156,6 +8095,7 @@ async function runBuddyCli(args, io, options = {}) {
8156
8095
  } catch (cause) {
8157
8096
  if (!(cause instanceof BuddyProjectContextError) || cause.code !== "PROJECT_DIRECTORY_NOT_FOUND") throw cause;
8158
8097
  }
8098
+ if (projectRoot !== void 0) await checkProjectGateway(projectRoot, resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
8159
8099
  await authenticate(options);
8160
8100
  if (projectRoot !== void 0) {
8161
8101
  io.write(`\u5DF2\u8BC6\u522B\u642D\u642D\u9879\u76EE\uFF1A${projectRoot}`);
@@ -8212,10 +8152,6 @@ async function runBuddyCli(args, io, options = {}) {
8212
8152
  return { exitCode: 0 };
8213
8153
  }
8214
8154
  let route = routeFromMode(parsed.mode);
8215
- if (parsed.runtimeVersion !== void 0) {
8216
- if (!allowsRuntimeVersionSelection(options.runtimeCatalog)) throw new CliUsageError("\u672A\u77E5 init \u53C2\u6570 --runtime-version");
8217
- 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");
8218
- }
8219
8155
  if (route === void 0 && !io.canPrompt) requireModeForNonInteractive();
8220
8156
  const cwd = resolve18(options.cwd ?? process.cwd());
8221
8157
  await assertInitializableBuddyTarget(cwd);
@@ -8223,10 +8159,7 @@ async function runBuddyCli(args, io, options = {}) {
8223
8159
  if (!parsed.directory.trim()) throw new CliUsageError("--directory \u4E0D\u80FD\u4E3A\u7A7A");
8224
8160
  await assertInitializableBuddyTarget(resolve18(cwd, parsed.directory));
8225
8161
  }
8226
- if (route === "direct-create" && (!io.canPrompt || parsed.directory !== void 0)) {
8227
- const target = resolve18(cwd, parsed.directory ?? (parsed.name ? defaultProjectDirectory(parsed.name) : "."));
8228
- parsed.resolvedRuntimeVersion = await selectInitRuntime(target, parsed.runtimeVersion, io, options.runtimeCatalog);
8229
- }
8162
+ await checkProjectGateway(resolve18(cwd, parsed.directory ?? "."), resolvePlatformUrl({ env: options.runtimeCatalog?.env }));
8230
8163
  await authenticate(options);
8231
8164
  await resumeProjectArguments(parsed, cwd, options, io);
8232
8165
  route ??= routeFromMode(parsed.mode);
@@ -8242,7 +8175,7 @@ async function runBuddyCli(args, io, options = {}) {
8242
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");
8243
8176
  return { exitCode: 130 };
8244
8177
  }
8245
- 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) {
8246
8179
  return failure2(cause.message, io, cause instanceof CliUsageError);
8247
8180
  }
8248
8181
  throw cause;