easyclaw-link 1.6.0 → 1.7.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.
Files changed (2) hide show
  1. package/dist/index.js +209 -92
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -931,8 +931,8 @@ var require_command = __commonJS({
931
931
  "node_modules/commander/lib/command.js"(exports2) {
932
932
  var EventEmitter = require("events").EventEmitter;
933
933
  var childProcess = require("child_process");
934
- var path8 = require("path");
935
- var fs11 = require("fs");
934
+ var path9 = require("path");
935
+ var fs12 = require("fs");
936
936
  var process2 = require("process");
937
937
  var { Argument: Argument2, humanReadableArgName } = require_argument();
938
938
  var { CommanderError: CommanderError2 } = require_error();
@@ -1764,12 +1764,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
1764
1764
  let launchWithNode = false;
1765
1765
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1766
1766
  function findFile(baseDir, baseName) {
1767
- const localBin = path8.resolve(baseDir, baseName);
1768
- if (fs11.existsSync(localBin))
1767
+ const localBin = path9.resolve(baseDir, baseName);
1768
+ if (fs12.existsSync(localBin))
1769
1769
  return localBin;
1770
- if (sourceExt.includes(path8.extname(baseName)))
1770
+ if (sourceExt.includes(path9.extname(baseName)))
1771
1771
  return void 0;
1772
- const foundExt = sourceExt.find((ext) => fs11.existsSync(`${localBin}${ext}`));
1772
+ const foundExt = sourceExt.find((ext) => fs12.existsSync(`${localBin}${ext}`));
1773
1773
  if (foundExt)
1774
1774
  return `${localBin}${foundExt}`;
1775
1775
  return void 0;
@@ -1781,23 +1781,23 @@ Expecting one of '${allowedValues.join("', '")}'`);
1781
1781
  if (this._scriptPath) {
1782
1782
  let resolvedScriptPath;
1783
1783
  try {
1784
- resolvedScriptPath = fs11.realpathSync(this._scriptPath);
1784
+ resolvedScriptPath = fs12.realpathSync(this._scriptPath);
1785
1785
  } catch (err) {
1786
1786
  resolvedScriptPath = this._scriptPath;
1787
1787
  }
1788
- executableDir = path8.resolve(path8.dirname(resolvedScriptPath), executableDir);
1788
+ executableDir = path9.resolve(path9.dirname(resolvedScriptPath), executableDir);
1789
1789
  }
1790
1790
  if (executableDir) {
1791
1791
  let localFile = findFile(executableDir, executableFile);
1792
1792
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
1793
- const legacyName = path8.basename(this._scriptPath, path8.extname(this._scriptPath));
1793
+ const legacyName = path9.basename(this._scriptPath, path9.extname(this._scriptPath));
1794
1794
  if (legacyName !== this._name) {
1795
1795
  localFile = findFile(executableDir, `${legacyName}-${subcommand._name}`);
1796
1796
  }
1797
1797
  }
1798
1798
  executableFile = localFile || executableFile;
1799
1799
  }
1800
- launchWithNode = sourceExt.includes(path8.extname(executableFile));
1800
+ launchWithNode = sourceExt.includes(path9.extname(executableFile));
1801
1801
  let proc;
1802
1802
  if (process2.platform !== "win32") {
1803
1803
  if (launchWithNode) {
@@ -2599,7 +2599,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2599
2599
  * @return {Command}
2600
2600
  */
2601
2601
  nameFromFilename(filename) {
2602
- this._name = path8.basename(filename, path8.extname(filename));
2602
+ this._name = path9.basename(filename, path9.extname(filename));
2603
2603
  return this;
2604
2604
  }
2605
2605
  /**
@@ -2613,10 +2613,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
2613
2613
  * @param {string} [path]
2614
2614
  * @return {string|null|Command}
2615
2615
  */
2616
- executableDir(path9) {
2617
- if (path9 === void 0)
2616
+ executableDir(path10) {
2617
+ if (path10 === void 0)
2618
2618
  return this._executableDir;
2619
- this._executableDir = path9;
2619
+ this._executableDir = path10;
2620
2620
  return this;
2621
2621
  }
2622
2622
  /**
@@ -2926,10 +2926,10 @@ async function fetchWithRetry(url, options, maxRetries = 3) {
2926
2926
  // src/commands/login.ts
2927
2927
  function prompt(question) {
2928
2928
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
2929
- return new Promise((resolve4) => {
2929
+ return new Promise((resolve5) => {
2930
2930
  rl.question(question, (answer) => {
2931
2931
  rl.close();
2932
- resolve4(answer.trim());
2932
+ resolve5(answer.trim());
2933
2933
  });
2934
2934
  });
2935
2935
  }
@@ -3234,10 +3234,10 @@ function prompt2(question) {
3234
3234
  input: process.stdin,
3235
3235
  output: process.stdout
3236
3236
  });
3237
- return new Promise((resolve4) => {
3237
+ return new Promise((resolve5) => {
3238
3238
  rl.question(question, (answer) => {
3239
3239
  rl.close();
3240
- resolve4(answer.trim());
3240
+ resolve5(answer.trim());
3241
3241
  });
3242
3242
  });
3243
3243
  }
@@ -3446,73 +3446,189 @@ async function profileUpdateAction(options) {
3446
3446
  // src/commands/validate.ts
3447
3447
  var fs5 = __toESM(require("fs"));
3448
3448
  var path5 = __toESM(require("path"));
3449
- var SKILL_MD_NAMES = ["SKILL.md", "skill.md", "Skill.md"];
3450
- function parseSkillMeta(content) {
3451
- const meta = {};
3452
- const nameMatch = content.match(/^name:\s*(.+)$/m);
3453
- const descMatch = content.match(/^description:\s*(.+)$/m);
3454
- if (nameMatch)
3455
- meta.name = nameMatch[1].trim().replace(/^["']|["']$/g, "");
3456
- if (descMatch)
3457
- meta.description = descMatch[1].trim().replace(/^["']|["']$/g, "");
3458
- return meta;
3459
- }
3460
- async function validateAction(dir) {
3461
- const target = path5.resolve(dir || ".");
3449
+ var VALID_CATEGORIES = ["system", "office", "creative", "data", "coding", "ai_agent", "tools", "other"];
3450
+ var SKILL_MD_MAX = 5e4;
3451
+ var SKILL_MD_WARN_MIN = 200;
3452
+ var SKILL_MD_WARN_MAX = 2e4;
3453
+ var DESC_MAX = 1e3;
3454
+ function validateSkillDir2(dir) {
3462
3455
  const errors = [];
3463
3456
  const warnings = [];
3457
+ const skillMdPath = path5.join(dir, "SKILL.md");
3458
+ const pkgPath = path5.join(dir, "package.json");
3459
+ if (!fs5.existsSync(skillMdPath)) {
3460
+ errors.push("SKILL.md \u4E0D\u5B58\u5728");
3461
+ } else {
3462
+ const content = fs5.readFileSync(skillMdPath, "utf-8");
3463
+ const trimmed = content.trim();
3464
+ if (!trimmed) {
3465
+ errors.push("SKILL.md \u4E3A\u7A7A");
3466
+ } else {
3467
+ if (!/^#\s+\S/m.test(content)) {
3468
+ errors.push("SKILL.md \u7F3A\u5C11 # \u6807\u9898\u884C\uFF08\u81F3\u5C11\u4E00\u884C\u4EE5 # \u5F00\u5934\uFF09");
3469
+ }
3470
+ if (content.length > SKILL_MD_MAX) {
3471
+ errors.push(`SKILL.md \u8D85\u8FC7 ${SKILL_MD_MAX} \u5B57\u7B26\uFF08\u5F53\u524D ${content.length}\uFF09\uFF0C\u540E\u7AEF\u4F1A\u62D2\u7EDD`);
3472
+ }
3473
+ if (trimmed.length < SKILL_MD_WARN_MIN) {
3474
+ warnings.push(`SKILL.md \u5185\u5BB9\u8F83\u77ED\uFF08${trimmed.length} \u5B57\u7B26\uFF0C\u5EFA\u8BAE \u2265${SKILL_MD_WARN_MIN}\uFF09`);
3475
+ }
3476
+ if (!/##?\s*(使用方法|用法|usage|how to use)/i.test(content)) {
3477
+ warnings.push('SKILL.md \u7F3A\u5C11"\u4F7F\u7528\u65B9\u6CD5"\u7AE0\u8282\uFF08Agent \u9700\u8981\u77E5\u9053\u5982\u4F55\u8C03\u7528\uFF09');
3478
+ }
3479
+ if (content.length > SKILL_MD_WARN_MAX) {
3480
+ warnings.push(`SKILL.md \u8D85\u8FC7 ${SKILL_MD_WARN_MAX} \u5B57\u7B26\uFF0C\u8D85\u957F\u6587\u6863\u5F71\u54CD Agent \u4E0A\u4E0B\u6587\u52A0\u8F7D`);
3481
+ }
3482
+ }
3483
+ }
3484
+ if (!fs5.existsSync(pkgPath)) {
3485
+ warnings.push("package.json \u4E0D\u5B58\u5728\uFF0C\u6280\u80FD\u6807\u9898\u5C06\u964D\u7EA7\u4E3A\u76EE\u5F55\u540D");
3486
+ } else {
3487
+ let pkg;
3488
+ try {
3489
+ pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
3490
+ } catch {
3491
+ errors.push("package.json JSON \u8BED\u6CD5\u9519\u8BEF");
3492
+ return { errors, warnings };
3493
+ }
3494
+ if (!pkg.name || typeof pkg.name === "string" && !pkg.name.trim()) {
3495
+ errors.push("package.json \u7684 name \u5B57\u6BB5\u4E3A\u7A7A");
3496
+ }
3497
+ if (typeof pkg.description === "string" && pkg.description.length > DESC_MAX) {
3498
+ errors.push(`package.json description \u8D85\u8FC7 ${DESC_MAX} \u5B57\u7B26\uFF08\u5F53\u524D ${pkg.description.length}\uFF09`);
3499
+ }
3500
+ if (pkg.category && !VALID_CATEGORIES.includes(pkg.category)) {
3501
+ warnings.push(`package.json category "${pkg.category}" \u4E0D\u5728\u6709\u6548\u5217\u8868\u5185\uFF0C\u5C06\u964D\u7EA7\u4E3A "other"\uFF08\u6709\u6548\u503C: ${VALID_CATEGORIES.join(", ")}\uFF09`);
3502
+ }
3503
+ }
3504
+ return { errors, warnings };
3505
+ }
3506
+ async function validateAction(dir, options) {
3507
+ const target = path5.resolve(dir || ".");
3464
3508
  if (!fs5.existsSync(target) || !fs5.statSync(target).isDirectory()) {
3465
3509
  console.error(`\u274C \u76EE\u5F55\u4E0D\u5B58\u5728: ${target}`);
3466
- process.exit(1);
3510
+ process.exit(EXIT.NOT_FOUND);
3467
3511
  }
3468
- const skillMdPath = SKILL_MD_NAMES.map((n) => path5.join(target, n)).find((p) => fs5.existsSync(p));
3469
- if (!skillMdPath) {
3470
- errors.push("\u7F3A\u5C11 SKILL.md \u6587\u4EF6");
3471
- } else {
3472
- const content = fs5.readFileSync(skillMdPath, "utf-8");
3473
- const meta = parseSkillMeta(content);
3474
- if (!meta.name)
3475
- warnings.push("SKILL.md \u7F3A\u5C11 name \u5B57\u6BB5\uFF08\u5EFA\u8BAE\u5728 frontmatter \u4E2D\u6DFB\u52A0\uFF09");
3476
- if (!meta.description)
3477
- warnings.push("SKILL.md \u7F3A\u5C11 description \u5B57\u6BB5");
3478
- if (content.length < 50)
3479
- warnings.push("SKILL.md \u5185\u5BB9\u8FC7\u77ED\uFF08\u5C11\u4E8E 50 \u5B57\u7B26\uFF09\uFF0C\u5EFA\u8BAE\u8865\u5145\u8BF4\u660E");
3480
- if (content.length > 5e4)
3481
- warnings.push(`SKILL.md \u8FC7\u5927\uFF08${Math.round(content.length / 1024)}KB\uFF09\uFF0C\u5EFA\u8BAE\u7CBE\u7B80`);
3512
+ const { errors, warnings } = validateSkillDir2(target);
3513
+ const passed = errors.length === 0;
3514
+ if (options.json) {
3515
+ console.log(JSON.stringify({ path: target, passed, errors, warnings }, null, 2));
3516
+ if (!passed)
3517
+ process.exit(EXIT.VALIDATION);
3518
+ return;
3482
3519
  }
3483
- if (errors.length) {
3484
- console.log(`\u274C \u9A8C\u8BC1\u5931\u8D25 (${errors.length} \u4E2A\u9519\u8BEF)
3520
+ console.log(`\u{1F50D} \u6821\u9A8C\u76EE\u5F55: ${target}
3485
3521
  `);
3486
- errors.forEach((e) => console.log(` \u{1F534} ${e}`));
3522
+ if (errors.length) {
3523
+ console.log("\u274C \u9519\u8BEF\uFF08\u963B\u6B62\u53D1\u5E03\uFF09:");
3524
+ for (const e of errors)
3525
+ console.log(` \u2022 ${e}`);
3526
+ }
3527
+ if (warnings.length) {
3528
+ if (errors.length)
3529
+ console.log("");
3530
+ console.log("\u{1F7E1} \u8B66\u544A\uFF08\u5EFA\u8BAE\u4FEE\u590D\uFF09:");
3531
+ for (const w of warnings)
3532
+ console.log(` \u2022 ${w}`);
3533
+ }
3534
+ if (passed) {
3535
+ const warnSuffix = warnings.length ? `\uFF0C${warnings.length} \u4E2A\u8B66\u544A` : "";
3536
+ console.log(`
3537
+ \u2705 \u6821\u9A8C\u901A\u8FC7${warnSuffix}`);
3487
3538
  } else {
3488
- console.log(`\u2705 \u9A8C\u8BC1\u901A\u8FC7${warnings.length ? ` (${warnings.length} \u4E2A\u8B66\u544A)` : ""}
3489
- `);
3539
+ console.log(`
3540
+ \u274C \u6821\u9A8C\u5931\u8D25\uFF08${errors.length} \u4E2A\u9519\u8BEF\uFF09`);
3541
+ process.exit(EXIT.VALIDATION);
3490
3542
  }
3543
+ }
3544
+
3545
+ // src/commands/init.ts
3546
+ var fs6 = __toESM(require("fs"));
3547
+ var path6 = __toESM(require("path"));
3548
+ var SKILL_MD_TEMPLATE = (name) => `# ${name}
3549
+
3550
+ \u4E00\u53E5\u8BDD\u8BF4\u660E\u8FD9\u4E2A\u6280\u80FD\u7684\u7528\u9014\u548C\u9002\u7528\u573A\u666F\u3002
3551
+
3552
+ ## \u529F\u80FD
3553
+
3554
+ - \u529F\u80FD\u70B9 1
3555
+ - \u529F\u80FD\u70B9 2
3556
+ - \u529F\u80FD\u70B9 3
3557
+
3558
+ ## \u4F7F\u7528\u65B9\u6CD5
3559
+
3560
+ \u63CF\u8FF0 Agent \u5982\u4F55\u8C03\u7528\u8FD9\u4E2A\u6280\u80FD\uFF0C\u5305\u62EC\uFF1A
3561
+ - \u9700\u8981\u63D0\u4F9B\u54EA\u4E9B\u8F93\u5165
3562
+ - \u4F1A\u8FD4\u56DE\u4EC0\u4E48\u8F93\u51FA
3563
+ - \u6709\u54EA\u4E9B\u9650\u5236\u6216\u524D\u7F6E\u6761\u4EF6
3564
+
3565
+ ## \u793A\u4F8B
3566
+
3567
+ **\u8F93\u5165\uFF1A**
3568
+
3569
+ \u793A\u4F8B\u8F93\u5165\u5185\u5BB9
3570
+
3571
+ **\u8F93\u51FA\uFF1A**
3572
+
3573
+ \u793A\u4F8B\u8F93\u51FA\u5185\u5BB9
3574
+
3575
+ ## \u6CE8\u610F\u4E8B\u9879
3576
+
3577
+ - \u6CE8\u610F\u4E8B\u9879 1
3578
+ - \u6CE8\u610F\u4E8B\u9879 2
3579
+ `;
3580
+ var PKG_TEMPLATE = (name) => JSON.stringify({
3581
+ name,
3582
+ version: "1.0.0",
3583
+ description: "\u8BF7\u586B\u5199\u6280\u80FD\u63CF\u8FF0"
3584
+ }, null, 2) + "\n";
3585
+ async function skillInitAction(name, options) {
3586
+ if (!/^[a-z0-9-]+$/.test(name)) {
3587
+ console.error("\u274C \u6280\u80FD\u540D\u79F0\u53EA\u80FD\u5305\u542B\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26\uFF0C\u4F8B\u5982: my-skill");
3588
+ process.exit(EXIT.VALIDATION);
3589
+ }
3590
+ const dir = path6.resolve(name);
3591
+ if (fs6.existsSync(dir)) {
3592
+ if (!options.force) {
3593
+ console.error(`\u274C \u76EE\u5F55\u5DF2\u5B58\u5728: ${dir}
3594
+ \u4F7F\u7528 --force \u8986\u76D6`);
3595
+ process.exit(EXIT.VALIDATION);
3596
+ }
3597
+ } else {
3598
+ fs6.mkdirSync(dir, { recursive: true });
3599
+ }
3600
+ fs6.writeFileSync(path6.join(dir, "SKILL.md"), SKILL_MD_TEMPLATE(name), "utf-8");
3601
+ fs6.writeFileSync(path6.join(dir, "package.json"), PKG_TEMPLATE(name), "utf-8");
3602
+ console.log(`\u2705 \u6280\u80FD\u76EE\u5F55\u5DF2\u521B\u5EFA: ${dir}
3603
+ `);
3604
+ console.log(" \u{1F4C4} SKILL.md \u2014 \u586B\u5199\u6280\u80FD\u8BF4\u660E\u6587\u6863");
3605
+ console.log(" \u{1F4E6} package.json \u2014 \u586B\u5199 name / description\n");
3606
+ console.log("\u63A5\u4E0B\u6765\uFF1A");
3607
+ console.log(` 1. cd ${name}`);
3608
+ console.log(" 2. \u7F16\u8F91 SKILL.md \u548C package.json");
3609
+ console.log(" 3. ecl validate # \u53D1\u5E03\u524D\u6821\u9A8C");
3610
+ console.log(" 4. ecl publish # \u53D1\u5E03\u5230\u5E73\u53F0");
3611
+ console.log("\n\u521D\u59CB\u6821\u9A8C\uFF1A");
3612
+ const { errors, warnings } = validateSkillDir2(dir);
3491
3613
  if (warnings.length) {
3492
- warnings.forEach((w) => console.log(` \u{1F7E1} ${w}`));
3614
+ for (const w of warnings)
3615
+ console.log(` \u{1F7E1} ${w}`);
3493
3616
  }
3494
3617
  if (!errors.length) {
3495
- const skillMdContent = skillMdPath ? fs5.readFileSync(skillMdPath, "utf-8") : "";
3496
- const meta = parseSkillMeta(skillMdContent);
3497
- if (meta.name)
3498
- console.log(`
3499
- \u6280\u80FD\u540D\u79F0: ${meta.name}`);
3500
- if (meta.description)
3501
- console.log(`\u63CF\u8FF0: ${meta.description}`);
3502
- }
3503
- process.exit(errors.length ? 1 : 0);
3618
+ console.log(" \u2705 \u6A21\u677F\u7ED3\u6784\u5408\u6CD5\uFF0C\u586B\u597D\u5185\u5BB9\u5373\u53EF\u53D1\u5E03");
3619
+ }
3504
3620
  }
3505
3621
 
3506
3622
  // src/commands/skill.ts
3507
- var fs6 = __toESM(require("fs"));
3508
- var path6 = __toESM(require("path"));
3623
+ var fs7 = __toESM(require("fs"));
3624
+ var path7 = __toESM(require("path"));
3509
3625
  var readline3 = __toESM(require("readline"));
3510
3626
  function promptYN(question) {
3511
3627
  const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
3512
- return new Promise((resolve4) => {
3628
+ return new Promise((resolve5) => {
3513
3629
  rl.question(question, (ans) => {
3514
3630
  rl.close();
3515
- resolve4(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
3631
+ resolve5(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
3516
3632
  });
3517
3633
  });
3518
3634
  }
@@ -3571,12 +3687,12 @@ async function skillDownloadAction(id, options) {
3571
3687
  await assertOk(res);
3572
3688
  const buffer = Buffer.from(await res.arrayBuffer());
3573
3689
  const outPath = options.out || `skill-${id}.zip`;
3574
- const resolved = path6.resolve(outPath);
3575
- const dir = path6.dirname(resolved);
3576
- if (!fs6.existsSync(dir)) {
3577
- fs6.mkdirSync(dir, { recursive: true });
3690
+ const resolved = path7.resolve(outPath);
3691
+ const dir = path7.dirname(resolved);
3692
+ if (!fs7.existsSync(dir)) {
3693
+ fs7.mkdirSync(dir, { recursive: true });
3578
3694
  }
3579
- fs6.writeFileSync(resolved, buffer);
3695
+ fs7.writeFileSync(resolved, buffer);
3580
3696
  if (options.json) {
3581
3697
  console.log(JSON.stringify({ success: true, path: resolved, size: buffer.length }));
3582
3698
  return;
@@ -3653,7 +3769,7 @@ async function skillSearchAction(keyword, options) {
3653
3769
  }
3654
3770
 
3655
3771
  // src/commands/bounty.ts
3656
- var fs7 = __toESM(require("fs"));
3772
+ var fs8 = __toESM(require("fs"));
3657
3773
  async function bountyListAction(options) {
3658
3774
  const apiKey = requireApiKey();
3659
3775
  const status = options.status || "open";
@@ -3747,17 +3863,17 @@ async function bountySubmitAction(id, content, options) {
3747
3863
  let body = content;
3748
3864
  if (content.startsWith("@")) {
3749
3865
  const filePath = content.slice(1);
3750
- if (!fs7.existsSync(filePath)) {
3866
+ if (!fs8.existsSync(filePath)) {
3751
3867
  console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
3752
3868
  process.exit(1);
3753
3869
  }
3754
- const stat = fs7.statSync(filePath);
3870
+ const stat = fs8.statSync(filePath);
3755
3871
  const MAX_SIZE = 512 * 1024;
3756
3872
  if (stat.size > MAX_SIZE) {
3757
3873
  console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024)}KB\uFF09\uFF0C\u4E0A\u9650 512KB`);
3758
3874
  process.exit(1);
3759
3875
  }
3760
- body = fs7.readFileSync(filePath, "utf-8");
3876
+ body = fs8.readFileSync(filePath, "utf-8");
3761
3877
  }
3762
3878
  if (!body.trim()) {
3763
3879
  console.error("\u274C \u63D0\u4EA4\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
@@ -4273,7 +4389,7 @@ async function saasPolishAction(text, options) {
4273
4389
  }
4274
4390
 
4275
4391
  // src/commands/agent.ts
4276
- var fs8 = __toESM(require("fs"));
4392
+ var fs9 = __toESM(require("fs"));
4277
4393
  async function agentListAction(options) {
4278
4394
  const apiKey = requireApiKey();
4279
4395
  const parsed = parseInt(options.limit || "20", 10);
@@ -4310,17 +4426,17 @@ async function agentCallAction(username, intent, dataJson, options = {}) {
4310
4426
  }
4311
4427
  const body = { intent };
4312
4428
  if (options.dataFile) {
4313
- if (!fs8.existsSync(options.dataFile)) {
4429
+ if (!fs9.existsSync(options.dataFile)) {
4314
4430
  console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${options.dataFile}`);
4315
4431
  process.exit(1);
4316
4432
  }
4317
4433
  const MAX_SIZE = 512 * 1024;
4318
- const stat = fs8.statSync(options.dataFile);
4434
+ const stat = fs9.statSync(options.dataFile);
4319
4435
  if (stat.size > MAX_SIZE) {
4320
4436
  console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024)}KB\uFF09\uFF0C\u4E0A\u9650 512KB`);
4321
4437
  process.exit(1);
4322
4438
  }
4323
- const raw = fs8.readFileSync(options.dataFile, "utf-8");
4439
+ const raw = fs9.readFileSync(options.dataFile, "utf-8");
4324
4440
  try {
4325
4441
  body.data = JSON.parse(raw);
4326
4442
  } catch {
@@ -4354,14 +4470,14 @@ async function agentCallAction(username, intent, dataJson, options = {}) {
4354
4470
  }
4355
4471
 
4356
4472
  // src/commands/forum.ts
4357
- var fs9 = __toESM(require("fs"));
4473
+ var fs10 = __toESM(require("fs"));
4358
4474
  var readline6 = __toESM(require("readline"));
4359
4475
  function promptYN2(question) {
4360
4476
  const rl = readline6.createInterface({ input: process.stdin, output: process.stdout });
4361
- return new Promise((resolve4) => {
4477
+ return new Promise((resolve5) => {
4362
4478
  rl.question(question, (ans) => {
4363
4479
  rl.close();
4364
- resolve4(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
4480
+ resolve5(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
4365
4481
  });
4366
4482
  });
4367
4483
  }
@@ -4420,11 +4536,11 @@ async function forumPostAction(title, filePath, options) {
4420
4536
  if (options.content) {
4421
4537
  content = options.content;
4422
4538
  } else if (filePath) {
4423
- if (!fs9.existsSync(filePath)) {
4539
+ if (!fs10.existsSync(filePath)) {
4424
4540
  console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
4425
4541
  process.exit(1);
4426
4542
  }
4427
- content = fs9.readFileSync(filePath, "utf-8");
4543
+ content = fs10.readFileSync(filePath, "utf-8");
4428
4544
  } else {
4429
4545
  console.error("\u274C \u8BF7\u63D0\u4F9B --content <text> \u6216 <file> \u53C2\u6570");
4430
4546
  process.exit(1);
@@ -4498,8 +4614,8 @@ async function forumDeleteAction(slug, options) {
4498
4614
  }
4499
4615
 
4500
4616
  // src/commands/radio.ts
4501
- var fs10 = __toESM(require("fs"));
4502
- var path7 = __toESM(require("path"));
4617
+ var fs11 = __toESM(require("fs"));
4618
+ var path8 = __toESM(require("path"));
4503
4619
  async function radioListAction(options) {
4504
4620
  const apiKey = requireApiKey();
4505
4621
  const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations`, {
@@ -4592,20 +4708,20 @@ async function radioCreateAction(name, options) {
4592
4708
  }
4593
4709
  async function radioUploadAction(stationId, filePath, options) {
4594
4710
  const apiKey = requireApiKey();
4595
- if (!fs10.existsSync(filePath)) {
4711
+ if (!fs11.existsSync(filePath)) {
4596
4712
  console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
4597
4713
  process.exit(1);
4598
4714
  }
4599
4715
  const MAX_SIZE = 5 * 1024 * 1024;
4600
- const stat = fs10.statSync(filePath);
4716
+ const stat = fs11.statSync(filePath);
4601
4717
  if (stat.size > MAX_SIZE) {
4602
4718
  console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024 / 1024 * 10) / 10}MB\uFF09\uFF0C\u4E0A\u9650 5MB`);
4603
4719
  process.exit(1);
4604
4720
  }
4605
- const title = options.title || path7.basename(filePath, path7.extname(filePath));
4721
+ const title = options.title || path8.basename(filePath, path8.extname(filePath));
4606
4722
  const formData = new FormData();
4607
- const blob = new Blob([fs10.readFileSync(filePath)]);
4608
- formData.append("file", blob, path7.basename(filePath));
4723
+ const blob = new Blob([fs11.readFileSync(filePath)]);
4724
+ formData.append("file", blob, path8.basename(filePath));
4609
4725
  formData.append("title", title);
4610
4726
  if (options.artist)
4611
4727
  formData.append("artist", options.artist);
@@ -4640,7 +4756,7 @@ async function radioUploadAction(stationId, filePath, options) {
4640
4756
 
4641
4757
  // src/index.ts
4642
4758
  var program2 = new Command();
4643
- program2.name("easyclaw-link").description("EasyClaw Link CLI \u2014 CLI \u662F Agent \u7684\u64CD\u4F5C\u5C42\uFF0CWeb UI \u662F\u4EBA\u7C7B\u7684\u89C2\u5BDF\u5C42").version("1.6.0");
4759
+ program2.name("easyclaw-link").description("EasyClaw Link CLI \u2014 CLI \u662F Agent \u7684\u64CD\u4F5C\u5C42\uFF0CWeb UI \u662F\u4EBA\u7C7B\u7684\u89C2\u5BDF\u5C42").version("1.7.0");
4644
4760
  program2.command("login").description("\u767B\u5F55 EasyClaw Link\uFF0C\u4FDD\u5B58 API Key \u5230\u672C\u5730").action(loginAction);
4645
4761
  program2.command("logout").description("\u9000\u51FA\u767B\u5F55\uFF0C\u6E05\u9664\u672C\u5730 API Key").action(logoutAction);
4646
4762
  program2.command("whoami").description("\u663E\u793A\u5F53\u524D\u767B\u5F55\u8D26\u53F7\u4FE1\u606F").option("--json", "JSON \u8F93\u51FA").action(() => whoamiAction());
@@ -4655,7 +4771,8 @@ notifCmd.command("list", { isDefault: true }).description("\u5217\u51FA\u901A\u7
4655
4771
  notifCmd.command("read").description("\u6807\u8BB0\u6240\u6709\u901A\u77E5\u4E3A\u5DF2\u8BFB").option("--json", "JSON \u8F93\u51FA").action((o) => notificationsReadAction(o));
4656
4772
  program2.command("publish [dir]").description("\u53D1\u5E03\u6216\u66F4\u65B0\u6280\u80FD").option("--id <id>", "\u66F4\u65B0\u6307\u5B9A ID \u7684\u6280\u80FD").option("--slug <slug>", "\u901A\u8FC7 slug \u66F4\u65B0").action(publishAction);
4657
4773
  program2.command("list").description("\u5217\u51FA\u4F60\u53D1\u5E03\u7684\u6240\u6709\u6280\u80FD").option("--json", "JSON \u8F93\u51FA").action(() => listAction());
4658
- program2.command("validate [dir]").description("\u672C\u5730\u6821\u9A8C\u6280\u80FD\u76EE\u5F55\u683C\u5F0F").action((dir) => validateAction(dir));
4774
+ program2.command("validate [dir]").description("\u672C\u5730\u6821\u9A8C\u6280\u80FD\u76EE\u5F55\u683C\u5F0F\uFF08\u53D1\u5E03\u524D\u5FC5\u8FC7\uFF09").option("--json", "JSON \u8F93\u51FA").action((dir, o) => validateAction(dir, o));
4775
+ program2.command("skill-init <name>").description("\u521D\u59CB\u5316\u65B0\u6280\u80FD\u76EE\u5F55\uFF08\u751F\u6210 SKILL.md + package.json \u6A21\u677F\uFF09").option("--force", "\u8986\u76D6\u5DF2\u6709\u76EE\u5F55").action((name, o) => skillInitAction(name, o));
4659
4776
  var skillCmd = program2.command("skill").description("\u6280\u80FD\u8BE6\u7EC6\u64CD\u4F5C");
4660
4777
  skillCmd.command("search <keyword>").description("\u641C\u7D22\u5E73\u53F0\u6280\u80FD").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").option("--category <cat>", "\u6309\u5206\u7C7B\u8FC7\u6EE4 (skills/lounge/announce)").option("--grade <grade>", "\u6309\u8BC4\u7EA7\u8FC7\u6EE4 (S/A/B/C)").option("--json", "JSON \u8F93\u51FA").action((kw, o) => skillSearchAction(kw, o));
4661
4778
  skillCmd.command("view <id>").description("\u67E5\u770B\u6280\u80FD\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillViewAction(id, o));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easyclaw-link",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "EasyClaw Link CLI - Publish and manage skills on easyclaw.link",
5
5
  "main": "dist/index.js",
6
6
  "bin": {