@my-life-buddies/cli 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/core.js CHANGED
@@ -17,7 +17,7 @@ function runModelsCommand(args, io) {
17
17
  } else if (args.length === 1 && args[0] === "--json") {
18
18
  io.write(JSON.stringify({ models: MODEL_IDS }, null, 2));
19
19
  } else if (args.length === 0) {
20
- io.write("CLI \u5185\u7F6E\u6A21\u578B\u76EE\u5F55\uFF08Runtime 0.11.0\uFF09\uFF1A");
20
+ io.write("CLI \u5185\u7F6E\u6A21\u578B\u76EE\u5F55\uFF08Runtime 0.12.0\uFF09\uFF1A");
21
21
  for (const id of MODEL_IDS) io.write(`- ${id}`);
22
22
  io.write("\u5C06\u6240\u9009 ID \u5199\u5165 buddy.agent.json.model\uFF1B\u672A\u8BBE\u7F6E\u65F6\u6A21\u677F\u4F7F\u7528 kimi-k2.6\u3002\u81EA\u5B9A\u4E49\u4F1A\u8BDD\u5DE5\u5382\u4E5F\u53EF\u6309\u4F1A\u8BDD\u8BBE\u7F6E initialState.model\u3002");
23
23
  } else {
@@ -1462,11 +1462,13 @@ Tool \u548C Hook \u662F Runtime \u7684\u6269\u5C55\u70B9\uFF1BService \u53EA\u66
1462
1462
 
1463
1463
  \u5E73\u53F0\u80FD\u529B\u8981\u4EE5\u5B9E\u9645\u63A5\u5165\u4E3A\u51C6\u3002\u5F53\u524D Runtime \u63D0\u4F9B\u4F1A\u8BDD\u6D88\u606F\u3001Memory\u3001\u6388\u6743\u6570\u636E\u3001\u5C0F\u6302\u4EF6\u548C\u672C\u5730 Markdown \u8D44\u6599\u80FD\u529B\uFF1B\u6CA1\u6709\u63A5\u901A\u7684 Files\u3001Knowledge \u4E0D\u80FD\u56E0\u624B\u518C\u63D0\u5230\u5C31\u5BA3\u79F0\u53EF\u7528\u3002\u666E\u901A Tool \u4E5F\u4E0D\u4EE3\u8868\u5DF2\u7ECF\u63D0\u4F9B\u5B9A\u65F6\u3001\u957F\u671F\u4EFB\u52A1\u3001\u540E\u53F0\u8C03\u5EA6\u6216\u4E3B\u52A8\u89E6\u8FBE\u3002\u624B\u518C\u63CF\u8FF0\u7684\u4ED8\u8D39\u3001\u53D1\u5E03\u7B49\u670D\u52A1\u8BBE\u8BA1\u4E5F\u4E0D\u6784\u6210\u6267\u884C\u6536\u8D39\u6216\u53D1\u5E03\u52A8\u4F5C\u7684\u6388\u6743\u3002
1464
1464
 
1465
- \u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002Runtime 0.11.0 \u542B 10 \u9879\uFF0CCLI \u4E0D\u590D\u5236\u679A\u4E3E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`buddy.agent.json.datasets\`\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0C\u7528\u9014\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u6700\u591A 200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
1465
+ \u9700\u8981\u7528\u6237\u6570\u636E\u65F6\uFF0C\u5148\u5728\u5DE5\u7A0B\u76EE\u5F55\u6267\u884C \`buddy-cli datasets\`\uFF08\u811A\u672C\u53EF\u7528 \`--json\`\uFF09\uFF0C\u4ECE\u5F53\u524D\u5B89\u88C5\u7684 Runtime \u5BFC\u51FA\u8BFB\u53D6\u5168\u90E8\u6570\u636E\u96C6\uFF1B\u4E0D\u8981\u6C42\u767B\u5F55\uFF0C\u4E0D\u4ECE Server \u62C9\u76EE\u5F55\u3002Runtime 0.12.0 \u542B 10 \u9879\uFF0CCLI \u4E0D\u590D\u5236\u679A\u4E3E\u3002\u628A\u5B9E\u9645\u9700\u8981\u7684 \`id\` \u548C\u7528\u9014 \`purpose\` \u5199\u5165 \`buddy.agent.json.datasets\`\uFF0C\u540C\u4E00 ID \u53EA\u5199\u4E00\u6B21\uFF0C\u7528\u9014\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u6700\u591A 200 \u5B57\uFF1B\u65E0\u9700\u6C42\u65F6\u4FDD\u7559\u7A7A\u6570\u7EC4\u3002DEV \u548C\u58F0\u660E\u975E\u7A7A\u65F6\u7684 push \u9884\u68C0\u7528\u8FD9\u4EFD\u5DE5\u7A0B\u4F9D\u8D56\u6821\u9A8C ID\uFF1B\u9700\u8981\u5148\u5B89\u88C5\u4E0E package.json \u51C6\u786E\u7248\u672C\u4E00\u81F4\u7684 Runtime\u3002\u6E05\u5355\u58F0\u660E\u6570\u91CF\u4E0D\u7B49\u4E8E\u5355\u6B21\u67E5\u8BE2\u4E0A\u9650\uFF0C\u5F53\u524D\u4E00\u6B21\u67E5\u8BE2\u6700\u591A 8 \u9879\u3002
1466
1466
 
1467
1467
  \`start.mjs\` \u5C06\u58F0\u660E\u4EA4\u7ED9 \`StartOptions.dataRequirements\`\u3002Runtime \u5728\u5B9E\u9645\u6570\u636E\u67E5\u8BE2\u3001HealthKit \u6388\u6743\u548C\u4E3B\u52A8\u670D\u52A1\u8BF7\u6C42\u4E2D\u643A\u5E26\u5B8C\u6574\u58F0\u660E\uFF0C\u7531 Server \u6821\u9A8C\u8303\u56F4\u4E0E\u7528\u6237\u540C\u610F\uFF1B\u586B\u5199\u914D\u7F6E\u4E0D\u8868\u793A\u5DF2\u7ECF\u6388\u6743\u3002\u670D\u52A1\u7AEF\u4ECE\u4E0A\u4F20\u5305\u89E3\u6790\u5E76\u7ED1\u5B9A\u53D1\u5E03\u7248\u672C\u4ECD\u5F85\u5B9E\u73B0\u3002
1468
1468
 
1469
- \u6A21\u578B\u9700\u8981\u67E5\u6570\u636E\u65F6\uFF0C\u5728 \`src/buddy-options.mjs\` \u7684 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.data_access_query\`\uFF1B\u9700\u8981\u5411\u7528\u6237\u7533\u8BF7\u65F6\u52A0\u5165 \`conversation.tools.data_access_request\`\uFF0C\u4F4D\u7F6E\u3001\u65E5\u5386\u7684\u4E00\u6B21\u6027\u7ED3\u679C\u901A\u8FC7 \`data_access_read_result\` \u8BFB\u53D6\uFF0CHealthKit \u5219\u91CD\u65B0\u67E5\u8BE2 Dataset\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query/request/readResult\`\u3002\u5DE5\u7A0B\u6A21\u677F\u5DF2\u9501\u5B9A npm Runtime 0.11.0\u3002
1469
+ \u6A21\u578B\u9700\u8981\u67E5\u6570\u636E\u65F6\uFF0C\u5728 \`src/buddy-options.mjs\` \u7684 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.data_access_query\`\uFF1B\u9700\u8981\u5411\u7528\u6237\u7533\u8BF7\u65F6\u52A0\u5165 \`conversation.tools.data_access_request\`\uFF0C\u4F4D\u7F6E\u3001\u65E5\u5386\u7684\u4E00\u6B21\u6027\u7ED3\u679C\u901A\u8FC7 \`data_access_read_result\` \u8BFB\u53D6\uFF0CHealthKit \u5219\u91CD\u65B0\u67E5\u8BE2 Dataset\u3002\u4E1A\u52A1\u4EE3\u7801\u5BF9\u5E94\u4F7F\u7528 \`conversation.dataAccess.query/request/readResult\`\u3002\u5DE5\u7A0B\u6A21\u677F\u5DF2\u9501\u5B9A npm Runtime 0.12.0\u3002
1470
+
1471
+ \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
1470
1472
 
1471
1473
  \u9700\u8981\u7528\u6237\u4ECE\u51E0\u4E2A\u9009\u9879\u4E2D\u9009\u62E9\u65F6\uFF0C\u5728 \`initialState.tools\` \u4E2D\u52A0\u5165 \`conversation.tools.ask_question\` \u5E76\u5728\u4EBA\u8BBE\u4E2D\u8BF4\u660E\u9002\u7528\u573A\u666F\u3002\u53D1\u9898\u5361\u6216\u6388\u6743\u5361\u540E\uFF0C\u672C\u8F6E\u7ED3\u675F\u5E76\u7B49\u5F85\u7528\u6237\uFF1BPreview \u80FD\u663E\u793A\u9009\u9879\u6587\u5B57\u5E76\u53D1\u9001\u7528\u6237\u7684\u6587\u5B57\u56DE\u7B54\uFF0C\u7CFB\u7EDF\u6570\u636E\u6388\u6743\u9700\u8981\u5728 App \u4E2D\u5B8C\u6210\u3002\u6A21\u677F\u7684 \`initialState.tools\` \u9ED8\u8BA4\u4E3A\u7A7A\u6570\u7EC4\uFF0C\u53EA\u52A0\u5165\u4E1A\u52A1\u5B9E\u9645\u9700\u8981\u7684\u5DE5\u5177\uFF1B\u8D44\u6599\u76EE\u5F55\u901A\u8FC7 \`resource_list\` \u53D1\u73B0\uFF0C\u4E0D\u81EA\u52A8\u6CE8\u5165\u7CFB\u7EDF\u63D0\u793A\u3002\u65B0\u4F1A\u8BDD\u7684\u95EE\u5019\u7531\u6A21\u578B\u6309\u4EBA\u8BBE\u751F\u6210\uFF0C\u4E0D\u53E6\u8BBE\u9759\u6001\u6B22\u8FCE\u8BED\u914D\u7F6E\u3002
1472
1474
 
@@ -1746,7 +1748,7 @@ function validateBuddyAvatar(value) {
1746
1748
  if (value !== null) {
1747
1749
  let valid = false;
1748
1750
  if (typeof value === "string" && value.length > 0 && value.length <= 2048 && !/[\s\u0000-\u001f]/u.test(value)) {
1749
- valid = /^\/media\/[A-Za-z0-9_.-]+$/u.test(value);
1751
+ valid = /^\/media\/[A-Za-z0-9_.-]+(?:\?v=[a-f0-9]{16})?$/u.test(value);
1750
1752
  if (!valid) {
1751
1753
  try {
1752
1754
  const url = new URL(value);
@@ -1758,6 +1760,10 @@ function validateBuddyAvatar(value) {
1758
1760
  if (!valid) invalidRequest("avatar \u5FC5\u987B\u4E3A\u5408\u6CD5\u56FE\u7247\u5730\u5740\u6216 null");
1759
1761
  }
1760
1762
  }
1763
+ function validateBuddyMetaUpdate(meta2) {
1764
+ if (meta2.avatar !== void 0 && meta2.avatar !== null) invalidRequest("\u5934\u50CF\u5730\u5740\u7531\u5E73\u53F0\u751F\u6210\uFF0C\u8BF7\u4E0A\u4F20\u56FE\u7247\u6587\u4EF6\u6216\u4F20 null \u6E05\u9664");
1765
+ if (Object.keys(meta2).some((key) => key !== "avatar")) validateBuddyMeta(meta2);
1766
+ }
1761
1767
 
1762
1768
  // packages/cli-core/src/commands/dev.ts
1763
1769
  import { resolve as resolve11 } from "node:path";
@@ -2915,6 +2921,33 @@ async function runDevCommand(args, io, options = {}) {
2915
2921
  // packages/cli-core/src/commands/cloud.ts
2916
2922
  import { resolve as resolve12 } from "node:path";
2917
2923
 
2924
+ // packages/cli-core/src/cloud/avatar.ts
2925
+ import { open as open3 } from "node:fs/promises";
2926
+ import { basename } from "node:path";
2927
+ var MAX_BUDDY_AVATAR_BYTES = 5 * 1024 * 1024;
2928
+ async function readBuddyAvatarFile(path) {
2929
+ const file2 = await open3(path, "r");
2930
+ try {
2931
+ const stat2 = await file2.stat();
2932
+ if (!stat2.isFile()) throw new Error("\u5934\u50CF\u5FC5\u987B\u662F\u666E\u901A\u56FE\u7247\u6587\u4EF6");
2933
+ if (!stat2.size || stat2.size > MAX_BUDDY_AVATAR_BYTES) throw new Error("\u5934\u50CF\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u4E0D\u80FD\u8D85\u8FC7 5 MiB");
2934
+ const buffer = Buffer.alloc(MAX_BUDDY_AVATAR_BYTES + 1);
2935
+ let size = 0;
2936
+ while (size < buffer.length) {
2937
+ const { bytesRead } = await file2.read(buffer, size, buffer.length - size, null);
2938
+ if (!bytesRead) break;
2939
+ size += bytesRead;
2940
+ }
2941
+ if (!size || size > MAX_BUDDY_AVATAR_BYTES) throw new Error("\u5934\u50CF\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u4E0D\u80FD\u8D85\u8FC7 5 MiB");
2942
+ const bytes = buffer.subarray(0, size);
2943
+ const mediaType = bytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10])) ? "image/png" : bytes.subarray(0, 3).equals(Buffer.from([255, 216, 255])) ? "image/jpeg" : bytes.toString("ascii", 0, 4) === "RIFF" && bytes.toString("ascii", 8, 12) === "WEBP" ? "image/webp" : void 0;
2944
+ if (!mediaType) throw new Error("\u4EC5\u652F\u6301 PNG\u3001JPEG\u3001WebP \u56FE\u7247\u6587\u4EF6");
2945
+ return { bytes, fileName: basename(path), mediaType };
2946
+ } finally {
2947
+ await file2.close();
2948
+ }
2949
+ }
2950
+
2918
2951
  // packages/cli-core/src/cloud/auth.ts
2919
2952
  import { randomUUID as randomUUID4 } from "node:crypto";
2920
2953
 
@@ -3253,7 +3286,7 @@ var HttpDeveloperPlatformClient = class {
3253
3286
  "Content-Length": String(binaryBody.byteLength)
3254
3287
  }
3255
3288
  },
3256
- ...options.json !== void 0 ? { body: JSON.stringify(options.json) } : binaryBody === void 0 ? {} : { body: binaryBody },
3289
+ ...options.form !== void 0 ? { body: options.form } : options.json !== void 0 ? { body: JSON.stringify(options.json) } : binaryBody === void 0 ? {} : { body: binaryBody },
3257
3290
  redirect: "error",
3258
3291
  signal: controller.signal
3259
3292
  });
@@ -3280,7 +3313,14 @@ var HttpDeveloperPlatformClient = class {
3280
3313
  return buddy(await this.#request("/cli/buddies", "POST", { json: { meta: request.meta } }), true);
3281
3314
  }
3282
3315
  async updateBuddy(request) {
3283
- validateBuddyMeta(request.meta);
3316
+ validateBuddyMetaUpdate(request.meta);
3317
+ if (request.avatar) {
3318
+ if (request.meta.avatar === null) throw new CloudLifecycleError("INVALID_REQUEST", "\u4E0D\u80FD\u540C\u65F6\u4E0A\u4F20\u548C\u6E05\u9664\u5934\u50CF");
3319
+ const form = new FormData();
3320
+ form.set("meta", JSON.stringify(request.meta));
3321
+ form.set("avatar", new Blob([new Uint8Array(request.avatar.bytes)], { type: request.avatar.mediaType }), request.avatar.fileName);
3322
+ return buddy(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/meta`, "PUT", { form }), true);
3323
+ }
3284
3324
  return buddy(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/meta`, "PUT", {
3285
3325
  json: request.meta
3286
3326
  }), true);
@@ -3711,7 +3751,7 @@ var SystemCloudTokenStore = class {
3711
3751
  };
3712
3752
 
3713
3753
  // packages/cli-core/src/cloud/mock-client.ts
3714
- import { randomBytes as randomBytes2 } from "node:crypto";
3754
+ import { createHash as createHash5, randomBytes as randomBytes2 } from "node:crypto";
3715
3755
  var MockDeveloperPlatformClient = class {
3716
3756
  #now;
3717
3757
  #buddies = /* @__PURE__ */ new Map();
@@ -3737,7 +3777,10 @@ var MockDeveloperPlatformClient = class {
3737
3777
  }
3738
3778
  async updateBuddy(request) {
3739
3779
  const current = this.#require(request.id);
3740
- const next = this.#value({ ...current, meta: request.meta, updatedAt: this.#now() });
3780
+ validateBuddyMetaUpdate(request.meta);
3781
+ const onlyAvatar = Object.keys(request.meta).every((key) => key === "avatar");
3782
+ const avatar = request.avatar ? `/media/avatar-${request.id}.webp?v=${createHash5("sha256").update(request.avatar.bytes).digest("hex").slice(0, 16)}` : request.meta.avatar === null ? null : current.meta?.avatar ?? null;
3783
+ const next = this.#value({ ...current, meta: { ...onlyAvatar ? current.meta : request.meta, avatar }, updatedAt: this.#now() });
3741
3784
  this.#buddies.set(request.id, next);
3742
3785
  return structuredClone(next);
3743
3786
  }
@@ -3823,9 +3866,9 @@ var HELP = Object.freeze({
3823
3866
  logout: "\u7528\u6CD5: buddy-cli logout",
3824
3867
  push: "\u7528\u6CD5: buddy-cli push [--directory <\u9879\u76EE\u76EE\u5F55>] [--commit <\u672C\u6B21\u6539\u52A8\u8BF4\u660E>]",
3825
3868
  status: "\u7528\u6CD5: buddy-cli status [--directory <\u9879\u76EE\u76EE\u5F55>]",
3826
- avatar: `\u7528\u6CD5: buddy-cli avatar (--url <\u56FE\u7247\u5730\u5740> | --clear) [--directory <\u9879\u76EE\u76EE\u5F55> | --buddy-id <\u642D\u5B50 ID>]
3869
+ avatar: `\u7528\u6CD5: buddy-cli avatar (--file <\u56FE\u7247\u6587\u4EF6> | --clear) [--directory <\u9879\u76EE\u76EE\u5F55> | --buddy-id <\u642D\u5B50 ID>]
3827
3870
  \u4FEE\u6539\u5F53\u524D\u9879\u76EE\u6216\u6307\u5B9A\u642D\u5B50\u7684\u4E91\u7AEF\u5934\u50CF\uFF0C\u4FDD\u7559\u5176\u4ED6\u8D44\u6599\uFF1B\u4E0D\u9700\u8981\u5B89\u88C5 Runtime \u6216\u4E0A\u4F20\u4EE3\u7801\u5305\u3002
3828
- --url \u63A5\u53D7 HTTP(S) \u56FE\u7247 URL \u6216\u5DF2\u6709\u7684 /media/... \u5730\u5740\uFF0C\u4E0D\u63A5\u53D7\u672C\u5730\u6587\u4EF6\u3002
3871
+ --file \u63A5\u53D7\u672C\u5730\u9759\u6001 PNG\u3001JPEG\u3001WebP \u56FE\u7247\uFF0C\u6700\u5927 5 MiB\uFF1BServer \u81EA\u52A8\u5904\u7406\u5E76\u751F\u6210\u5730\u5740\u3002
3829
3872
  \u9700\u8981\u5F53\u524D\u8D26\u53F7\u62E5\u6709\u8BE5\u642D\u5B50\uFF0C\u547D\u4EE4\u6267\u884C\u540E\u7ACB\u5373\u66F4\u65B0\u4E91\u7AEF\u8D44\u6599\u3002`
3830
3873
  });
3831
3874
  function parse2(args, command) {
@@ -3843,7 +3886,7 @@ function parse2(args, command) {
3843
3886
  values.set(flag2, "");
3844
3887
  continue;
3845
3888
  }
3846
- const allowed = command === "push" ? flag2 === "--directory" || flag2 === "--commit" : command === "avatar" ? ["--directory", "--buddy-id", "--url"].includes(flag2) : command === "status" && flag2 === "--directory";
3889
+ const allowed = command === "push" ? flag2 === "--directory" || flag2 === "--commit" : command === "avatar" ? ["--directory", "--buddy-id", "--file"].includes(flag2) : command === "status" && flag2 === "--directory";
3847
3890
  if (!allowed) throw new CloudCommandUsageError(`\u672A\u77E5\u53C2\u6570 ${flag2}`);
3848
3891
  const value = args[index + 1];
3849
3892
  if (value === void 0 || !value.trim() || command === "avatar" && value.startsWith("--")) throw new CloudCommandUsageError(`${flag2} \u7F3A\u5C11\u503C`);
@@ -3955,17 +3998,18 @@ async function runPush(parsed, io, options) {
3955
3998
  return { exitCode: 0, buddyId: config.buddyId, version: receipt.version };
3956
3999
  }
3957
4000
  async function runAvatar(parsed, io, options) {
3958
- if (parsed.values.has("--url") === parsed.values.has("--clear")) {
3959
- throw new CloudCommandUsageError("\u5FC5\u987B\u9009\u62E9 --url <\u56FE\u7247\u5730\u5740> \u6216 --clear\uFF0C\u4E14\u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
4001
+ if (parsed.values.has("--file") === parsed.values.has("--clear")) {
4002
+ throw new CloudCommandUsageError("\u5FC5\u987B\u9009\u62E9 --file <\u56FE\u7247\u6587\u4EF6> \u6216 --clear\uFF0C\u4E14\u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
3960
4003
  }
3961
4004
  if (parsed.values.has("--buddy-id") && parsed.values.has("--directory")) {
3962
4005
  throw new CloudCommandUsageError("--buddy-id \u548C --directory \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
3963
4006
  }
3964
- const avatar = parsed.values.get("--url") ?? null;
4007
+ const file2 = parsed.values.get("--file");
4008
+ let upload;
3965
4009
  try {
3966
- validateBuddyAvatar(avatar);
4010
+ upload = file2 ? await readBuddyAvatarFile(resolve12(options.cwd ?? process.cwd(), file2)) : void 0;
3967
4011
  } catch (error2) {
3968
- throw new CloudCommandUsageError(error2 instanceof Error ? error2.message : "\u5934\u50CF\u5730\u5740\u65E0\u6548");
4012
+ throw new CloudCommandUsageError(error2 instanceof Error ? error2.message : "\u65E0\u6CD5\u8BFB\u53D6\u5934\u50CF\u56FE\u7247");
3969
4013
  }
3970
4014
  let id = parsed.values.get("--buddy-id");
3971
4015
  if (id !== void 0 && !/^[A-Za-z0-9_-]{1,128}$/u.test(id)) throw new CloudCommandUsageError("--buddy-id \u5FC5\u987B\u662F\u6709\u6548\u7684\u642D\u5B50 ID");
@@ -3978,12 +4022,13 @@ async function runAvatar(parsed, io, options) {
3978
4022
  await session.token({ signal: options.signal });
3979
4023
  const current = await client.getBuddy({ id });
3980
4024
  if (current.id !== id) throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u5E73\u53F0\u8FD4\u56DE\u7684\u642D\u5B50\u8EAB\u4EFD\u4E0D\u5339\u914D");
3981
- const updated = await client.updateBuddy({ id, meta: { ...current.meta, avatar } });
3982
- if (updated.id !== id || updated.meta?.avatar !== avatar) {
4025
+ const updated = await client.updateBuddy({ id, meta: upload ? {} : { avatar: null }, ...upload ? { avatar: upload } : {} });
4026
+ const avatar = updated.meta?.avatar;
4027
+ if (updated.id !== id || (upload ? typeof avatar !== "string" || !avatar : avatar !== null)) {
3983
4028
  throw new CloudLifecycleError("PLATFORM_RESPONSE_INVALID", "\u5E73\u53F0\u672A\u786E\u8BA4\u5934\u50CF\u66F4\u65B0\uFF0C\u8BF7\u67E5\u8BE2\u642D\u5B50\u8D44\u6599\u786E\u8BA4\u7ED3\u679C");
3984
4029
  }
3985
4030
  io.write(`${avatar === null ? "\u5DF2\u6E05\u9664" : "\u5DF2\u66F4\u65B0"}\u642D\u5B50\u5934\u50CF\uFF1A${updated.meta?.name ?? id}\uFF08${id}\uFF09`);
3986
- if (avatar !== null) io.write(`\u5934\u50CF\uFF1A${avatar}`);
4031
+ if (typeof avatar === "string") io.write(`\u5934\u50CF\uFF1A${avatar}`);
3987
4032
  io.write("\u4E91\u7AEF\u8D44\u6599\u5DF2\u66F4\u65B0\uFF0C\u65E0\u9700 push \u6216\u91CD\u65B0\u53D1\u5E03\u7A0B\u5E8F\u5305\u3002");
3988
4033
  return { exitCode: 0, buddyId: id };
3989
4034
  }
@@ -4031,7 +4076,7 @@ async function runCloudCommand(command, args, io, options = {}) {
4031
4076
  var CLOUD_COMMAND_HELP = HELP;
4032
4077
 
4033
4078
  // packages/cli-core/src/migration/index.ts
4034
- import { lstat as lstat7, open as open3, readdir as readdir4, realpath as realpath4, stat } from "node:fs/promises";
4079
+ import { lstat as lstat7, open as open4, readdir as readdir4, realpath as realpath4, stat } from "node:fs/promises";
4035
4080
  import { extname, isAbsolute as isAbsolute2, join as join8, relative, resolve as resolve13, sep, win32 as win322 } from "node:path";
4036
4081
  var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
4037
4082
  maxFiles: 128,
@@ -4384,7 +4429,7 @@ async function scanFile(actualPath, reportPath, context) {
4384
4429
  }
4385
4430
  let handle;
4386
4431
  try {
4387
- handle = await open3(actualPath, "r");
4432
+ handle = await open4(actualPath, "r");
4388
4433
  } catch (cause) {
4389
4434
  return rejectScan("SKILL_SCAN_IO_ERROR", reportPath, "\u65E0\u6CD5\u6253\u5F00 Skill \u6587\u4EF6\u3002", cause);
4390
4435
  }
@@ -4796,8 +4841,8 @@ async function scanExternalSkillPortability(options) {
4796
4841
  }
4797
4842
 
4798
4843
  // packages/cli-core/src/push/preflight.ts
4799
- import { createHash as createHash5 } from "node:crypto";
4800
- import { lstat as lstat8, open as open4, readdir as readdir5, realpath as realpath5 } from "node:fs/promises";
4844
+ import { createHash as createHash6 } from "node:crypto";
4845
+ import { lstat as lstat8, open as open5, readdir as readdir5, realpath as realpath5 } from "node:fs/promises";
4801
4846
  import { isAbsolute as isAbsolute3, join as join9, relative as relative2, resolve as resolve14, sep as sep2, win32 as win323 } from "node:path";
4802
4847
 
4803
4848
  // packages/cli-core/src/push/errors.ts
@@ -4896,7 +4941,7 @@ function error(options) {
4896
4941
  throw new PushPreflightError(options);
4897
4942
  }
4898
4943
  function sha256(value) {
4899
- return `sha256:${createHash5("sha256").update(value).digest("hex")}`;
4944
+ return `sha256:${createHash6("sha256").update(value).digest("hex")}`;
4900
4945
  }
4901
4946
  function positiveLimit(value, name, hardMaximum) {
4902
4947
  if (!Number.isSafeInteger(value) || value < 1 || value > hardMaximum) {
@@ -5127,7 +5172,7 @@ function sameFileIdentity(left, right) {
5127
5172
  return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs;
5128
5173
  }
5129
5174
  async function hashRegularFile(options) {
5130
- const handle = await open4(options.absolutePath, "r").catch((cause) => error({
5175
+ const handle = await open5(options.absolutePath, "r").catch((cause) => error({
5131
5176
  code: "PUSH_PROJECT_INVALID",
5132
5177
  path: options.portablePath,
5133
5178
  message: `\u65E0\u6CD5\u8BFB\u53D6\u63D0\u4EA4\u6587\u4EF6\uFF1A${options.portablePath}`,
@@ -5142,7 +5187,7 @@ async function hashRegularFile(options) {
5142
5187
  message: `\u751F\u6210\u6E05\u5355\u65F6\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF1A${options.portablePath}`
5143
5188
  });
5144
5189
  }
5145
- const hash = createHash5("sha256");
5190
+ const hash = createHash6("sha256");
5146
5191
  const captured = [];
5147
5192
  const buffer = Buffer.allocUnsafe(READ_BUFFER_BYTES);
5148
5193
  let bytes = 0;
@@ -5607,7 +5652,7 @@ async function createPushPreflight(options) {
5607
5652
  }
5608
5653
 
5609
5654
  // packages/cli-core/src/push/bundle.ts
5610
- import { createHash as createHash6 } from "node:crypto";
5655
+ import { createHash as createHash7 } from "node:crypto";
5611
5656
  import { lstat as lstat9, readFile as readFile8, realpath as realpath6 } from "node:fs/promises";
5612
5657
  import { join as join10, relative as relative3, sep as sep3, win32 as win324 } from "node:path";
5613
5658
  import { Writable } from "node:stream";
@@ -5616,7 +5661,7 @@ import { createGzip } from "node:zlib";
5616
5661
  import { pack } from "tar-stream";
5617
5662
  var MEDIA_TYPE = "application/gzip";
5618
5663
  function digest(bytes) {
5619
- return `sha256:${createHash6("sha256").update(bytes).digest("hex")}`;
5664
+ return `sha256:${createHash7("sha256").update(bytes).digest("hex")}`;
5620
5665
  }
5621
5666
  function changed(path, message, cause) {
5622
5667
  throw new PushPreflightError({
@@ -5665,7 +5710,7 @@ async function createPushSourceBundle(plan) {
5665
5710
  schemaVersion: "1",
5666
5711
  files: files.map((file2) => ({ path: file2.path, bytes: file2.bytes, digest: file2.digest }))
5667
5712
  });
5668
- const calculatedBundleDigest = `sha256:${createHash6("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
5713
+ const calculatedBundleDigest = `sha256:${createHash7("sha256").update(`buddy-push-bundle-v1\0${descriptor}`).digest("hex")}`;
5669
5714
  if (calculatedBundleDigest !== plan.bundleDigest) {
5670
5715
  changed(plan.projectRoot, "\u63D0\u4EA4\u6E05\u5355\u8EAB\u4EFD\u5728\u6253\u5305\u524D\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C push");
5671
5716
  }
@@ -5720,12 +5765,14 @@ var HELP2 = `\u642D\u642D Developer Platform CLI
5720
5765
 
5721
5766
  \u7528\u6CD5:
5722
5767
  buddy-cli
5768
+ buddy-cli --version [--json]
5769
+ buddy-cli update [--check] [--json]
5723
5770
  buddy-cli init
5724
5771
  buddy-cli init --mode create --directory <\u9879\u76EE\u76EE\u5F55> --name <\u540D\u79F0> --tagline <\u4E00\u53E5\u8BDD\u4ECB\u7ECD> --intro <\u5B8C\u6574\u4ECB\u7ECD> [--buddy-id <\u5DF2\u6709\u642D\u5B50 ID>]
5725
5772
  buddy-cli init --mode direct --directory <\u9879\u76EE\u76EE\u5F55> --name <\u540D\u79F0> --tagline <\u4E00\u53E5\u8BDD\u4ECB\u7ECD> --intro <\u5B8C\u6574\u4ECB\u7ECD> [--buddy-id <\u5DF2\u6709\u642D\u5B50 ID>]
5726
5773
  buddy-cli dev [--app-server <URL>] [--directory <\u9879\u76EE\u76EE\u5F55>]
5727
5774
  buddy-cli login | logout | push | status
5728
- buddy-cli avatar (--url <\u56FE\u7247\u5730\u5740> | --clear) [--directory <\u9879\u76EE\u76EE\u5F55> | --buddy-id <\u642D\u5B50 ID>]
5775
+ buddy-cli avatar (--file <\u56FE\u7247\u6587\u4EF6> | --clear) [--directory <\u9879\u76EE\u76EE\u5F55> | --buddy-id <\u642D\u5B50 ID>]
5729
5776
  buddy-cli models [--json]
5730
5777
  buddy-cli widgets sync | check | verify
5731
5778
  buddy-cli datasets [--directory <\u9879\u76EE\u76EE\u5F55>] [--json]
@@ -5733,6 +5780,8 @@ var HELP2 = `\u642D\u642D Developer Platform CLI
5733
5780
  buddy-cli help
5734
5781
 
5735
5782
  \u547D\u4EE4:
5783
+ --version \u67E5\u770B\u5F53\u524D\u8FD0\u884C\u7684 CLI \u7248\u672C\uFF08\u65E0\u9700\u8054\u7F51\u6216\u767B\u5F55\uFF09
5784
+ update \u68C0\u67E5 npm \u6700\u65B0\u7248\u672C\u6216\u66F4\u65B0\u5168\u5C40 CLI\uFF08\u65E0\u9700\u767B\u5F55\u6216 Agent \u5DE5\u7A0B\uFF09
5736
5785
  init \u521B\u5EFA\u6216\u6062\u590D\u642D\u5B50\uFF0C\u51C6\u5907\u5B98\u65B9 Runtime \u5DE5\u7A0B\u6216 Creator \u624B\u518C
5737
5786
  dev \u542F\u52A8\u5B98\u65B9 Runtime \u5E76\u8FDE\u63A5 DEV App Server
5738
5787
  login \u901A\u8FC7\u6D4F\u89C8\u5668\u767B\u5F55\u642D\u642D\u8D26\u53F7