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