@my-life-buddies/cli 0.28.0-dev.1 → 0.28.0-dev.2
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 +3 -1
- package/dist/bin/core.js +44 -9
- package/dist/bin/core.js.map +3 -3
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -344,7 +344,9 @@ buddy-cli-sit meta update --intro "根据食材、人数和口味推荐菜谱"
|
|
|
344
344
|
buddy-cli-sit meta update --avatar ./avatar.png
|
|
345
345
|
```
|
|
346
346
|
|
|
347
|
-
`meta` 只读,修改时必须带 `update` 并至少提供一个字段。多个修改参数可以组合,未传字段保持原样,包括云端已有的扩展资料。文字字段不能为空,名称最多 60 字,一句话介绍最多 200 字,完整介绍最多 10000 字。头像只上传替换,不提供清除选项;支持静态 PNG、JPEG、WebP
|
|
347
|
+
`meta` 只读,修改时必须带 `update` 并至少提供一个字段。多个修改参数可以组合,未传字段保持原样,包括云端已有的扩展资料。文字字段不能为空,名称最多 60 字,一句话介绍最多 200 字,完整介绍最多 10000 字。头像只上传替换,不提供清除选项;支持静态 PNG、JPEG、WebP,原图最大 5 MiB、宽高不超过 4096 px。Server 校验图片并生成地址,处理失败时保留原头像。
|
|
348
|
+
|
|
349
|
+
头像上传请求最多等待 5 分钟,适用于首次登记、替换头像以及同时修改文字和头像。CLI 上传前按服务端规则居中裁切至 512×512,编码为无损 WebP,保留颜色和透明度;原始文件与本地原图草稿不变;查询、仅文字更新和兼容命令清除头像仍使用 30 秒超时。
|
|
348
350
|
|
|
349
351
|
默认向上寻找 `package.json.buddyId`,也可用 `--directory ./cooking-buddy` 指定工程;图片路径始终相对执行命令的当前目录。创作阶段只有身份清单时也能使用,无需安装或启动 Runtime。工程外可直接指定平台 ID:
|
|
350
352
|
|
package/dist/bin/core.js
CHANGED
|
@@ -386,7 +386,8 @@ var resolveAvatarSkill = (previous, options = {}) => resolveSkillPackage(definit
|
|
|
386
386
|
|
|
387
387
|
// packages/cli-core/src/cloud/avatar.ts
|
|
388
388
|
import { open } from "node:fs/promises";
|
|
389
|
-
import { basename } from "node:path";
|
|
389
|
+
import { basename, extname } from "node:path";
|
|
390
|
+
import sharp from "sharp";
|
|
390
391
|
var MAX_BUDDY_AVATAR_BYTES = 5 * 1024 * 1024;
|
|
391
392
|
async function readBuddyAvatarFile(path) {
|
|
392
393
|
const file = await open(path, "r");
|
|
@@ -410,6 +411,33 @@ async function readBuddyAvatarFile(path) {
|
|
|
410
411
|
await file.close();
|
|
411
412
|
}
|
|
412
413
|
}
|
|
414
|
+
async function prepareBuddyAvatarUpload(source) {
|
|
415
|
+
const input = Buffer.from(source.bytes);
|
|
416
|
+
if (!input.length || input.length > MAX_BUDDY_AVATAR_BYTES) throw new Error("\u5934\u50CF\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u4E0D\u80FD\u8D85\u8FC7 5 MiB");
|
|
417
|
+
if (source.mediaType === "image/png") {
|
|
418
|
+
for (let at = 8; at + 12 <= input.length; ) {
|
|
419
|
+
const length = input.readUInt32BE(at);
|
|
420
|
+
if (input.toString("ascii", at + 4, at + 8) === "acTL") throw new Error("\u4EC5\u652F\u6301\u9759\u6001\u5934\u50CF\uFF0C\u4E0D\u652F\u6301\u52A8\u56FE");
|
|
421
|
+
at += length + 12;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const image = sharp(input, { failOn: "warning", limitInputPixels: 4096 * 4096 });
|
|
425
|
+
let meta2;
|
|
426
|
+
try {
|
|
427
|
+
meta2 = await image.metadata();
|
|
428
|
+
} catch {
|
|
429
|
+
throw new Error("\u56FE\u7247\u65E0\u6CD5\u89E3\u7801\u6216\u50CF\u7D20\u8FC7\u5927\uFF0C\u8BF7\u9009\u62E9\u5BBD\u9AD8\u4E0D\u8D85\u8FC7 4096 px \u7684\u9759\u6001 PNG\u3001JPEG\u3001WebP");
|
|
430
|
+
}
|
|
431
|
+
if (!["png", "jpeg", "webp"].includes(meta2.format ?? "")) throw new Error("\u4EC5\u652F\u6301 PNG\u3001JPEG\u3001WebP \u56FE\u7247\u6587\u4EF6");
|
|
432
|
+
if ((meta2.pages ?? 1) !== 1) throw new Error("\u4EC5\u652F\u6301\u9759\u6001\u5934\u50CF\uFF0C\u4E0D\u652F\u6301\u52A8\u56FE");
|
|
433
|
+
if (!meta2.width || !meta2.height || meta2.width > 4096 || meta2.height > 4096) throw new Error("\u5934\u50CF\u5BBD\u9AD8\u4E0D\u80FD\u8D85\u8FC7 4096 px");
|
|
434
|
+
try {
|
|
435
|
+
const bytes = await image.rotate().resize(512, 512, { fit: "cover", position: "centre" }).webp({ lossless: true }).timeout({ seconds: 10 }).toBuffer();
|
|
436
|
+
return { bytes, mediaType: "image/webp", fileName: `${basename(source.fileName, extname(source.fileName))}.webp` };
|
|
437
|
+
} catch {
|
|
438
|
+
throw new Error("\u5934\u50CF\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u56FE\u7247\u662F\u5426\u5B8C\u6574\uFF0C\u6216\u6362\u4E00\u5F20\u56FE\u7247\u91CD\u8BD5");
|
|
439
|
+
}
|
|
440
|
+
}
|
|
413
441
|
|
|
414
442
|
// packages/cli-core/src/process-lock.ts
|
|
415
443
|
import { randomUUID } from "node:crypto";
|
|
@@ -547,9 +575,10 @@ async function save(path, content) {
|
|
|
547
575
|
});
|
|
548
576
|
}
|
|
549
577
|
}
|
|
550
|
-
async function readImage(path) {
|
|
578
|
+
async function readImage(path, { forUpload = false } = {}) {
|
|
551
579
|
try {
|
|
552
|
-
|
|
580
|
+
const source = await readBuddyAvatarFile(path);
|
|
581
|
+
return forUpload ? await prepareBuddyAvatarUpload(source) : source;
|
|
553
582
|
} catch (error2) {
|
|
554
583
|
throw new MetaPreparationError(`\u5934\u50CF\u672A\u5B8C\u6210\uFF1A${error2 instanceof Error ? error2.message : "\u65E0\u6CD5\u8BFB\u53D6\u56FE\u7247"}\u3002\u672C\u5730\u8D44\u6599\u5DF2\u4FDD\u7559\uFF0C\u5C1A\u672A\u63D0\u4EA4\u8FD9\u5F20\u5934\u50CF\u3002`);
|
|
555
584
|
}
|
|
@@ -679,7 +708,7 @@ async function prepareLockedMeta(options) {
|
|
|
679
708
|
io.write(`\u5934\u50CF\u672A\u5B8C\u6210\uFF0C\u5DF2\u4FDD\u5B58\u672C\u5730\u8D44\u6599\uFF0C\u5C1A\u672A\u521B\u5EFA\u4E91\u7AEF\u642D\u5B50\u3002\u8BF7\u8BA9 Coding Agent \u8BFB\u53D6 ${join4(folder(root), "HANDOFF.md")}\uFF1B\u6216\u4F7F\u7528 --avatar <\u56FE\u7247\u8DEF\u5F84> \u7EE7\u7EED\u3002`);
|
|
680
709
|
return void 0;
|
|
681
710
|
}
|
|
682
|
-
const upload = await readImage(join4(folder(root), draft.avatarPath));
|
|
711
|
+
const upload = await readImage(join4(folder(root), draft.avatarPath), { forUpload: true });
|
|
683
712
|
const confirmation = hash(JSON.stringify([profile.name, profile.tagline, profile.intro, hash(upload.bytes)]));
|
|
684
713
|
const preview = join4(folder(root), "preview.html");
|
|
685
714
|
await save(preview, `<!doctype html><html lang="zh-CN"><meta charset="utf-8"><title>\u786E\u8BA4\u642D\u5B50\u8D44\u6599\u4E0E\u5934\u50CF</title><style>body{font:18px system-ui;max-width:800px;margin:48px auto;padding:24px;color:#163342}p{white-space:pre-wrap}section{display:flex;gap:24px}figure{margin:0;padding:24px;background:#eef4f8;border-radius:12px}figure.dark{background:#183040}img{width:220px;height:220px;object-fit:contain;border-radius:50%}</style><h1>${escape(profile.name)}</h1><p>${escape(profile.tagline)}</p><p>${escape(profile.intro)}</p><section><figure><img alt="\u6D45\u8272\u80CC\u666F\u5934\u50CF" src="data:${upload.mediaType};base64,${Buffer.from(upload.bytes).toString("base64")}"></figure><figure class="dark"><img alt="\u6DF1\u8272\u80CC\u666F\u5934\u50CF" src="data:${upload.mediaType};base64,${Buffer.from(upload.bytes).toString("base64")}"></figure></section><p>\u67E5\u770B\u5934\u50CF\u548C\u8D44\u6599\u540E\uFF0C\u56DE\u5230\u7EC8\u7AEF\u786E\u8BA4\u3002\u6B64\u9875\u9762\u4E0D\u4F1A\u4E0A\u4F20\u4EFB\u4F55\u5185\u5BB9\u3002</p></html>`);
|
|
@@ -3425,6 +3454,7 @@ direct \u751F\u6210\u65B0\u4E1A\u52A1\u5DE5\u5382\u524D\uFF0C\u6309\u6700\u65B0
|
|
|
3425
3454
|
\u540C\u76EE\u5F55\u6062\u590D\u4FDD\u7559\u5DF2\u6709\u4E1A\u52A1\u6587\u4EF6\u3002create \u540E\u6309 .buddy/creator/HANDOFF.md \u7EE7\u7EED\uFF0Cdirect \u540E\u5B89\u88C5\u4F9D\u8D56\u5E76\u5B9E\u73B0\u4E1A\u52A1\u3002
|
|
3426
3455
|
Creator \u6BCF\u6B21\u8FDB\u5165\u6216\u6062\u590D\u90FD\u67E5\u8BE2\u516C\u5171 npm latest\uFF1B\u6709 Creator \u8BB0\u5F55\u7684\u5B8C\u6574\u5DE5\u7A0B\u4E5F\u53EF\u6267\u884C create \u63A5\u7EED\u521B\u4F5C\uFF0C\u4E0D\u91CD\u5EFA\u4E1A\u52A1\u6587\u4EF6\u3002
|
|
3427
3456
|
\u5DF2\u767B\u8BB0\u642D\u5B50\u7684\u540D\u79F0\u3001\u4ECB\u7ECD\u6216\u5934\u50CF\u7528 buddy-cli-sit meta update \u4FEE\u6539\uFF1Binit \u4E0D\u8986\u76D6\u4E91\u7AEF\u8D44\u6599\u3002
|
|
3457
|
+
\u5934\u50CF\u4E0A\u4F20\u8BF7\u6C42\u6700\u591A\u7B49\u5F85 5 \u5206\u949F\uFF0CCLI \u4E0A\u4F20\u524D\u5C45\u4E2D\u88C1\u5207\u81F3 512\xD7512 \u65E0\u635F WebP\uFF0C\u4FDD\u7559\u989C\u8272\u3001\u900F\u660E\u5EA6\u4E0E\u539F\u59CB\u6587\u4EF6\uFF1B\u666E\u901A\u8BF7\u6C42\u4ECD\u4E3A 30 \u79D2\u3002
|
|
3428
3458
|
|
|
3429
3459
|
\u793A\u4F8B:
|
|
3430
3460
|
buddy-cli-sit init --mode direct --directory ./my-buddy --name "\u505A\u996D\u642D\u5B50" --tagline "\u5E2E\u4F60\u5B89\u6392\u665A\u996D" --intro "\u6839\u636E\u73B0\u6709\u98DF\u6750\u63A8\u8350\u83DC\u8C31"
|
|
@@ -6060,7 +6090,10 @@ var HttpDeveloperPlatformClient = class {
|
|
|
6060
6090
|
const form = new FormData();
|
|
6061
6091
|
form.set("meta", JSON.stringify(request.meta));
|
|
6062
6092
|
form.set("avatar", new Blob([new Uint8Array(request.avatar.bytes)], { type: request.avatar.mediaType }), request.avatar.fileName);
|
|
6063
|
-
return buddy(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/meta`, "PUT", {
|
|
6093
|
+
return buddy(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/meta`, "PUT", {
|
|
6094
|
+
form,
|
|
6095
|
+
timeoutMs: this.#uploadTimeoutMs
|
|
6096
|
+
}), true);
|
|
6064
6097
|
}
|
|
6065
6098
|
return buddy(await this.#request(`/cli/buddies/${encodeURIComponent(request.id)}/meta`, "PUT", {
|
|
6066
6099
|
json: request.meta
|
|
@@ -6285,6 +6318,7 @@ var HELP = Object.freeze({
|
|
|
6285
6318
|
meta \u53EA\u67E5\u770B\u4E91\u7AEF\u8D44\u6599\uFF1Bmeta update \u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u4FEE\u6539\u5B57\u6BB5\uFF0C\u672A\u4F20\u5B57\u6BB5\u4FDD\u6301\u539F\u6837\u3002
|
|
6286
6319
|
\u6587\u5B57\u5B57\u6BB5\u4E0D\u80FD\u4E3A\u7A7A\uFF1B\u540D\u79F0\u6700\u591A ${BUDDY_PROFILE_TEXT_LIMITS.name} \u5B57\uFF0C\u4E00\u53E5\u8BDD\u4ECB\u7ECD\u6700\u591A ${BUDDY_PROFILE_TEXT_LIMITS.tagline} \u5B57\uFF0C\u5B8C\u6574\u4ECB\u7ECD\u6700\u591A ${BUDDY_PROFILE_TEXT_LIMITS.intro} \u5B57\u3002
|
|
6287
6320
|
--avatar \u4E0A\u4F20\u66FF\u6362\u5934\u50CF\uFF1A\u672C\u5730\u9759\u6001 PNG\u3001JPEG\u3001WebP\uFF0C\u6700\u5927 5 MiB\uFF1B\u4E0D\u63D0\u4F9B\u6E05\u9664\u5934\u50CF\u9009\u9879\u3002
|
|
6321
|
+
\u5934\u50CF\u4E0A\u4F20\u8BF7\u6C42\u6700\u591A\u7B49\u5F85 5 \u5206\u949F\uFF0CCLI \u4E0A\u4F20\u524D\u5C45\u4E2D\u88C1\u5207\u81F3 512\xD7512 \u65E0\u635F WebP\uFF0C\u4FDD\u7559\u989C\u8272\u3001\u900F\u660E\u5EA6\u4E0E\u539F\u59CB\u6587\u4EF6\uFF1B\u67E5\u8BE2\u548C\u4EC5\u6587\u5B57\u66F4\u65B0\u4ECD\u4E3A 30 \u79D2\u3002
|
|
6288
6322
|
\u9ED8\u8BA4\u8BFB\u53D6\u5F53\u524D\u5DE5\u7A0B\u7684 package.json.buddyId\uFF1B--buddy-id \u4E0E --directory \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\u3002\u56FE\u7247\u8DEF\u5F84\u76F8\u5BF9\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002
|
|
6289
6323
|
\u9700\u8981\u5F53\u524D\u8D26\u53F7\u62E5\u6709\u8BE5\u642D\u5B50\uFF1B\u66F4\u65B0\u7ACB\u5373\u5F71\u54CD\u4E91\u7AEF\u5C55\u793A\u8D44\u6599\uFF0C\u65E0\u9700 Runtime\u3001push \u6216\u91CD\u65B0\u53D1\u5E03\u7A0B\u5E8F\u5305\u3002
|
|
6290
6324
|
\u793A\u4F8B: buddy-cli-sit meta update --name "\u5DDD\u5927\u53A8" --tagline "\u5E2E\u4F60\u5B89\u6392\u6BCF\u5929\u5403\u4EC0\u4E48" --avatar ./avatar.png`,
|
|
@@ -6292,6 +6326,7 @@ meta \u53EA\u67E5\u770B\u4E91\u7AEF\u8D44\u6599\uFF1Bmeta update \u81F3\u5C11\u6
|
|
|
6292
6326
|
\u65E7\u547D\u4EE4\u517C\u5BB9\u5165\u53E3\uFF1B\u66F4\u6362\u5934\u50CF\u63A8\u8350\u4F7F\u7528 buddy-cli-sit meta update --avatar <\u56FE\u7247\u6587\u4EF6>\u3002
|
|
6293
6327
|
\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
|
|
6294
6328
|
--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
|
|
6329
|
+
\u5934\u50CF\u4E0A\u4F20\u8BF7\u6C42\u6700\u591A\u7B49\u5F85 5 \u5206\u949F\uFF0CCLI \u4E0A\u4F20\u524D\u5C45\u4E2D\u88C1\u5207\u81F3 512\xD7512 \u65E0\u635F WebP\uFF0C\u4FDD\u7559\u989C\u8272\u3001\u900F\u660E\u5EA6\u4E0E\u539F\u59CB\u6587\u4EF6\uFF1B\u6E05\u9664\u5934\u50CF\u4ECD\u4E3A 30 \u79D2\u3002
|
|
6295
6330
|
\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`
|
|
6296
6331
|
});
|
|
6297
6332
|
function parse3(args, command) {
|
|
@@ -6420,7 +6455,7 @@ async function runMeta(parsed, io, options, legacyAvatar = false) {
|
|
|
6420
6455
|
}
|
|
6421
6456
|
let upload;
|
|
6422
6457
|
try {
|
|
6423
|
-
upload = file ? await readBuddyAvatarFile(resolve16(options.cwd ?? process.cwd(), file)) : void 0;
|
|
6458
|
+
upload = file ? await prepareBuddyAvatarUpload(await readBuddyAvatarFile(resolve16(options.cwd ?? process.cwd(), file))) : void 0;
|
|
6424
6459
|
} catch (error2) {
|
|
6425
6460
|
throw new CloudCommandUsageError(error2 instanceof Error ? error2.message : "\u65E0\u6CD5\u8BFB\u53D6\u5934\u50CF\u56FE\u7247");
|
|
6426
6461
|
}
|
|
@@ -6518,7 +6553,7 @@ var CLOUD_COMMAND_HELP = HELP;
|
|
|
6518
6553
|
|
|
6519
6554
|
// packages/cli-core/src/migration/index.ts
|
|
6520
6555
|
import { lstat as lstat12, open as open5, readdir as readdir6, realpath as realpath7, stat } from "node:fs/promises";
|
|
6521
|
-
import { extname, isAbsolute as isAbsolute3, join as join22, relative, resolve as resolve17, sep, win32 as win322 } from "node:path";
|
|
6556
|
+
import { extname as extname2, isAbsolute as isAbsolute3, join as join22, relative, resolve as resolve17, sep, win32 as win322 } from "node:path";
|
|
6522
6557
|
var DEFAULT_SKILL_SCAN_LIMITS = Object.freeze({
|
|
6523
6558
|
maxFiles: 128,
|
|
6524
6559
|
maxFileBytes: 256 * 1024,
|
|
@@ -6950,7 +6985,7 @@ function frontmatterEnd(lines) {
|
|
|
6950
6985
|
return -1;
|
|
6951
6986
|
}
|
|
6952
6987
|
function shellLines(lines, path) {
|
|
6953
|
-
const extension =
|
|
6988
|
+
const extension = extname2(path).toLowerCase();
|
|
6954
6989
|
const shebang = lines[0] ?? "";
|
|
6955
6990
|
if (SHELL_EXTENSIONS.has(extension) || /^#!.*(?:[/\s])(?:bash|fish|powershell|pwsh|sh|zsh)(?:\s|$)/u.test(shebang)) return lines.map(() => true);
|
|
6956
6991
|
const result = lines.map(() => false);
|
|
@@ -7078,7 +7113,7 @@ function analyzeText(source, path, context) {
|
|
|
7078
7113
|
const lines = source.split(/\r\n|\n|\r/u);
|
|
7079
7114
|
const metadataEnd = frontmatterEnd(lines);
|
|
7080
7115
|
const shellContext = shellLines(lines, path);
|
|
7081
|
-
const extension =
|
|
7116
|
+
const extension = extname2(path).toLowerCase();
|
|
7082
7117
|
const localShellVariables = /* @__PURE__ */ new Set();
|
|
7083
7118
|
const localBatchVariables = /* @__PURE__ */ new Set();
|
|
7084
7119
|
const localPowerShellEnvironment = /* @__PURE__ */ new Set();
|