@my-life-buddies/cli 0.13.3 → 0.14.1
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 +11 -7
- package/dist/bin/buddy.js +1 -1
- package/dist/bin/buddy.js.map +1 -1
- package/dist/bin/core.js +233 -54
- package/dist/bin/core.js.map +4 -4
- package/dist/bin/preview.js +281 -19
- package/dist/bin/preview.js.map +4 -4
- package/dist/web/app.css +65 -6
- package/dist/web/app.js +92 -33
- package/dist/web/diagnostics.js +184 -0
- package/dist/web/index.html +34 -34
- package/package.json +3 -3
- package/resources/agent-template/package-lock.json +4 -4
- package/resources/agent-template/package.json +2 -2
package/dist/bin/core.js
CHANGED
|
@@ -16,6 +16,12 @@ function runtimeDependencyVersion(pkg) {
|
|
|
16
16
|
const version = dependencies2[BUDDY_RUNTIME_PACKAGE];
|
|
17
17
|
return typeof version === "string" && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(version) ? version : void 0;
|
|
18
18
|
}
|
|
19
|
+
function runtimeUsesEnvironmentIdentity(pkg) {
|
|
20
|
+
const version = runtimeDependencyVersion(pkg);
|
|
21
|
+
if (!version) return false;
|
|
22
|
+
const [major, minor] = version.split(".").map(Number);
|
|
23
|
+
return major > 0 || minor >= 16;
|
|
24
|
+
}
|
|
19
25
|
|
|
20
26
|
// packages/cli-core/src/config/runtime-catalog.ts
|
|
21
27
|
async function loadRuntime(projectRoot) {
|
|
@@ -529,7 +535,7 @@ import { lstat as lstat4 } from "node:fs/promises";
|
|
|
529
535
|
import { join as join5 } from "node:path";
|
|
530
536
|
|
|
531
537
|
// packages/cli-core/src/init/scaffold.ts
|
|
532
|
-
import { lstat as lstat3, mkdir as mkdir4, open as open2, readFile as readFile6, rmdir as rmdir2, unlink as unlink3 } from "node:fs/promises";
|
|
538
|
+
import { lstat as lstat3, mkdir as mkdir4, open as open2, readFile as readFile6, rmdir as rmdir2, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
|
|
533
539
|
import { resolve as resolve3 } from "node:path";
|
|
534
540
|
|
|
535
541
|
// packages/cli-core/src/config/models.ts
|
|
@@ -766,8 +772,6 @@ process.on("SIGTERM", stop);
|
|
|
766
772
|
let runtime;
|
|
767
773
|
try {
|
|
768
774
|
runtime = await BuddyServer.start({
|
|
769
|
-
buddyId: process.env.BUDDY_ID,
|
|
770
|
-
token: process.env.BUDDY_TOKEN,
|
|
771
775
|
dataRequirements: config.datasets ?? [],
|
|
772
776
|
buddy: createBuddyOptions,
|
|
773
777
|
});
|
|
@@ -786,6 +790,32 @@ try {
|
|
|
786
790
|
}
|
|
787
791
|
`;
|
|
788
792
|
}
|
|
793
|
+
function legacyPlatformStartTemplate() {
|
|
794
|
+
return platformStartTemplate().replace(" dataRequirements: config.datasets ?? [],", " buddyId: process.env.BUDDY_ID,\n token: process.env.BUDDY_TOKEN,\n dataRequirements: config.datasets ?? [],");
|
|
795
|
+
}
|
|
796
|
+
async function migrateRuntimeStartup(projectRoot) {
|
|
797
|
+
const packagePath = resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON);
|
|
798
|
+
const entryPath = resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY);
|
|
799
|
+
for (const path of [packagePath, entryPath]) {
|
|
800
|
+
if (!(await lstat3(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");
|
|
801
|
+
}
|
|
802
|
+
const pkg = JSON.parse(await readFile6(packagePath, "utf8"));
|
|
803
|
+
if (!runtimeUsesEnvironmentIdentity(pkg)) return false;
|
|
804
|
+
const current = await readFile6(entryPath, "utf8");
|
|
805
|
+
const latest = platformStartTemplate();
|
|
806
|
+
const legacy = legacyPlatformStartTemplate();
|
|
807
|
+
let changed2 = false;
|
|
808
|
+
if (current.replace(/\r\n/gu, "\n") === legacy) {
|
|
809
|
+
await writeFile5(entryPath, latest, "utf8");
|
|
810
|
+
changed2 = true;
|
|
811
|
+
}
|
|
812
|
+
if (pkg.scripts?.start === "node start.mjs") {
|
|
813
|
+
pkg.scripts.start = "node --env-file-if-exists=.env start.mjs";
|
|
814
|
+
await writeFile5(packagePath, JSON.stringify(pkg, null, 2) + "\n", "utf8");
|
|
815
|
+
changed2 = true;
|
|
816
|
+
}
|
|
817
|
+
return changed2;
|
|
818
|
+
}
|
|
789
819
|
async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
|
|
790
820
|
const path = resolve3(projectRoot, BUDDY_PLATFORM_AGENT_ENTRY);
|
|
791
821
|
const hasAlternateLockfile = (await Promise.all(["pnpm-lock.yaml", "yarn.lock"].map(async (name2) => {
|
|
@@ -804,7 +834,9 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
|
|
|
804
834
|
{ path: resolve3(projectRoot, BUDDY_PLATFORM_FACTORY_ENTRY), content: platformFactoryTemplate() },
|
|
805
835
|
{ path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_JSON), content: await readFile6(new URL("../../resources/agent-template/package.json", import.meta.url), "utf8") },
|
|
806
836
|
...hasAlternateLockfile ? [] : [{ path: resolve3(projectRoot, BUDDY_PLATFORM_PACKAGE_LOCK), content: await readFile6(new URL("../../resources/agent-template/package-lock.json", import.meta.url), "utf8") }],
|
|
807
|
-
{ path: resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() }
|
|
837
|
+
{ path: resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY), content: platformStartTemplate() },
|
|
838
|
+
{ path: resolve3(projectRoot, ".gitignore"), content: "node_modules/\n/.env\n" },
|
|
839
|
+
{ 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" }
|
|
808
840
|
];
|
|
809
841
|
const handles = [];
|
|
810
842
|
const createdDirectories = [];
|
|
@@ -847,12 +879,17 @@ async function scaffoldPlatformAgent(projectRoot, name, options = {}) {
|
|
|
847
879
|
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");
|
|
848
880
|
}
|
|
849
881
|
}
|
|
882
|
+
const effectivePackage = handles.some((file) => file.path === packageFile.path) ? packageFile.content : await readFile6(packageFile.path, "utf8");
|
|
883
|
+
if (!runtimeUsesEnvironmentIdentity(JSON.parse(effectivePackage))) {
|
|
884
|
+
files.find((file) => file.path === resolve3(projectRoot, BUDDY_PLATFORM_START_ENTRY)).content = legacyPlatformStartTemplate();
|
|
885
|
+
}
|
|
850
886
|
for (const { path: filePath, handle } of handles) {
|
|
851
887
|
const file = files.find((candidate) => candidate.path === filePath);
|
|
852
888
|
await handle.writeFile(file.content, "utf8");
|
|
853
889
|
await handle.sync();
|
|
854
890
|
}
|
|
855
|
-
|
|
891
|
+
const migrated = await migrateRuntimeStartup(projectRoot);
|
|
892
|
+
return Object.freeze({ path, created: migrated || handles.length > 0 || createdDirectories.length > 0 });
|
|
856
893
|
} catch (cause) {
|
|
857
894
|
await Promise.all(handles.map(({ handle }) => handle.close().catch(() => void 0)));
|
|
858
895
|
await Promise.all(handles.map(({ path: createdPath }) => unlink3(createdPath).catch(() => void 0)));
|
|
@@ -1635,7 +1672,7 @@ ${DATASETS_COMMAND_HELP}`);
|
|
|
1635
1672
|
|
|
1636
1673
|
// packages/cli-core/src/commands/knowledge.ts
|
|
1637
1674
|
import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
|
|
1638
|
-
import { lstat as lstat7, mkdir as mkdir6, readFile as readFile8, rename as rename5, unlink as unlink5, writeFile as
|
|
1675
|
+
import { lstat as lstat7, mkdir as mkdir6, readFile as readFile8, rename as rename5, unlink as unlink5, writeFile as writeFile6 } from "node:fs/promises";
|
|
1639
1676
|
import { dirname as dirname2, join as join8, resolve as resolve8 } from "node:path";
|
|
1640
1677
|
var MANIFEST = "knowledge-manifest.json";
|
|
1641
1678
|
var INDEX = "resources/knowledge/index.md";
|
|
@@ -1705,7 +1742,7 @@ async function atomicWrite(root, path, value) {
|
|
|
1705
1742
|
const full = await safePath(root, path);
|
|
1706
1743
|
await mkdir6(dirname2(full), { recursive: true });
|
|
1707
1744
|
const temporary = `${full}.${randomUUID4()}.tmp`;
|
|
1708
|
-
await
|
|
1745
|
+
await writeFile6(temporary, value, { flag: "wx", mode: 384 });
|
|
1709
1746
|
try {
|
|
1710
1747
|
await rename5(temporary, full);
|
|
1711
1748
|
} finally {
|
|
@@ -1947,11 +1984,11 @@ ${KNOWLEDGE_HELP}`);
|
|
|
1947
1984
|
}
|
|
1948
1985
|
|
|
1949
1986
|
// packages/cli-core/src/index.ts
|
|
1950
|
-
import { join as
|
|
1987
|
+
import { join as join16, resolve as resolve16 } from "node:path";
|
|
1951
1988
|
|
|
1952
1989
|
// packages/cli-core/src/init/creator.ts
|
|
1953
1990
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
1954
|
-
import { link as link2, lstat as lstat8, mkdir as mkdir7, readFile as readFile9, unlink as unlink6, writeFile as
|
|
1991
|
+
import { link as link2, lstat as lstat8, mkdir as mkdir7, readFile as readFile9, unlink as unlink6, writeFile as writeFile7 } from "node:fs/promises";
|
|
1955
1992
|
import { join as join9 } from "node:path";
|
|
1956
1993
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
1957
1994
|
|
|
@@ -2022,7 +2059,7 @@ ${KNOWLEDGE_GUIDE}
|
|
|
2022
2059
|
| \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 |
|
|
2023
2060
|
| \u6A21\u578B\u548C\u5E73\u53F0\u8D44\u6E90 | \u5DF2\u786E\u5B9A\u7684\u6A21\u578B\u76F4\u63A5\u6CBF\u7528\uFF1B\u672A\u6307\u5B9A\u65F6\u67E5\u8BE2 \`buddy-cli models\`\uFF0C\u6838\u5BF9\u53EF\u7528\u6027\u5E76\u91C7\u7528\u6EE1\u8DB3\u9700\u6C42\u7684\u9009\u62E9\uFF0C\u4E0D\u9ED8\u8BA4\u518D\u95EE\u4E00\u8F6E\u9009\u578B\u95EE\u9898\uFF0C\u4E5F\u4E0D\u7F16\u9020\u4EF7\u683C\u6216\u80FD\u529B\u3002\u6A21\u677F\u628A\u914D\u7F6E\u4E2D\u7684\u6A21\u578B\u4EA4\u7ED9 \`initialState.model\`\uFF1B\u81EA\u5B9A\u4E49\u5DE5\u5382\u4E5F\u53EF\u6309\u4F1A\u8BDD\u9009\u62E9\u53D7\u652F\u6301\u6A21\u578B\uFF1B\u4F1A\u4EA7\u751F\u65B0\u7684\u8D39\u7528\u3001\u6570\u636E\u4F7F\u7528\u6216\u6743\u9650\u8FB9\u754C\u65F6\u5148\u786E\u8BA4\u3002 |
|
|
2024
2061
|
|
|
2025
|
-
\`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({
|
|
2062
|
+
\`src/buddy-options.mjs\` \u662F\u6BCF\u573A\u4F1A\u8BDD\u7684\u4E1A\u52A1\u88C5\u914D\u5165\u53E3\uFF0C\u5BFC\u51FA \`createBuddyOptions(conversation)\`\uFF0C\u8FD4\u56DE \`initialState\`\u3001\u5728 \`initialState.tools\` \u6CE8\u518C\u7684\u4E1A\u52A1\u53CA\u5E73\u53F0\u5DE5\u5177\u548C\u53EF\u9009\u56DE\u5408\u94A9\u5B50\u3002\`start.mjs\` \u4ECE \`./src/buddy-options.mjs\` \u5BFC\u5165\u5DE5\u5382\u5E76\u4F20\u7ED9 \`BuddyServer.start({ dataRequirements: config.datasets ?? [], buddy: createBuddyOptions })\`\uFF1B\u7EC4\u88C5\u5668\u8BFB\u53D6 \`buddy.agent.json.model\`\uFF0C\u7701\u7565\u65F6\u7528 \`kimi-k2.6\`\uFF0C\u653E\u5165 \`initialState.model\`\uFF1B\u7528 \`new URL("../agent.md", import.meta.url)\` \u8BFB\u53D6\u6839\u76EE\u5F55 Prompt\u3002\u9ED8\u8BA4\u6A21\u677F\u53EA\u662F\u8D77\u70B9\uFF0C\u53EA\u6539\u8BF4\u660E\u4E0D\u7B49\u4E8E\u6539\u53D8\u4E86\u4FDD\u5B58\u3001\u67E5\u8BE2\u6216\u5904\u7406\u903B\u8F91\u3002 Runtime 0.16.0 \u4ECE\u73AF\u5883\u53D8\u91CF\u8BFB\u53D6\u8EAB\u4EFD\u548C\u4EE4\u724C\uFF1B\u9996\u6B21\u542F\u52A8 DEV \u65F6 CLI \u51C6\u5907\u5DE5\u7A0B \`.env\`\uFF0CNode \u7528 \`--env-file-if-exists=.env\` \u52A0\u8F7D\u3002\u4E0D\u8981\u5C06 token \u5199\u5165\u4E1A\u52A1\u4EE3\u7801\u3002
|
|
2026
2063
|
|
|
2027
2064
|
### \u6309\u76EE\u5F55\u804C\u8D23\u7EC4\u7EC7\u5B9E\u73B0
|
|
2028
2065
|
|
|
@@ -2052,11 +2089,11 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
|
|
|
2052
2089
|
|
|
2053
2090
|
\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
|
|
2054
2091
|
|
|
2055
|
-
\u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\
|
|
2092
|
+
\u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002\u4EE5\u5DE5\u7A0B\u5B89\u88C5\u7248\u672C\u5BFC\u51FA\u7684\u76EE\u5F55\u4E3A\u51C6\uFF0CCLI \u4E0D\u590D\u5236\u679A\u4E3E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`buddy.agent.json.datasets\`\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0C\u7528\u9014\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u6700\u591A 200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
|
|
2056
2093
|
|
|
2057
2094
|
\`start.mjs\` \u5C06\u58F0\u660E\u4EA4\u7ED9 \`StartOptions.dataRequirements\`\u3002Runtime \u5728\u5B9E\u9645\u6570\u636E\u67E5\u8BE2\u3001HealthKit \u6388\u6743\u548C\u4E3B\u52A8\u670D\u52A1\u8BF7\u6C42\u4E2D\u643A\u5E26\u5B8C\u6574\u58F0\u660E\uFF0C\u7531 Server \u6821\u9A8C\u8303\u56F4\u4E0E\u7528\u6237\u540C\u610F\uFF1B\u586B\u5199\u914D\u7F6E\u4E0D\u8868\u793A\u5DF2\u7ECF\u6388\u6743\u3002\u670D\u52A1\u7AEF\u4ECE\u4E0A\u4F20\u5305\u89E3\u6790\u5E76\u7ED1\u5B9A\u53D1\u5E03\u7248\u672C\u4ECD\u5F85\u5B9E\u73B0\u3002
|
|
2058
2095
|
|
|
2059
|
-
\u6A21\u578B\u9700\u8981\u67E5\u6570\u636E\u65F6\uFF0C\u5728 \`src/buddy-options.mjs\` \u7684 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.data_access_query\`\uFF1B\u9700\u8981\u5411\u7528\u6237\u7533\u8BF7\u65F6\u52A0\u5165 \`conversation.tools.data_access_request\`\uFF0C\u4F4D\u7F6E\u3001\u65E5\u5386\u7684\u4E00\u6B21\u6027\u7ED3\u679C\u901A\u8FC7 \`data_access_read_result\` \u8BFB\u53D6\uFF0CHealthKit \u5219\u91CD\u65B0\u67E5\u8BE2 Dataset\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query/request/readResult\`\u3002\u65B0\u5EFA\u5DE5\u7A0B\u52A8\u6001\u9009\u62E9\u516C\u5171 npm latest \u5E76\u9501\u5B9A\u51C6\u786E\u7248\u672C\uFF1B\u8054\u7F51\u5931\u8D25\u65F6\u660E\u786E\u63D0\u793A\u4F7F\u7528\u968F CLI \u9644\u5E26\u7684 Runtime 0.
|
|
2096
|
+
\u6A21\u578B\u9700\u8981\u67E5\u6570\u636E\u65F6\uFF0C\u5728 \`src/buddy-options.mjs\` \u7684 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.data_access_query\`\uFF1B\u9700\u8981\u5411\u7528\u6237\u7533\u8BF7\u65F6\u52A0\u5165 \`conversation.tools.data_access_request\`\uFF0C\u4F4D\u7F6E\u3001\u65E5\u5386\u7684\u4E00\u6B21\u6027\u7ED3\u679C\u901A\u8FC7 \`data_access_read_result\` \u8BFB\u53D6\uFF0CHealthKit \u5219\u91CD\u65B0\u67E5\u8BE2 Dataset\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query/request/readResult\`\u3002\u65B0\u5EFA\u5DE5\u7A0B\u52A8\u6001\u9009\u62E9\u516C\u5171 npm latest \u5E76\u9501\u5B9A\u51C6\u786E\u7248\u672C\uFF1B\u8054\u7F51\u5931\u8D25\u65F6\u660E\u786E\u63D0\u793A\u4F7F\u7528\u968F CLI \u9644\u5E26\u7684 Runtime 0.16.0\u3002\u5DF2\u6709\u5DE5\u7A0B\u901A\u8FC7\u5305\u7BA1\u7406\u5668\u663E\u5F0F\u5347\u7EA7\u4F9D\u8D56\u3002
|
|
2060
2097
|
|
|
2061
2098
|
\u5C0F\u6302\u4EF6\u7684\u6A21\u578B\u5DE5\u5177\u4E3A \`widget_create\`\u3001\`widget_read\`\uFF08\u6574\u4E2A\u5C0F\u6302\u4EF6\uFF09\u3001\`widget_read_module\`\uFF08\u4E00\u4E2A\u6A21\u5757\uFF09\u3001\`widget_rename\`\u3001\`widget_write_record\`\u3001\`widget_delete_record\`\u3001\`widget_delete\`\uFF08\u6574\u4E2A\u5C0F\u6302\u4EF6\u8FDE\u8BB0\u5F55\uFF09\u548C \`widget_send\`\uFF0C\u6309\u4E1A\u52A1\u9700\u8981\u6CE8\u518C\u5230 \`initialState.tools\`\u3002\u4FEE\u6539\u8BB0\u5F55\u7528 \`conversation.widget.writeRecord(id, input)\`\uFF1B\u5220\u4E00\u6761\u8BB0\u5F55\u7528 \`conversation.widget.deleteRecord(id, module, recordId)\`\uFF0C\u4E0D\u80FD\u7528\u5220\u9664\u6574\u4E2A\u5C0F\u6302\u4EF6\u7684 \`conversation.widget.delete(id)\` \u4EE3\u66FF\u3002\u4E24\u4E2A\u8BFB\u53D6\u5DE5\u5177\u53EF\u7528\u4E8E\u4E3B\u52A8\u56DE\u5408\uFF0C\u5176\u4F59\u516D\u4E2A\u5199\u5165\u5DE5\u5177\u7531 Runtime \u963B\u6B62\u5728\u4E3B\u52A8\u56DE\u5408\u6267\u884C\u3002
|
|
2062
2099
|
|
|
@@ -2153,7 +2190,7 @@ async function safeRead(path) {
|
|
|
2153
2190
|
}
|
|
2154
2191
|
async function writeOnce(path, bytes) {
|
|
2155
2192
|
const temporary = `${path}.${randomUUID5()}.tmp`;
|
|
2156
|
-
await
|
|
2193
|
+
await writeFile7(temporary, bytes, { flag: "wx", mode: 384 });
|
|
2157
2194
|
try {
|
|
2158
2195
|
await link2(temporary, path).catch((cause) => {
|
|
2159
2196
|
if (cause.code !== "EEXIST") throw cause;
|
|
@@ -2376,6 +2413,13 @@ function resolvePlatformUrl(options = {}) {
|
|
|
2376
2413
|
return normalizePlatformUrl(options.override ?? configured ?? DEFAULT_MLB_TEST_URL);
|
|
2377
2414
|
}
|
|
2378
2415
|
|
|
2416
|
+
// packages/cli-core/src/dev/project-env.ts
|
|
2417
|
+
import { constants } from "node:fs";
|
|
2418
|
+
import { open as open4, rename as rename6, unlink as unlink7 } from "node:fs/promises";
|
|
2419
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
2420
|
+
import { join as join10 } from "node:path";
|
|
2421
|
+
import { parseEnv } from "node:util";
|
|
2422
|
+
|
|
2379
2423
|
// packages/cli-core/src/dev/errors.ts
|
|
2380
2424
|
var BuddyDevError = class extends Error {
|
|
2381
2425
|
code;
|
|
@@ -2404,6 +2448,124 @@ function throwIfDevAborted(signal) {
|
|
|
2404
2448
|
if (signal?.aborted) throw abortedDevError(signal);
|
|
2405
2449
|
}
|
|
2406
2450
|
|
|
2451
|
+
// packages/cli-core/src/dev/project-env.ts
|
|
2452
|
+
function invalid(message) {
|
|
2453
|
+
return new BuddyDevError({ code: "DEV_CONFIG_INVALID", phase: "config", message });
|
|
2454
|
+
}
|
|
2455
|
+
async function readLocalFile(path) {
|
|
2456
|
+
let file;
|
|
2457
|
+
try {
|
|
2458
|
+
file = await open4(path, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
2459
|
+
const stat2 = await file.stat();
|
|
2460
|
+
if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > 256 * 1024) throw invalid("\u672C\u5730\u914D\u7F6E\u5FC5\u987B\u662F\u5C0F\u4E8E 256 KB \u7684\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u4F7F\u7528\u94FE\u63A5\u3002");
|
|
2461
|
+
return await file.readFile("utf8");
|
|
2462
|
+
} catch (cause) {
|
|
2463
|
+
if (cause.code === "ENOENT") return "";
|
|
2464
|
+
if (cause instanceof BuddyDevError) throw cause;
|
|
2465
|
+
throw invalid("\u65E0\u6CD5\u8BFB\u53D6\u5DE5\u7A0B\u672C\u5730\u914D\u7F6E\uFF0C\u8BF7\u68C0\u67E5 .env \u548C .gitignore \u7684\u6587\u4EF6\u7C7B\u578B\u4E0E\u6743\u9650\u3002");
|
|
2466
|
+
} finally {
|
|
2467
|
+
await file?.close();
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
async function readProjectEnvironment(projectRoot, buddyId) {
|
|
2471
|
+
const source = await readLocalFile(join10(projectRoot, ".env"));
|
|
2472
|
+
let values;
|
|
2473
|
+
try {
|
|
2474
|
+
values = parseEnv(source);
|
|
2475
|
+
} catch {
|
|
2476
|
+
throw invalid("\u5DE5\u7A0B .env \u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u68C0\u67E5\u540E\u91CD\u8BD5\u3002");
|
|
2477
|
+
}
|
|
2478
|
+
if (values.BUDDY_ID && values.BUDDY_ID !== buddyId) throw invalid(".env \u7684 BUDDY_ID \u4E0E buddy.agent.json \u4E0D\u4E00\u81F4\uFF0C\u8BF7\u5148\u4FEE\u6B63\u5DE5\u7A0B\u8EAB\u4EFD\u3002");
|
|
2479
|
+
return values;
|
|
2480
|
+
}
|
|
2481
|
+
async function projectBuddyToken(projectRoot, buddyId, gatewayUrl) {
|
|
2482
|
+
const values = await readProjectEnvironment(projectRoot, buddyId);
|
|
2483
|
+
if (!values.BUDDY_TOKEN) return void 0;
|
|
2484
|
+
if (!values.BUDDY_ID) throw invalid(".env \u4E2D\u6709 BUDDY_TOKEN\uFF0C\u4F46\u7F3A\u5C11 BUDDY_ID\uFF0C\u8BF7\u8865\u9F50\u540E\u91CD\u8BD5\u3002");
|
|
2485
|
+
if (values.MLB_GATEWAY_URL) {
|
|
2486
|
+
let gateway;
|
|
2487
|
+
try {
|
|
2488
|
+
gateway = normalizePlatformUrl(values.MLB_GATEWAY_URL);
|
|
2489
|
+
} catch {
|
|
2490
|
+
throw invalid(".env \u4E2D\u7684 MLB_GATEWAY_URL \u65E0\u6548\u3002");
|
|
2491
|
+
}
|
|
2492
|
+
if (gateway.href !== gatewayUrl.href) throw invalid(".env \u7684\u5E73\u53F0\u5730\u5740\u4E0E\u672C\u6B21\u542F\u52A8\u4E0D\u540C\uFF1B\u8BF7\u786E\u8BA4\u5E73\u53F0\u540E\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u5F00\u53D1\u4EE4\u724C\u3002");
|
|
2493
|
+
}
|
|
2494
|
+
if (!values.BUDDY_TOKEN.trim() || /[\u0000-\u001f\u007f]/u.test(values.BUDDY_TOKEN)) throw invalid(".env \u4E2D\u7684\u5F00\u53D1\u4EE4\u724C\u683C\u5F0F\u65E0\u6548\uFF0C\u8BF7\u4F7F\u7528 --refresh-token \u91CD\u65B0\u9886\u53D6\u3002");
|
|
2495
|
+
return values.BUDDY_TOKEN;
|
|
2496
|
+
}
|
|
2497
|
+
function quote(value) {
|
|
2498
|
+
if (/[\u0000-\u001f\u007f]/u.test(value)) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26\u3002");
|
|
2499
|
+
const delimiter = ["'", '"', "`"].find((character) => !value.includes(character));
|
|
2500
|
+
if (!delimiter) throw invalid("\u672C\u5730\u8FD0\u884C\u914D\u7F6E\u5305\u542B\u65E0\u6CD5\u5199\u5165 .env \u7684\u5F15\u53F7\u7EC4\u5408\u3002");
|
|
2501
|
+
return `${delimiter}${value}${delimiter}`;
|
|
2502
|
+
}
|
|
2503
|
+
function updateValues(source, values) {
|
|
2504
|
+
const assignment = /^[\t ]*(?:export[\t ]+)?([A-Za-z_][A-Za-z0-9_]*)[\t ]*=[\t ]*/gm;
|
|
2505
|
+
let output = "", cursor = 0, match;
|
|
2506
|
+
const written = /* @__PURE__ */ new Set();
|
|
2507
|
+
while (match = assignment.exec(source)) {
|
|
2508
|
+
const valueStart = assignment.lastIndex;
|
|
2509
|
+
let end = source.indexOf("\n", valueStart);
|
|
2510
|
+
if (end < 0) end = source.length;
|
|
2511
|
+
let commentStart = valueStart;
|
|
2512
|
+
const delimiter = source[valueStart];
|
|
2513
|
+
if (delimiter && ["'", '"', "`"].includes(delimiter)) {
|
|
2514
|
+
const close = source.indexOf(delimiter, valueStart + 1);
|
|
2515
|
+
if (close < 0) throw invalid(".env \u4E2D\u6709\u672A\u95ED\u5408\u7684\u5F15\u53F7\uFF0C\u8BF7\u4FEE\u6B63\u540E\u91CD\u8BD5\u3002");
|
|
2516
|
+
commentStart = close + 1;
|
|
2517
|
+
end = source.indexOf("\n", close + 1);
|
|
2518
|
+
if (end < 0) end = source.length;
|
|
2519
|
+
}
|
|
2520
|
+
assignment.lastIndex = end;
|
|
2521
|
+
const name = match[1];
|
|
2522
|
+
if (!(name in values)) continue;
|
|
2523
|
+
const comment = source.slice(commentStart, end).match(/[\t ]*#[^\r\n]*/u)?.[0] ?? "";
|
|
2524
|
+
output += source.slice(cursor, match.index);
|
|
2525
|
+
output += written.has(name) ? comment : `${name}=${quote(values[name])}${comment ? ` ${comment.trimStart()}` : ""}`;
|
|
2526
|
+
if (source[end - 1] === "\r") output += "\r";
|
|
2527
|
+
cursor = end;
|
|
2528
|
+
written.add(name);
|
|
2529
|
+
}
|
|
2530
|
+
output += source.slice(cursor);
|
|
2531
|
+
const newline = source.includes("\r\n") ? "\r\n" : "\n";
|
|
2532
|
+
for (const [name, value] of Object.entries(values)) if (!written.has(name)) {
|
|
2533
|
+
if (output && !output.endsWith("\n")) output += newline;
|
|
2534
|
+
output += `${name}=${quote(value)}${newline}`;
|
|
2535
|
+
}
|
|
2536
|
+
const parsed = parseEnv(output);
|
|
2537
|
+
if (Object.entries(values).some(([name, value]) => parsed[name] !== value)) throw invalid("\u65E0\u6CD5\u5B8C\u6574\u66F4\u65B0 .env\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u683C\u5F0F\u3002");
|
|
2538
|
+
return output;
|
|
2539
|
+
}
|
|
2540
|
+
async function replaceFile(path, contents, mode) {
|
|
2541
|
+
const temporary = `${path}.${randomUUID6()}.tmp`;
|
|
2542
|
+
let file;
|
|
2543
|
+
try {
|
|
2544
|
+
file = await open4(temporary, "wx", mode);
|
|
2545
|
+
await file.writeFile(contents, "utf8");
|
|
2546
|
+
await file.sync();
|
|
2547
|
+
await file.close();
|
|
2548
|
+
file = void 0;
|
|
2549
|
+
await rename6(temporary, path);
|
|
2550
|
+
} finally {
|
|
2551
|
+
await file?.close();
|
|
2552
|
+
await unlink7(temporary).catch((cause) => {
|
|
2553
|
+
if (cause.code !== "ENOENT") throw cause;
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
async function writeProjectEnvironment(projectRoot, values) {
|
|
2558
|
+
await readProjectEnvironment(projectRoot, values.BUDDY_ID);
|
|
2559
|
+
const envPath = join10(projectRoot, ".env"), ignorePath = join10(projectRoot, ".gitignore");
|
|
2560
|
+
const contents = updateValues(await readLocalFile(envPath), values);
|
|
2561
|
+
const ignored = await readLocalFile(ignorePath);
|
|
2562
|
+
if (ignored.trimEnd().split(/\r?\n/u).at(-1) !== "/.env") {
|
|
2563
|
+
await replaceFile(ignorePath, `${ignored}${ignored && !ignored.endsWith("\n") ? "\n" : ""}/.env
|
|
2564
|
+
`, 420);
|
|
2565
|
+
}
|
|
2566
|
+
await replaceFile(envPath, contents, 384);
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2407
2569
|
// packages/cli-core/src/dev/app-server.ts
|
|
2408
2570
|
var MAX_JSON_BODY_LENGTH = 1048576;
|
|
2409
2571
|
function safeCredential(value, name) {
|
|
@@ -2543,6 +2705,11 @@ var MlbDevRegistrationClient = class {
|
|
|
2543
2705
|
});
|
|
2544
2706
|
}
|
|
2545
2707
|
options.signal.throwIfAborted();
|
|
2708
|
+
if (request.projectRoot) {
|
|
2709
|
+
await readProjectEnvironment(request.projectRoot, request.devAgentId);
|
|
2710
|
+
const localToken = this.#refreshToken ? void 0 : await projectBuddyToken(request.projectRoot, request.devAgentId, this.#baseUrl);
|
|
2711
|
+
if (localToken !== void 0) return Object.freeze({ devAgentId: request.devAgentId, appServerUrl: new URL(this.#baseUrl), agentToken: localToken });
|
|
2712
|
+
}
|
|
2546
2713
|
const store = this.#tokenStoreFor?.(request.devAgentId);
|
|
2547
2714
|
const cached = this.#refreshToken ? void 0 : await store?.load();
|
|
2548
2715
|
if (cached !== void 0) {
|
|
@@ -2565,7 +2732,7 @@ var MlbDevRegistrationClient = class {
|
|
|
2565
2732
|
}
|
|
2566
2733
|
const token = safeCredential(body.token, "agentToken");
|
|
2567
2734
|
options.signal.throwIfAborted();
|
|
2568
|
-
await store?.save(token);
|
|
2735
|
+
if (!request.projectRoot) await store?.save(token);
|
|
2569
2736
|
return Object.freeze({
|
|
2570
2737
|
devAgentId: request.devAgentId,
|
|
2571
2738
|
appServerUrl: new URL(this.#baseUrl),
|
|
@@ -2667,7 +2834,7 @@ function buildAgentEnvironment(options) {
|
|
|
2667
2834
|
// packages/cli-core/src/dev/orchestrator.ts
|
|
2668
2835
|
import { createHash as createHash4 } from "node:crypto";
|
|
2669
2836
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
2670
|
-
import { join as
|
|
2837
|
+
import { join as join12, resolve as resolve10 } from "node:path";
|
|
2671
2838
|
|
|
2672
2839
|
// packages/cli-core/src/dev/launch.ts
|
|
2673
2840
|
import { lstatSync, readFileSync } from "node:fs";
|
|
@@ -2712,9 +2879,10 @@ async function officialAgentLaunchPlan(input) {
|
|
|
2712
2879
|
cause
|
|
2713
2880
|
});
|
|
2714
2881
|
}
|
|
2882
|
+
await migrateRuntimeStartup(input.projectRoot);
|
|
2715
2883
|
return Object.freeze({
|
|
2716
2884
|
command: process.execPath,
|
|
2717
|
-
args: Object.freeze([entry2])
|
|
2885
|
+
args: Object.freeze(["--env-file-if-exists=.env", entry2])
|
|
2718
2886
|
});
|
|
2719
2887
|
}
|
|
2720
2888
|
|
|
@@ -2917,14 +3085,14 @@ function processTreeControllerFor(platform) {
|
|
|
2917
3085
|
// packages/cli-core/src/dev/instance-lock.ts
|
|
2918
3086
|
import { createHash as createHash3 } from "node:crypto";
|
|
2919
3087
|
import { homedir as homedir2 } from "node:os";
|
|
2920
|
-
import { join as
|
|
3088
|
+
import { join as join11 } from "node:path";
|
|
2921
3089
|
function alreadyRunningError() {
|
|
2922
3090
|
const message = "\u8FD9\u4E2A\u642D\u5B50\u5DF2\u6709 DEV \u5B9E\u4F8B\u5728\u8FD0\u884C\u3002\u8BF7\u5148\u5728\u539F\u9884\u89C8\u9875\u70B9\u51FB\u300C\u505C\u6B62 DEV\u300D\uFF0C\u6216\u5728\u8FD0\u884C dev \u7684\u7EC8\u7AEF\u6309 Ctrl+C\uFF0C\u518D\u542F\u52A8\u3002";
|
|
2923
3091
|
return Object.assign(new BuddyDevError({ code: "DEV_ALREADY_RUNNING", phase: "launch", message }), { publicMessage: message });
|
|
2924
3092
|
}
|
|
2925
3093
|
async function acquireDevInstanceLock(options) {
|
|
2926
3094
|
return acquireProcessLock({
|
|
2927
|
-
directory: options.directory ??
|
|
3095
|
+
directory: options.directory ?? join11(homedir2(), ".buddy", "dev-locks"),
|
|
2928
3096
|
key: createHash3("sha256").update(`${new URL(options.gatewayUrl).origin}
|
|
2929
3097
|
${options.devAgentId}`).digest("hex"),
|
|
2930
3098
|
busyError: alreadyRunningError
|
|
@@ -2993,6 +3161,7 @@ async function launchPlanFor(config, options, projectRoot, signal) {
|
|
|
2993
3161
|
async function registerDevAgent(options) {
|
|
2994
3162
|
try {
|
|
2995
3163
|
return validateRegistration(await options.client.register({
|
|
3164
|
+
projectRoot: options.projectRoot,
|
|
2996
3165
|
devAgentId: options.devAgentId,
|
|
2997
3166
|
configSource: options.configSource,
|
|
2998
3167
|
configDigest: options.configDigest
|
|
@@ -3183,7 +3352,7 @@ async function startBuddyDev(options) {
|
|
|
3183
3352
|
let config;
|
|
3184
3353
|
let configSource;
|
|
3185
3354
|
try {
|
|
3186
|
-
configSource = await readFile10(
|
|
3355
|
+
configSource = await readFile10(join12(projectRoot, BUDDY_AGENT_FILENAME), "utf8");
|
|
3187
3356
|
config = combineBuddyProject(parseBuddyAgentConfig(configSource));
|
|
3188
3357
|
} catch (cause) {
|
|
3189
3358
|
throw new BuddyDevError({
|
|
@@ -3193,8 +3362,10 @@ async function startBuddyDev(options) {
|
|
|
3193
3362
|
cause
|
|
3194
3363
|
});
|
|
3195
3364
|
}
|
|
3365
|
+
await readProjectEnvironment(projectRoot, devAgentId);
|
|
3196
3366
|
const launchPlan = await launchPlanFor(config, options, projectRoot, signal);
|
|
3197
3367
|
const registration = await registerDevAgent({
|
|
3368
|
+
projectRoot,
|
|
3198
3369
|
client: options.registrationClient,
|
|
3199
3370
|
devAgentId,
|
|
3200
3371
|
configSource,
|
|
@@ -3218,13 +3389,19 @@ async function startBuddyDev(options) {
|
|
|
3218
3389
|
buddyToken: registration.agentToken,
|
|
3219
3390
|
gatewayUrl: registration.appServerUrl
|
|
3220
3391
|
});
|
|
3392
|
+
await writeProjectEnvironment(projectRoot, {
|
|
3393
|
+
BUDDY_ID: environment.BUDDY_ID,
|
|
3394
|
+
BUDDY_TOKEN: environment.BUDDY_TOKEN,
|
|
3395
|
+
MLB_GATEWAY_URL: environment.MLB_GATEWAY_URL
|
|
3396
|
+
});
|
|
3397
|
+
const { BUDDY_ID: _id, BUDDY_TOKEN: _token, MLB_GATEWAY_URL: _gateway, ...childEnvironment } = environment;
|
|
3221
3398
|
const launcher = options.processLauncher ?? new NodeAgentProcessLauncher();
|
|
3222
3399
|
processTree = options.processTree ?? processTreeControllerFor(platform);
|
|
3223
3400
|
agentProcess = await launcher.spawn({
|
|
3224
3401
|
command: launchPlan.command,
|
|
3225
3402
|
args: launchPlan.args,
|
|
3226
3403
|
cwd: projectRoot,
|
|
3227
|
-
env:
|
|
3404
|
+
env: childEnvironment,
|
|
3228
3405
|
shell: false,
|
|
3229
3406
|
detached: platform === "darwin",
|
|
3230
3407
|
...options.onLog === void 0 ? {} : {
|
|
@@ -3495,7 +3672,7 @@ var DEV_COMMAND_HELP = `\u7528\u6CD5:
|
|
|
3495
3672
|
\u8BF4\u660E:
|
|
3496
3673
|
\u672A\u914D\u7F6E\u5730\u5740\u65F6\u8FDE\u63A5 MLB \u6D4B\u8BD5\u73AF\u5883 ${DEFAULT_MLB_TEST_URL}\uFF08HTTP \u4EC5\u9650\u6D4B\u8BD5\uFF09\u3002
|
|
3497
3674
|
CLI \u7EDF\u4E00\u542F\u52A8\u5E76\u7BA1\u7406\u5DE5\u7A0B\u4E2D\u7684\u5B98\u65B9 Runtime\u3002
|
|
3498
|
-
DEV \u4F1A\u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u5F00\u53D1\u8005\u4F1A\u8BDD\uFF0C\
|
|
3675
|
+
DEV \u4F1A\u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u83B7\u53D6\u5F00\u53D1\u8005\u4F1A\u8BDD\uFF0C\u5C06\u5F53\u524D\u642D\u5B50\u7684\u5F00\u53D1 Token \u5199\u5165\u5DE5\u7A0B .env\uFF0C\u540E\u7EED\u4F18\u5148\u590D\u7528\uFF1B\u767B\u5F55\u51ED\u636E\u4ECD\u4F7F\u7528\u7CFB\u7EDF\u51ED\u636E\u5B58\u50A8\u3002
|
|
3499
3676
|
--refresh-token \u91CD\u65B0\u9886\u53D6\u5DF2\u6709\u5F00\u53D1 Token\uFF0C\u7528\u4E8E\u670D\u52A1\u7AEF\u91CD\u7F6E\u540E\u7684\u672C\u673A\u66F4\u65B0\uFF1B\u4E0D\u4F1A\u751F\u6210\u65B0\u5BC6\u94A5\u3002`;
|
|
3500
3677
|
function valueAfter(args, index, flag2) {
|
|
3501
3678
|
const value = args[index + 1];
|
|
@@ -3625,7 +3802,7 @@ async function runDevCommand(args, io, options = {}) {
|
|
|
3625
3802
|
import { resolve as resolve13 } from "node:path";
|
|
3626
3803
|
|
|
3627
3804
|
// packages/cli-core/src/cloud/auth.ts
|
|
3628
|
-
import { randomUUID as
|
|
3805
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
3629
3806
|
|
|
3630
3807
|
// packages/cli-core/src/cloud/validation.ts
|
|
3631
3808
|
function record(value, path = "request") {
|
|
@@ -3693,7 +3870,7 @@ var CloudAuthenticator = class {
|
|
|
3693
3870
|
this.#adapter = adapter;
|
|
3694
3871
|
this.#store = store;
|
|
3695
3872
|
this.#now = options.now ?? Date.now;
|
|
3696
|
-
this.#createState = options.createState ??
|
|
3873
|
+
this.#createState = options.createState ?? randomUUID7;
|
|
3697
3874
|
this.#minimumValidityMs = options.minimumValidityMs ?? 3e4;
|
|
3698
3875
|
if (!Number.isSafeInteger(this.#minimumValidityMs) || this.#minimumValidityMs < 0) {
|
|
3699
3876
|
throw new TypeError("minimumValidityMs must be a non-negative safe integer");
|
|
@@ -3795,17 +3972,17 @@ function positiveTimeout(value, fallback, name) {
|
|
|
3795
3972
|
}
|
|
3796
3973
|
function object3(value, path) {
|
|
3797
3974
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
3798
|
-
throw
|
|
3975
|
+
throw invalid2(`${path} \u5FC5\u987B\u662F\u5BF9\u8C61`);
|
|
3799
3976
|
}
|
|
3800
3977
|
return value;
|
|
3801
3978
|
}
|
|
3802
|
-
function
|
|
3979
|
+
function invalid2(message) {
|
|
3803
3980
|
return new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", message);
|
|
3804
3981
|
}
|
|
3805
3982
|
function safeText(value, path, allowNewlines = false, allowEmpty = false) {
|
|
3806
|
-
if (typeof value !== "string" || !allowEmpty && !value.trim()) throw
|
|
3983
|
+
if (typeof value !== "string" || !allowEmpty && !value.trim()) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32`);
|
|
3807
3984
|
const invalidControl = allowNewlines ? /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/u : /[\u0000-\u001f\u007f]/u;
|
|
3808
|
-
if (invalidControl.test(value)) throw
|
|
3985
|
+
if (invalidControl.test(value)) throw invalid2(`${path} \u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26`);
|
|
3809
3986
|
return value;
|
|
3810
3987
|
}
|
|
3811
3988
|
function optionalText(value, path, allowNewlines = false) {
|
|
@@ -3827,23 +4004,23 @@ function meta(value, path) {
|
|
|
3827
4004
|
});
|
|
3828
4005
|
}
|
|
3829
4006
|
function flag(value, path) {
|
|
3830
|
-
if (typeof value !== "boolean") throw
|
|
4007
|
+
if (typeof value !== "boolean") throw invalid2(`${path} \u5FC5\u987B\u662F boolean`);
|
|
3831
4008
|
return value;
|
|
3832
4009
|
}
|
|
3833
4010
|
function timestamp(value, path) {
|
|
3834
|
-
if (!Number.isSafeInteger(value) || value < 0) throw
|
|
4011
|
+
if (!Number.isSafeInteger(value) || value < 0) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6BEB\u79D2\u65F6\u95F4\u6233`);
|
|
3835
4012
|
return value;
|
|
3836
4013
|
}
|
|
3837
4014
|
function nullableText(value, path) {
|
|
3838
4015
|
return value === null ? null : safeText(value, path);
|
|
3839
4016
|
}
|
|
3840
4017
|
function nonNegativeInteger(value, path) {
|
|
3841
|
-
if (!Number.isSafeInteger(value) || value < 0) throw
|
|
4018
|
+
if (!Number.isSafeInteger(value) || value < 0) throw invalid2(`${path} \u5FC5\u987B\u662F\u975E\u8D1F\u6574\u6570`);
|
|
3842
4019
|
return value;
|
|
3843
4020
|
}
|
|
3844
4021
|
function auditStatus(value, path) {
|
|
3845
4022
|
if (value !== "auditing" && value !== "approved" && value !== "rejected") {
|
|
3846
|
-
throw
|
|
4023
|
+
throw invalid2(`${path} \u5FC5\u987B\u662F auditing\u3001approved \u6216 rejected`);
|
|
3847
4024
|
}
|
|
3848
4025
|
return value;
|
|
3849
4026
|
}
|
|
@@ -3891,7 +4068,7 @@ async function boundedJson(response) {
|
|
|
3891
4068
|
total += item.value.byteLength;
|
|
3892
4069
|
if (total > MAX_RESPONSE_BYTES) {
|
|
3893
4070
|
void reader.cancel().catch(() => void 0);
|
|
3894
|
-
throw
|
|
4071
|
+
throw invalid2("\u5E73\u53F0\u54CD\u5E94\u8D85\u8FC7 1 MiB");
|
|
3895
4072
|
}
|
|
3896
4073
|
chunks.push(item.value);
|
|
3897
4074
|
}
|
|
@@ -3907,7 +4084,7 @@ async function boundedJson(response) {
|
|
|
3907
4084
|
try {
|
|
3908
4085
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
3909
4086
|
} catch {
|
|
3910
|
-
throw
|
|
4087
|
+
throw invalid2("\u5E73\u53F0\u54CD\u5E94\u4E0D\u662F\u6709\u6548 JSON");
|
|
3911
4088
|
}
|
|
3912
4089
|
}
|
|
3913
4090
|
function serverError(response, body) {
|
|
@@ -3978,7 +4155,7 @@ var HttpDeveloperPlatformClient = class {
|
|
|
3978
4155
|
const mediaType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
3979
4156
|
if (mediaType !== "application/json") {
|
|
3980
4157
|
await response.body?.cancel().catch(() => void 0);
|
|
3981
|
-
throw
|
|
4158
|
+
throw invalid2(`\u5E73\u53F0\u54CD\u5E94 Content-Type \u65E0\u6548\uFF08HTTP ${response.status}\uFF09`);
|
|
3982
4159
|
}
|
|
3983
4160
|
const payload = await boundedJson(response);
|
|
3984
4161
|
if (!response.ok) throw serverError(response, payload);
|
|
@@ -4003,7 +4180,7 @@ var HttpDeveloperPlatformClient = class {
|
|
|
4003
4180
|
}
|
|
4004
4181
|
async listBuddies() {
|
|
4005
4182
|
const source = object3(await this.#request("/cli/buddies", "GET"), "response");
|
|
4006
|
-
if (!Array.isArray(source.buddies)) throw
|
|
4183
|
+
if (!Array.isArray(source.buddies)) throw invalid2("response.buddies \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
4007
4184
|
return Object.freeze({
|
|
4008
4185
|
buddies: Object.freeze(source.buddies.map((item) => buddy(item, false)))
|
|
4009
4186
|
});
|
|
@@ -4023,7 +4200,7 @@ var HttpDeveloperPlatformClient = class {
|
|
|
4023
4200
|
`/cli/buddies/${encodeURIComponent(request.id)}/packages${suffix}`,
|
|
4024
4201
|
"GET"
|
|
4025
4202
|
), "response");
|
|
4026
|
-
if (!Array.isArray(source.items)) throw
|
|
4203
|
+
if (!Array.isArray(source.items)) throw invalid2("response.items \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
4027
4204
|
return Object.freeze({
|
|
4028
4205
|
total: nonNegativeInteger(source.total, "response.total"),
|
|
4029
4206
|
page: nonNegativeInteger(source.page, "response.page"),
|
|
@@ -4059,7 +4236,7 @@ var HttpDeveloperPlatformClient = class {
|
|
|
4059
4236
|
}
|
|
4060
4237
|
async logout(accessToken) {
|
|
4061
4238
|
const source = object3(await this.#request("/cli/auth/logout", "POST", { accessToken }), "response");
|
|
4062
|
-
if (source.ok !== true) throw
|
|
4239
|
+
if (source.ok !== true) throw invalid2("response.ok \u5FC5\u987B\u662F true");
|
|
4063
4240
|
}
|
|
4064
4241
|
};
|
|
4065
4242
|
|
|
@@ -4634,8 +4811,8 @@ async function runCloudCommand(command, args, io, options = {}) {
|
|
|
4634
4811
|
var CLOUD_COMMAND_HELP = HELP;
|
|
4635
4812
|
|
|
4636
4813
|
// packages/cli-core/src/migration/index.ts
|
|
4637
|
-
import { lstat as lstat9, open as
|
|
4638
|
-
import { extname, isAbsolute as isAbsolute2, join as
|
|
4814
|
+
import { lstat as lstat9, open as open5, readdir as readdir4, realpath as realpath3, stat } from "node:fs/promises";
|
|
4815
|
+
import { extname, isAbsolute as isAbsolute2, join as join13, relative, resolve as resolve14, sep, win32 as win322 } from "node:path";
|
|
4639
4816
|
var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
|
|
4640
4817
|
maxFiles: 128,
|
|
4641
4818
|
maxFileBytes: 256 * 1024,
|
|
@@ -4804,7 +4981,7 @@ async function existingProjectRoot(value) {
|
|
|
4804
4981
|
}
|
|
4805
4982
|
}
|
|
4806
4983
|
async function existingSkillRoot(projectRoot, skillPath) {
|
|
4807
|
-
const candidate = skillPath === "." ? projectRoot :
|
|
4984
|
+
const candidate = skillPath === "." ? projectRoot : join13(projectRoot, ...skillPath.split("/"));
|
|
4808
4985
|
try {
|
|
4809
4986
|
await lstat9(candidate);
|
|
4810
4987
|
} catch (cause) {
|
|
@@ -4841,7 +5018,7 @@ async function existingSkillRoot(projectRoot, skillPath) {
|
|
|
4841
5018
|
}
|
|
4842
5019
|
async function assertEntrypoint(context) {
|
|
4843
5020
|
const entryPath = reportChild(context.skillPath, "SKILL.md");
|
|
4844
|
-
const candidate =
|
|
5021
|
+
const candidate = join13(context.skillRoot, "SKILL.md");
|
|
4845
5022
|
try {
|
|
4846
5023
|
await lstat9(candidate);
|
|
4847
5024
|
const target = await realpath3(candidate);
|
|
@@ -4945,7 +5122,7 @@ async function walkDirectory(actualDirectory, reportDirectory, ancestors, contex
|
|
|
4945
5122
|
}
|
|
4946
5123
|
for (const entry2 of entries) {
|
|
4947
5124
|
const childReportPath = reportChild(reportDirectory, entry2.name);
|
|
4948
|
-
const childPath =
|
|
5125
|
+
const childPath = join13(directory, entry2.name);
|
|
4949
5126
|
let target;
|
|
4950
5127
|
try {
|
|
4951
5128
|
target = await realpath3(childPath);
|
|
@@ -4987,7 +5164,7 @@ async function scanFile(actualPath, reportPath, context) {
|
|
|
4987
5164
|
}
|
|
4988
5165
|
let handle;
|
|
4989
5166
|
try {
|
|
4990
|
-
handle = await
|
|
5167
|
+
handle = await open5(actualPath, "r");
|
|
4991
5168
|
} catch (cause) {
|
|
4992
5169
|
return rejectScan("SKILL_SCAN_IO_ERROR", reportPath, "\u65E0\u6CD5\u6253\u5F00 Skill \u6587\u4EF6\u3002", cause);
|
|
4993
5170
|
}
|
|
@@ -5400,8 +5577,8 @@ async function scanExternalSkillPortability(options) {
|
|
|
5400
5577
|
|
|
5401
5578
|
// packages/cli-core/src/push/preflight.ts
|
|
5402
5579
|
import { createHash as createHash8 } from "node:crypto";
|
|
5403
|
-
import { lstat as lstat10, open as
|
|
5404
|
-
import { isAbsolute as isAbsolute3, join as
|
|
5580
|
+
import { lstat as lstat10, open as open6, readdir as readdir5, realpath as realpath4 } from "node:fs/promises";
|
|
5581
|
+
import { isAbsolute as isAbsolute3, join as join14, relative as relative2, resolve as resolve15, sep as sep2, win32 as win323 } from "node:path";
|
|
5405
5582
|
|
|
5406
5583
|
// packages/cli-core/src/push/errors.ts
|
|
5407
5584
|
var PushPreflightError = class extends Error {
|
|
@@ -5620,7 +5797,7 @@ async function canonicalProjectRoot(projectRoot) {
|
|
|
5620
5797
|
}
|
|
5621
5798
|
}
|
|
5622
5799
|
async function captureConfigWithinLimit(projectRoot, maxFileBytes, filename) {
|
|
5623
|
-
const path =
|
|
5800
|
+
const path = join14(projectRoot, filename);
|
|
5624
5801
|
let entry2;
|
|
5625
5802
|
try {
|
|
5626
5803
|
entry2 = await lstat10(path);
|
|
@@ -5730,7 +5907,7 @@ function sameFileIdentity(left, right) {
|
|
|
5730
5907
|
return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs;
|
|
5731
5908
|
}
|
|
5732
5909
|
async function hashRegularFile(options) {
|
|
5733
|
-
const handle = await
|
|
5910
|
+
const handle = await open6(options.absolutePath, "r").catch((cause) => error({
|
|
5734
5911
|
code: "PUSH_PROJECT_INVALID",
|
|
5735
5912
|
path: options.portablePath,
|
|
5736
5913
|
message: `\u65E0\u6CD5\u8BFB\u53D6\u63D0\u4EA4\u6587\u4EF6\uFF1A${options.portablePath}`,
|
|
@@ -5823,7 +6000,7 @@ async function createManifest(options) {
|
|
|
5823
6000
|
sensitiveEntriesExcluded += 1;
|
|
5824
6001
|
continue;
|
|
5825
6002
|
}
|
|
5826
|
-
const absolutePath =
|
|
6003
|
+
const absolutePath = join14(directory, name);
|
|
5827
6004
|
let entry2;
|
|
5828
6005
|
try {
|
|
5829
6006
|
entry2 = await lstat10(absolutePath);
|
|
@@ -6049,11 +6226,12 @@ function assertOfficialProjectIncluded(files) {
|
|
|
6049
6226
|
message: `package.json \u7684 dependencies \u5FC5\u987B\u58F0\u660E ${BUDDY_RUNTIME_PACKAGE} \u7684\u51C6\u786E\u7248\u672C\uFF0C\u5E76\u63D0\u4EA4\u76F8\u5E94\u9501\u6587\u4EF6\u3002`
|
|
6050
6227
|
});
|
|
6051
6228
|
}
|
|
6052
|
-
|
|
6229
|
+
const expectedStart = `node ${runtimeUsesEnvironmentIdentity(pkg) ? "--env-file-if-exists=.env " : ""}${BUDDY_PLATFORM_START_ENTRY}`;
|
|
6230
|
+
if (typeof pkg !== "object" || pkg === null || Array.isArray(pkg) || !("scripts" in pkg) || typeof pkg.scripts !== "object" || pkg.scripts === null || !("start" in pkg.scripts) || pkg.scripts.start !== expectedStart) {
|
|
6053
6231
|
error({
|
|
6054
6232
|
code: "PUSH_PROJECT_INVALID",
|
|
6055
6233
|
path: BUDDY_PLATFORM_PACKAGE_JSON,
|
|
6056
|
-
message: `\u5B98\u65B9 Runtime \u5DE5\u7A0B\u7684 package.json \u5FC5\u987B\u8BBE\u7F6E scripts.start \u4E3A "
|
|
6234
|
+
message: `\u5B98\u65B9 Runtime \u5DE5\u7A0B\u7684 package.json \u5FC5\u987B\u8BBE\u7F6E scripts.start \u4E3A "${expectedStart}"\uFF0C\u4F7F\u4E91\u7AEF\u4E0E\u672C\u5730\u4F7F\u7528\u540C\u4E00\u542F\u52A8\u5165\u53E3\u3002`
|
|
6057
6235
|
});
|
|
6058
6236
|
}
|
|
6059
6237
|
}
|
|
@@ -6075,7 +6253,7 @@ async function assertCapturedConfigStable(options) {
|
|
|
6075
6253
|
}
|
|
6076
6254
|
let current;
|
|
6077
6255
|
try {
|
|
6078
|
-
const path =
|
|
6256
|
+
const path = join14(options.projectRoot, options.filename);
|
|
6079
6257
|
const entry2 = await lstat10(path);
|
|
6080
6258
|
if (!entry2.isFile() || entry2.isSymbolicLink()) {
|
|
6081
6259
|
error({
|
|
@@ -6206,7 +6384,7 @@ async function createPushPreflight(options) {
|
|
|
6206
6384
|
// packages/cli-core/src/push/bundle.ts
|
|
6207
6385
|
import { createHash as createHash9 } from "node:crypto";
|
|
6208
6386
|
import { lstat as lstat11, readFile as readFile11, realpath as realpath5 } from "node:fs/promises";
|
|
6209
|
-
import { join as
|
|
6387
|
+
import { join as join15, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
|
|
6210
6388
|
import { Writable } from "node:stream";
|
|
6211
6389
|
import { pipeline } from "node:stream/promises";
|
|
6212
6390
|
import { createGzip } from "node:zlib";
|
|
@@ -6228,7 +6406,7 @@ function inside(root, target) {
|
|
|
6228
6406
|
return path === "" || path !== ".." && !path.startsWith(`..${sep3}`) && !path.startsWith("/") && !win324.isAbsolute(path);
|
|
6229
6407
|
}
|
|
6230
6408
|
async function capture(root, file) {
|
|
6231
|
-
const absolute =
|
|
6409
|
+
const absolute = join15(root, ...file.path.split("/"));
|
|
6232
6410
|
try {
|
|
6233
6411
|
const entry2 = await lstat11(absolute);
|
|
6234
6412
|
if (!entry2.isFile() || entry2.isSymbolicLink() || entry2.size !== file.bytes) {
|
|
@@ -6687,7 +6865,7 @@ async function resumeProjectArguments(args, cwd, options) {
|
|
|
6687
6865
|
await assertInitializableBuddyTarget(root);
|
|
6688
6866
|
let entry2;
|
|
6689
6867
|
try {
|
|
6690
|
-
entry2 = await lstat12(
|
|
6868
|
+
entry2 = await lstat12(join16(root, "buddy.agent.json"));
|
|
6691
6869
|
} catch (cause) {
|
|
6692
6870
|
if (cause.code === "ENOENT") {
|
|
6693
6871
|
const draft = await readMetaDraft(root);
|
|
@@ -6942,6 +7120,7 @@ export {
|
|
|
6942
7120
|
isSafeProjectRelativePath,
|
|
6943
7121
|
isWindowsReservedPathSegment,
|
|
6944
7122
|
latestRuntimeTemplate,
|
|
7123
|
+
migrateRuntimeStartup,
|
|
6945
7124
|
normalizePlatformUrl,
|
|
6946
7125
|
openExternalUrl,
|
|
6947
7126
|
parseBuddyAgentConfig,
|