easyclaw-link 1.4.2 → 1.6.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 +178 -279
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -932,7 +932,7 @@ var require_command = __commonJS({
932
932
  var EventEmitter = require("events").EventEmitter;
933
933
  var childProcess = require("child_process");
934
934
  var path8 = require("path");
935
- var fs10 = require("fs");
935
+ var fs11 = require("fs");
936
936
  var process2 = require("process");
937
937
  var { Argument: Argument2, humanReadableArgName } = require_argument();
938
938
  var { CommanderError: CommanderError2 } = require_error();
@@ -1765,11 +1765,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
1765
1765
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1766
1766
  function findFile(baseDir, baseName) {
1767
1767
  const localBin = path8.resolve(baseDir, baseName);
1768
- if (fs10.existsSync(localBin))
1768
+ if (fs11.existsSync(localBin))
1769
1769
  return localBin;
1770
1770
  if (sourceExt.includes(path8.extname(baseName)))
1771
1771
  return void 0;
1772
- const foundExt = sourceExt.find((ext) => fs10.existsSync(`${localBin}${ext}`));
1772
+ const foundExt = sourceExt.find((ext) => fs11.existsSync(`${localBin}${ext}`));
1773
1773
  if (foundExt)
1774
1774
  return `${localBin}${foundExt}`;
1775
1775
  return void 0;
@@ -1781,7 +1781,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1781
1781
  if (this._scriptPath) {
1782
1782
  let resolvedScriptPath;
1783
1783
  try {
1784
- resolvedScriptPath = fs10.realpathSync(this._scriptPath);
1784
+ resolvedScriptPath = fs11.realpathSync(this._scriptPath);
1785
1785
  } catch (err) {
1786
1786
  resolvedScriptPath = this._scriptPath;
1787
1787
  }
@@ -2833,6 +2833,54 @@ var os = __toESM(require("os"));
2833
2833
  var CONFIG_DIR = path.join(os.homedir(), ".easyclaw-link");
2834
2834
  var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
2835
2835
  var BASE_URL = process.env.EASYCLAW_LINK_API || "https://easyclaw.link";
2836
+ var EXIT = {
2837
+ OK: 0,
2838
+ ERROR: 1,
2839
+ AUTH: 2,
2840
+ PERMISSION: 3,
2841
+ NOT_FOUND: 4,
2842
+ VALIDATION: 5,
2843
+ RATE_LIMIT: 6
2844
+ };
2845
+ function httpError(status, serverMessage) {
2846
+ const msg = serverMessage ? `: ${serverMessage}` : "";
2847
+ switch (status) {
2848
+ case 401:
2849
+ console.error(`\u274C \u8BA4\u8BC1\u5931\u8D25${msg}
2850
+ \u2192 \u8BF7\u5148\u8FD0\u884C: ecl login`);
2851
+ process.exit(EXIT.AUTH);
2852
+ case 403:
2853
+ console.error(`\u274C \u6743\u9650\u4E0D\u8DB3${msg}
2854
+ \u2192 \u5F53\u524D\u8D26\u53F7\u65E0\u6B64\u64CD\u4F5C\u6743\u9650\uFF0C\u68C0\u67E5\u8D26\u53F7\u89D2\u8272`);
2855
+ process.exit(EXIT.PERMISSION);
2856
+ case 404:
2857
+ console.error(`\u274C \u8D44\u6E90\u4E0D\u5B58\u5728${msg}
2858
+ \u2192 \u68C0\u67E5 ID/slug \u662F\u5426\u6B63\u786E`);
2859
+ process.exit(EXIT.NOT_FOUND);
2860
+ case 422:
2861
+ console.error(`\u274C \u8BF7\u6C42\u6821\u9A8C\u5931\u8D25${msg}
2862
+ \u2192 \u68C0\u67E5\u53C2\u6570\u683C\u5F0F`);
2863
+ process.exit(EXIT.VALIDATION);
2864
+ case 429:
2865
+ console.error(`\u274C \u89E6\u53D1\u9891\u7387\u9650\u5236${msg}
2866
+ \u2192 \u8BF7\u7A0D\u540E\u91CD\u8BD5`);
2867
+ process.exit(EXIT.RATE_LIMIT);
2868
+ default:
2869
+ console.error(`\u274C \u8BF7\u6C42\u5931\u8D25 (HTTP ${status})${msg}`);
2870
+ process.exit(EXIT.ERROR);
2871
+ }
2872
+ }
2873
+ async function assertOk(res) {
2874
+ if (res.ok)
2875
+ return;
2876
+ let serverMsg;
2877
+ try {
2878
+ const body = await res.clone().json();
2879
+ serverMsg = body.error || body.message;
2880
+ } catch {
2881
+ }
2882
+ httpError(res.status, serverMsg);
2883
+ }
2836
2884
  function readConfig() {
2837
2885
  try {
2838
2886
  if (!fs.existsSync(CONFIG_FILE))
@@ -2852,8 +2900,8 @@ function writeConfig(config) {
2852
2900
  function requireApiKey() {
2853
2901
  const cfg = readConfig();
2854
2902
  if (!cfg.apiKey) {
2855
- console.error("\u274C \u672A\u767B\u5F55\uFF0C\u8BF7\u5148\u8FD0\u884C: npx easyclaw-link login");
2856
- process.exit(1);
2903
+ console.error("\u274C \u672A\u767B\u5F55\uFF0C\u8BF7\u5148\u8FD0\u884C: ecl login");
2904
+ process.exit(EXIT.AUTH);
2857
2905
  }
2858
2906
  return cfg.apiKey;
2859
2907
  }
@@ -2970,10 +3018,7 @@ async function resolveId(apiKey, slug) {
2970
3018
  `${BASE_URL}/api/assets?author=me&limit=${PAGE_SIZE}&offset=${offset}`,
2971
3019
  { headers: { Authorization: `Bearer ${apiKey}` } }
2972
3020
  );
2973
- if (!res.ok) {
2974
- console.error(`\u274C \u67E5\u8BE2\u6280\u80FD\u5217\u8868\u5931\u8D25 (${res.status})`);
2975
- process.exit(1);
2976
- }
3021
+ await assertOk(res);
2977
3022
  const { assets } = await res.json();
2978
3023
  if (!assets || assets.length === 0)
2979
3024
  break;
@@ -3027,11 +3072,7 @@ async function publishAction(dir, options) {
3027
3072
  body: JSON.stringify({ content })
3028
3073
  }
3029
3074
  );
3030
- if (!res.ok) {
3031
- const body = await res.text();
3032
- console.error(`\u274C \u66F4\u65B0\u5931\u8D25 (${res.status}): ${body}`);
3033
- process.exit(1);
3034
- }
3075
+ await assertOk(res);
3035
3076
  const { asset } = await res.json();
3036
3077
  console.log(`\u2705 \u6280\u80FD\u5DF2\u66F4\u65B0`);
3037
3078
  console.log(`\u{1F517} ${BASE_URL}/market/${asset?.id ?? resolvedId}`);
@@ -3045,11 +3086,7 @@ async function publishAction(dir, options) {
3045
3086
  body: JSON.stringify({ title, content, description, category: "other" })
3046
3087
  }
3047
3088
  );
3048
- if (!res.ok) {
3049
- const body = await res.text();
3050
- console.error(`\u274C \u53D1\u5E03\u5931\u8D25 (${res.status}): ${body}`);
3051
- process.exit(1);
3052
- }
3089
+ await assertOk(res);
3053
3090
  const { asset } = await res.json();
3054
3091
  console.log(`\u2705 \u6280\u80FD\u53D1\u5E03\u6210\u529F\uFF01`);
3055
3092
  console.log(`\u{1F517} ${BASE_URL}/market/${asset?.id}`);
@@ -3066,11 +3103,7 @@ async function listAction() {
3066
3103
  `${BASE_URL}/api/assets?author=me`,
3067
3104
  { headers: { Authorization: `Bearer ${apiKey}` } }
3068
3105
  );
3069
- if (!res.ok) {
3070
- const body = await res.text();
3071
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status}): ${body}`);
3072
- process.exit(1);
3073
- }
3106
+ await assertOk(res);
3074
3107
  const { assets } = await res.json();
3075
3108
  if (!assets || assets.length === 0) {
3076
3109
  console.log("\u{1F4ED} \u6682\u65E0\u6280\u80FD\uFF0C\u4F7F\u7528 npx easyclaw-link publish . \u53D1\u5E03\u4F60\u7684\u7B2C\u4E00\u4E2A\u6280\u80FD");
@@ -3099,11 +3132,7 @@ async function whoamiAction() {
3099
3132
  const res = await fetch(`${BASE_URL}/api/auth/me`, {
3100
3133
  headers: { Authorization: `Bearer ${apiKey}` }
3101
3134
  });
3102
- if (!res.ok) {
3103
- const body = await res.text();
3104
- console.error(`\u274C \u8BF7\u6C42\u5931\u8D25 (${res.status}): ${body}`);
3105
- process.exit(1);
3106
- }
3135
+ await assertOk(res);
3107
3136
  const { user } = await res.json();
3108
3137
  if (!user) {
3109
3138
  console.error("\u274C \u672A\u767B\u5F55\u6216 API Key \u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C npx easyclaw-link login");
@@ -3124,11 +3153,7 @@ async function creditsAction() {
3124
3153
  const res = await fetch(`${BASE_URL}/api/credits`, {
3125
3154
  headers: { Authorization: `Bearer ${apiKey}` }
3126
3155
  });
3127
- if (!res.ok) {
3128
- const body = await res.text();
3129
- console.error(`\u274C \u8BF7\u6C42\u5931\u8D25 (${res.status}): ${body}`);
3130
- process.exit(1);
3131
- }
3156
+ await assertOk(res);
3132
3157
  const data = await res.json();
3133
3158
  console.log(`\u{1F4B0} \u9F99\u867E\u5E01\u4F59\u989D: ${data.credits} \u{1F99E}`);
3134
3159
  console.log(`\u2B50 \u58F0\u671B: ${data.reputation} ${data.level.badge} ${data.level.name}
@@ -3157,11 +3182,7 @@ async function tasksAction() {
3157
3182
  const res = await fetch(`${BASE_URL}/api/bounties?status=open&sort=date_desc`, {
3158
3183
  headers: { Authorization: `Bearer ${apiKey}` }
3159
3184
  });
3160
- if (!res.ok) {
3161
- const body = await res.text();
3162
- console.error(`\u274C \u8BF7\u6C42\u5931\u8D25 (${res.status}): ${body}`);
3163
- process.exit(1);
3164
- }
3185
+ await assertOk(res);
3165
3186
  const data = await res.json();
3166
3187
  const bounties = data.bounties ?? [];
3167
3188
  if (bounties.length === 0) {
@@ -3267,12 +3288,7 @@ ${bounty.description}
3267
3288
  },
3268
3289
  body: JSON.stringify({ content })
3269
3290
  });
3270
- if (!res.ok) {
3271
- const body = await res.json().catch(() => ({}));
3272
- const msg = typeof body.error === "string" ? body.error : `HTTP ${res.status}`;
3273
- console.error(`\u274C \u63D0\u4EA4\u5931\u8D25: ${msg}`);
3274
- process.exit(1);
3275
- }
3291
+ await assertOk(res);
3276
3292
  const { submission } = await res.json();
3277
3293
  console.log(`\u2705 \u7533\u8BF7\u63D0\u4EA4\u6210\u529F\uFF01\u63D0\u4EA4 ID: ${submission.id}`);
3278
3294
  console.log(`\u{1F517} \u67E5\u770B\u4EFB\u52A1: ${BASE_URL}/bounties/${id}`);
@@ -3293,10 +3309,7 @@ async function notificationsAction(options) {
3293
3309
  `${BASE_URL}/api/notifications?limit=${limit}`,
3294
3310
  { headers: { Authorization: `Bearer ${apiKey}` } }
3295
3311
  );
3296
- if (!res.ok) {
3297
- console.error(`\u274C \u83B7\u53D6\u901A\u77E5\u5931\u8D25 (${res.status})`);
3298
- process.exit(1);
3299
- }
3312
+ await assertOk(res);
3300
3313
  const data = await res.json();
3301
3314
  if (options.json) {
3302
3315
  console.log(JSON.stringify(data, null, 2));
@@ -3321,10 +3334,7 @@ async function notificationsReadAction(options) {
3321
3334
  Authorization: `Bearer ${apiKey}`
3322
3335
  }
3323
3336
  });
3324
- if (!res.ok) {
3325
- console.error(`\u274C \u6807\u8BB0\u5931\u8D25 (${res.status})`);
3326
- process.exit(1);
3327
- }
3337
+ await assertOk(res);
3328
3338
  const data = await res.json();
3329
3339
  if (options.json) {
3330
3340
  console.log(JSON.stringify(data, null, 2));
@@ -3339,10 +3349,7 @@ async function unreadAction(options) {
3339
3349
  const res = await fetchWithRetry(`${BASE_URL}/api/unread-counts`, {
3340
3350
  headers: { Authorization: `Bearer ${apiKey}` }
3341
3351
  });
3342
- if (!res.ok) {
3343
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3344
- process.exit(1);
3345
- }
3352
+ await assertOk(res);
3346
3353
  const data = await res.json();
3347
3354
  if (options.json) {
3348
3355
  console.log(JSON.stringify(data, null, 2));
@@ -3368,10 +3375,7 @@ async function statsAction(options) {
3368
3375
  const res = await fetchWithRetry(`${BASE_URL}/api/stats`, {
3369
3376
  headers: { Authorization: `Bearer ${apiKey}` }
3370
3377
  });
3371
- if (!res.ok) {
3372
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3373
- process.exit(1);
3374
- }
3378
+ await assertOk(res);
3375
3379
  const data = await res.json();
3376
3380
  if (options.json) {
3377
3381
  console.log(JSON.stringify(data, null, 2));
@@ -3392,10 +3396,7 @@ async function leaderboardAction(options) {
3392
3396
  const res = await fetchWithRetry(`${BASE_URL}/api/leaderboard?limit=${limit}`, {
3393
3397
  headers: { Authorization: `Bearer ${apiKey}` }
3394
3398
  });
3395
- if (!res.ok) {
3396
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3397
- process.exit(1);
3398
- }
3399
+ await assertOk(res);
3399
3400
  const data = await res.json();
3400
3401
  if (options.json) {
3401
3402
  console.log(JSON.stringify(data, null, 2));
@@ -3429,11 +3430,7 @@ async function profileUpdateAction(options) {
3429
3430
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
3430
3431
  body: JSON.stringify(body)
3431
3432
  });
3432
- if (!res.ok) {
3433
- const err = await res.json().catch(() => ({}));
3434
- console.error(`\u274C \u66F4\u65B0\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
3435
- process.exit(1);
3436
- }
3433
+ await assertOk(res);
3437
3434
  const data = await res.json();
3438
3435
  if (options.json) {
3439
3436
  console.log(JSON.stringify(data, null, 2));
@@ -3524,13 +3521,7 @@ async function skillViewAction(id, options) {
3524
3521
  const res = await fetchWithRetry(`${BASE_URL}/api/assets/${id}`, {
3525
3522
  headers: { Authorization: `Bearer ${apiKey}` }
3526
3523
  });
3527
- if (!res.ok) {
3528
- if (res.status === 404)
3529
- console.error(`\u274C \u6280\u80FD #${id} \u4E0D\u5B58\u5728`);
3530
- else
3531
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3532
- process.exit(1);
3533
- }
3524
+ await assertOk(res);
3534
3525
  const data = await res.json();
3535
3526
  const asset = data.asset ?? data;
3536
3527
  if (options.json) {
@@ -3565,15 +3556,7 @@ async function skillDeleteAction(id, options) {
3565
3556
  method: "DELETE",
3566
3557
  headers: { Authorization: `Bearer ${apiKey}` }
3567
3558
  });
3568
- if (!res.ok) {
3569
- if (res.status === 404)
3570
- console.error(`\u274C \u6280\u80FD #${id} \u4E0D\u5B58\u5728`);
3571
- else if (res.status === 403)
3572
- console.error("\u274C \u65E0\u6743\u9650\u5220\u9664\u6B64\u6280\u80FD");
3573
- else
3574
- console.error(`\u274C \u5220\u9664\u5931\u8D25 (${res.status})`);
3575
- process.exit(1);
3576
- }
3559
+ await assertOk(res);
3577
3560
  if (options.json) {
3578
3561
  console.log(JSON.stringify({ success: true, id }));
3579
3562
  return;
@@ -3585,13 +3568,7 @@ async function skillDownloadAction(id, options) {
3585
3568
  const res = await fetchWithRetry(`${BASE_URL}/api/assets/${id}/download`, {
3586
3569
  headers: { Authorization: `Bearer ${apiKey}` }
3587
3570
  });
3588
- if (!res.ok) {
3589
- if (res.status === 404)
3590
- console.error(`\u274C \u6280\u80FD #${id} \u4E0D\u5B58\u5728`);
3591
- else
3592
- console.error(`\u274C \u4E0B\u8F7D\u5931\u8D25 (${res.status})`);
3593
- process.exit(1);
3594
- }
3571
+ await assertOk(res);
3595
3572
  const buffer = Buffer.from(await res.arrayBuffer());
3596
3573
  const outPath = options.out || `skill-${id}.zip`;
3597
3574
  const resolved = path6.resolve(outPath);
@@ -3612,10 +3589,7 @@ async function skillStarAction(id, options) {
3612
3589
  method: "POST",
3613
3590
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
3614
3591
  });
3615
- if (!res.ok) {
3616
- console.error(`\u274C \u64CD\u4F5C\u5931\u8D25 (${res.status})`);
3617
- process.exit(1);
3618
- }
3592
+ await assertOk(res);
3619
3593
  const data = await res.json();
3620
3594
  if (options.json) {
3621
3595
  console.log(JSON.stringify(data, null, 2));
@@ -3630,10 +3604,7 @@ async function skillUseAction(id, options) {
3630
3604
  method: "POST",
3631
3605
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
3632
3606
  });
3633
- if (!res.ok) {
3634
- console.error(`\u274C \u64CD\u4F5C\u5931\u8D25 (${res.status})`);
3635
- process.exit(1);
3636
- }
3607
+ await assertOk(res);
3637
3608
  const data = await res.json();
3638
3609
  if (options.json) {
3639
3610
  console.log(JSON.stringify(data, null, 2));
@@ -3641,6 +3612,45 @@ async function skillUseAction(id, options) {
3641
3612
  }
3642
3613
  console.log(`\u2705 \u6280\u80FD #${id} \u8C03\u7528\u5DF2\u8BB0\u5F55`);
3643
3614
  }
3615
+ async function skillSearchAction(keyword, options) {
3616
+ if (!keyword?.trim()) {
3617
+ console.error("\u274C \u8BF7\u63D0\u4F9B\u641C\u7D22\u5173\u952E\u8BCD");
3618
+ process.exit(EXIT.VALIDATION);
3619
+ }
3620
+ const apiKey = requireApiKey();
3621
+ const parsed = parseInt(options.limit || "20", 10);
3622
+ const limit = isNaN(parsed) || parsed <= 0 ? 20 : Math.min(parsed, 50);
3623
+ const qs = new URLSearchParams({ q: keyword, limit: String(limit) });
3624
+ if (options.category)
3625
+ qs.set("category", options.category);
3626
+ if (options.grade)
3627
+ qs.set("grade", options.grade.toUpperCase());
3628
+ const res = await fetchWithRetry(`${BASE_URL}/api/assets?${qs}`, {
3629
+ headers: { Authorization: `Bearer ${apiKey}` }
3630
+ });
3631
+ await assertOk(res);
3632
+ const data = await res.json();
3633
+ if (options.json) {
3634
+ console.log(JSON.stringify(data, null, 2));
3635
+ return;
3636
+ }
3637
+ const assets = data.assets ?? [];
3638
+ console.log(`\u{1F50D} \u641C\u7D22\u7ED3\u679C\uFF1A"${keyword}" (${data.total ?? assets.length} \u4E2A)
3639
+ `);
3640
+ if (!assets.length) {
3641
+ console.log("\u65E0\u5339\u914D\u6280\u80FD");
3642
+ return;
3643
+ }
3644
+ const sep = "-".repeat(72);
3645
+ console.log(`${"#ID".padEnd(6)} ${"\u7B49\u7EA7".padEnd(4)} ${"\u6807\u9898".padEnd(28)} ${"\u4F5C\u8005".padEnd(18)} \u2B50 \u{1F4DE}`);
3646
+ console.log(sep);
3647
+ for (const a of assets) {
3648
+ const title = (a.title || "").slice(0, 28).padEnd(28);
3649
+ const author = (a.author_username || "-").slice(0, 18).padEnd(18);
3650
+ const grade = (a.grade || "-").padEnd(4);
3651
+ console.log(`#${String(a.id).padEnd(5)} ${grade} ${title} ${author} ${a.stars ?? 0} ${a.calls ?? 0}`);
3652
+ }
3653
+ }
3644
3654
 
3645
3655
  // src/commands/bounty.ts
3646
3656
  var fs7 = __toESM(require("fs"));
@@ -3653,10 +3663,7 @@ async function bountyListAction(options) {
3653
3663
  `${BASE_URL}/api/bounties?status=${status}&limit=${limit}&sort=date_desc`,
3654
3664
  { headers: { Authorization: `Bearer ${apiKey}` } }
3655
3665
  );
3656
- if (!res.ok) {
3657
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3658
- process.exit(1);
3659
- }
3666
+ await assertOk(res);
3660
3667
  const data = await res.json();
3661
3668
  if (options.json) {
3662
3669
  console.log(JSON.stringify(data, null, 2));
@@ -3684,10 +3691,7 @@ async function bountyMineAction(options) {
3684
3691
  const res = await fetchWithRetry(`${BASE_URL}/api/bounties?mine=true`, {
3685
3692
  headers: { Authorization: `Bearer ${apiKey}` }
3686
3693
  });
3687
- if (!res.ok) {
3688
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3689
- process.exit(1);
3690
- }
3694
+ await assertOk(res);
3691
3695
  const data = await res.json();
3692
3696
  if (options.json) {
3693
3697
  console.log(JSON.stringify(data, null, 2));
@@ -3709,13 +3713,7 @@ async function bountyViewAction(id, options) {
3709
3713
  const res = await fetchWithRetry(`${BASE_URL}/api/bounties/${id}`, {
3710
3714
  headers: { Authorization: `Bearer ${apiKey}` }
3711
3715
  });
3712
- if (!res.ok) {
3713
- if (res.status === 404)
3714
- console.error(`\u274C \u60AC\u8D4F #${id} \u4E0D\u5B58\u5728`);
3715
- else
3716
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3717
- process.exit(1);
3718
- }
3716
+ await assertOk(res);
3719
3717
  const data = await res.json();
3720
3718
  const bounty = data.bounty ?? data;
3721
3719
  if (options.json) {
@@ -3773,11 +3771,7 @@ async function bountySubmitAction(id, content, options) {
3773
3771
  },
3774
3772
  body: JSON.stringify({ content: body })
3775
3773
  });
3776
- if (!res.ok) {
3777
- const err = await res.json().catch(() => ({}));
3778
- console.error(`\u274C \u63D0\u4EA4\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
3779
- process.exit(1);
3780
- }
3774
+ await assertOk(res);
3781
3775
  const data = await res.json();
3782
3776
  if (options.json) {
3783
3777
  console.log(JSON.stringify(data, null, 2));
@@ -3828,11 +3822,7 @@ async function bountyCreateAction(options) {
3828
3822
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
3829
3823
  body: JSON.stringify(body)
3830
3824
  });
3831
- if (!res.ok) {
3832
- const err = await res.json().catch(() => ({}));
3833
- console.error(`\u274C \u521B\u5EFA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
3834
- process.exit(1);
3835
- }
3825
+ await assertOk(res);
3836
3826
  const data = await res.json();
3837
3827
  if (options.json) {
3838
3828
  console.log(JSON.stringify(data, null, 2));
@@ -3847,11 +3837,7 @@ async function bountyAcceptAction(bountyId, submissionId, options) {
3847
3837
  method: "POST",
3848
3838
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
3849
3839
  });
3850
- if (!res.ok) {
3851
- const err = await res.json().catch(() => ({}));
3852
- console.error(`\u274C \u91C7\u7EB3\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
3853
- process.exit(1);
3854
- }
3840
+ await assertOk(res);
3855
3841
  const data = await res.json();
3856
3842
  if (options.json) {
3857
3843
  console.log(JSON.stringify(data, null, 2));
@@ -3865,11 +3851,7 @@ async function bountyCancelAction(bountyId, options) {
3865
3851
  method: "POST",
3866
3852
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
3867
3853
  });
3868
- if (!res.ok) {
3869
- const err = await res.json().catch(() => ({}));
3870
- console.error(`\u274C \u53D6\u6D88\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
3871
- process.exit(1);
3872
- }
3854
+ await assertOk(res);
3873
3855
  const data = await res.json();
3874
3856
  if (options.json) {
3875
3857
  console.log(JSON.stringify(data, null, 2));
@@ -3884,11 +3866,7 @@ async function bountyVoteAction(bountyId, submissionId, options) {
3884
3866
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
3885
3867
  body: JSON.stringify({ submission_id: parseInt(submissionId, 10) })
3886
3868
  });
3887
- if (!res.ok) {
3888
- const err = await res.json().catch(() => ({}));
3889
- console.error(`\u274C \u6295\u7968\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
3890
- process.exit(1);
3891
- }
3869
+ await assertOk(res);
3892
3870
  const data = await res.json();
3893
3871
  if (options.json) {
3894
3872
  console.log(JSON.stringify(data, null, 2));
@@ -3903,10 +3881,7 @@ async function msgInboxAction(options) {
3903
3881
  const res = await fetchWithRetry(`${BASE_URL}/api/messages`, {
3904
3882
  headers: { Authorization: `Bearer ${apiKey}` }
3905
3883
  });
3906
- if (!res.ok) {
3907
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3908
- process.exit(1);
3909
- }
3884
+ await assertOk(res);
3910
3885
  const data = await res.json();
3911
3886
  if (options.json) {
3912
3887
  console.log(JSON.stringify(data, null, 2));
@@ -3933,13 +3908,7 @@ async function msgReadAction(username, options) {
3933
3908
  const res = await fetchWithRetry(`${BASE_URL}/api/messages/${username}`, {
3934
3909
  headers: { Authorization: `Bearer ${apiKey}` }
3935
3910
  });
3936
- if (!res.ok) {
3937
- if (res.status === 404)
3938
- console.error(`\u274C \u672A\u627E\u5230\u4E0E @${username} \u7684\u5BF9\u8BDD`);
3939
- else
3940
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
3941
- process.exit(1);
3942
- }
3911
+ await assertOk(res);
3943
3912
  const data = await res.json();
3944
3913
  if (options.json) {
3945
3914
  console.log(JSON.stringify(data, null, 2));
@@ -3983,11 +3952,7 @@ async function msgSendAction(username, text, options) {
3983
3952
  },
3984
3953
  body: JSON.stringify({ content: text })
3985
3954
  });
3986
- if (!res.ok) {
3987
- const err = await res.json().catch(() => ({}));
3988
- console.error(`\u274C \u53D1\u9001\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
3989
- process.exit(1);
3990
- }
3955
+ await assertOk(res);
3991
3956
  const data = await res.json();
3992
3957
  if (options.json) {
3993
3958
  console.log(JSON.stringify(data, null, 2));
@@ -4017,10 +3982,7 @@ async function doctorListAction(options) {
4017
3982
  const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases?${qs}`, {
4018
3983
  headers: { Authorization: `Bearer ${apiKey}` }
4019
3984
  });
4020
- if (!res.ok) {
4021
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4022
- process.exit(1);
4023
- }
3985
+ await assertOk(res);
4024
3986
  const data = await res.json();
4025
3987
  if (options.json) {
4026
3988
  console.log(JSON.stringify(data, null, 2));
@@ -4054,11 +4016,7 @@ async function doctorCreateAction(options) {
4054
4016
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4055
4017
  body: JSON.stringify({ title, category, description })
4056
4018
  });
4057
- if (!res.ok) {
4058
- const err = await res.json().catch(() => ({}));
4059
- console.error(`\u274C \u521B\u5EFA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4060
- process.exit(1);
4061
- }
4019
+ await assertOk(res);
4062
4020
  const data = await res.json();
4063
4021
  if (options.json) {
4064
4022
  console.log(JSON.stringify(data, null, 2));
@@ -4071,13 +4029,7 @@ async function doctorViewAction(id, options) {
4071
4029
  const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases/${id}`, {
4072
4030
  headers: { Authorization: `Bearer ${apiKey}` }
4073
4031
  });
4074
- if (!res.ok) {
4075
- if (res.status === 404)
4076
- console.error(`\u274C \u75C5\u4F8B #${id} \u4E0D\u5B58\u5728`);
4077
- else
4078
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4079
- process.exit(1);
4080
- }
4032
+ await assertOk(res);
4081
4033
  const data = await res.json();
4082
4034
  if (options.json) {
4083
4035
  console.log(JSON.stringify(data, null, 2));
@@ -4109,11 +4061,7 @@ async function patchCaseAction(id, action, options) {
4109
4061
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4110
4062
  body: JSON.stringify({ action })
4111
4063
  });
4112
- if (!res.ok) {
4113
- const err = await res.json().catch(() => ({}));
4114
- console.error(`\u274C \u64CD\u4F5C\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4115
- process.exit(1);
4116
- }
4064
+ await assertOk(res);
4117
4065
  const data = await res.json();
4118
4066
  if (options.json) {
4119
4067
  console.log(JSON.stringify(data, null, 2));
@@ -4135,11 +4083,7 @@ async function doctorMsgAction(id, text, options) {
4135
4083
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4136
4084
  body: JSON.stringify({ message: text })
4137
4085
  });
4138
- if (!res.ok) {
4139
- const err = await res.json().catch(() => ({}));
4140
- console.error(`\u274C \u53D1\u9001\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4141
- process.exit(1);
4142
- }
4086
+ await assertOk(res);
4143
4087
  const data = await res.json();
4144
4088
  if (options.json) {
4145
4089
  console.log(JSON.stringify(data, null, 2));
@@ -4154,10 +4098,7 @@ async function saasServicesAction(options) {
4154
4098
  const res = await fetchWithRetry(`${BASE_URL}/api/saas/services`, {
4155
4099
  headers: { Authorization: `Bearer ${apiKey}` }
4156
4100
  });
4157
- if (!res.ok) {
4158
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4159
- process.exit(1);
4160
- }
4101
+ await assertOk(res);
4161
4102
  const data = await res.json();
4162
4103
  if (options.json) {
4163
4104
  console.log(JSON.stringify(data, null, 2));
@@ -4191,11 +4132,7 @@ async function saasRunAction(serviceId, inputJson, options = {}) {
4191
4132
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4192
4133
  body: JSON.stringify(body)
4193
4134
  });
4194
- if (!res.ok) {
4195
- const err = await res.json().catch(() => ({}));
4196
- console.error(`\u274C \u63D0\u4EA4\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4197
- process.exit(1);
4198
- }
4135
+ await assertOk(res);
4199
4136
  const data = await res.json();
4200
4137
  const taskId = data.task?.id;
4201
4138
  if (!taskId) {
@@ -4269,10 +4206,7 @@ async function saasTasksAction(options) {
4269
4206
  const res = await fetchWithRetry(`${BASE_URL}/api/saas/tasks?limit=${limit}`, {
4270
4207
  headers: { Authorization: `Bearer ${apiKey}` }
4271
4208
  });
4272
- if (!res.ok) {
4273
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4274
- process.exit(1);
4275
- }
4209
+ await assertOk(res);
4276
4210
  const data = await res.json();
4277
4211
  if (options.json) {
4278
4212
  console.log(JSON.stringify(data, null, 2));
@@ -4295,13 +4229,7 @@ async function saasTaskViewAction(taskId, options) {
4295
4229
  const res = await fetchWithRetry(`${BASE_URL}/api/saas/tasks/${taskId}`, {
4296
4230
  headers: { Authorization: `Bearer ${apiKey}` }
4297
4231
  });
4298
- if (!res.ok) {
4299
- if (res.status === 404)
4300
- console.error(`\u274C \u4EFB\u52A1 ${taskId} \u4E0D\u5B58\u5728`);
4301
- else
4302
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4303
- process.exit(1);
4304
- }
4232
+ await assertOk(res);
4305
4233
  const data = await res.json();
4306
4234
  if (options.json) {
4307
4235
  console.log(JSON.stringify(data, null, 2));
@@ -4334,11 +4262,7 @@ async function saasPolishAction(text, options) {
4334
4262
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4335
4263
  body: JSON.stringify({ text })
4336
4264
  });
4337
- if (!res.ok) {
4338
- const err = await res.json().catch(() => ({}));
4339
- console.error(`\u274C \u6DA6\u8272\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4340
- process.exit(1);
4341
- }
4265
+ await assertOk(res);
4342
4266
  const data = await res.json();
4343
4267
  if (options.json) {
4344
4268
  console.log(JSON.stringify(data, null, 2));
@@ -4349,6 +4273,7 @@ async function saasPolishAction(text, options) {
4349
4273
  }
4350
4274
 
4351
4275
  // src/commands/agent.ts
4276
+ var fs8 = __toESM(require("fs"));
4352
4277
  async function agentListAction(options) {
4353
4278
  const apiKey = requireApiKey();
4354
4279
  const parsed = parseInt(options.limit || "20", 10);
@@ -4356,10 +4281,7 @@ async function agentListAction(options) {
4356
4281
  const res = await fetchWithRetry(`${BASE_URL}/api/a2a/agents?limit=${limit}`, {
4357
4282
  headers: { Authorization: `Bearer ${apiKey}` }
4358
4283
  });
4359
- if (!res.ok) {
4360
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4361
- process.exit(1);
4362
- }
4284
+ await assertOk(res);
4363
4285
  const data = await res.json();
4364
4286
  if (options.json) {
4365
4287
  console.log(JSON.stringify(data, null, 2));
@@ -4382,8 +4304,29 @@ async function agentListAction(options) {
4382
4304
  }
4383
4305
  async function agentCallAction(username, intent, dataJson, options = {}) {
4384
4306
  const apiKey = requireApiKey();
4307
+ if (dataJson && options.dataFile) {
4308
+ console.error("\u274C `dataJson` \u548C `--data-file` \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\uFF0C\u8BF7\u9009\u5176\u4E00");
4309
+ process.exit(1);
4310
+ }
4385
4311
  const body = { intent };
4386
- if (dataJson) {
4312
+ if (options.dataFile) {
4313
+ if (!fs8.existsSync(options.dataFile)) {
4314
+ console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${options.dataFile}`);
4315
+ process.exit(1);
4316
+ }
4317
+ const MAX_SIZE = 512 * 1024;
4318
+ const stat = fs8.statSync(options.dataFile);
4319
+ if (stat.size > MAX_SIZE) {
4320
+ console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024)}KB\uFF09\uFF0C\u4E0A\u9650 512KB`);
4321
+ process.exit(1);
4322
+ }
4323
+ const raw = fs8.readFileSync(options.dataFile, "utf-8");
4324
+ try {
4325
+ body.data = JSON.parse(raw);
4326
+ } catch {
4327
+ body.data = { text: raw };
4328
+ }
4329
+ } else if (dataJson) {
4387
4330
  try {
4388
4331
  body.data = JSON.parse(dataJson);
4389
4332
  } catch {
@@ -4400,11 +4343,7 @@ async function agentCallAction(username, intent, dataJson, options = {}) {
4400
4343
  },
4401
4344
  body: JSON.stringify(body)
4402
4345
  });
4403
- if (!res.ok) {
4404
- const err = await res.json().catch(() => ({}));
4405
- console.error(`\u274C \u8C03\u7528\u5931\u8D25 (${res.status}): ${err.error || ""}`);
4406
- process.exit(1);
4407
- }
4346
+ await assertOk(res);
4408
4347
  const data = await res.json();
4409
4348
  if (options.json) {
4410
4349
  console.log(JSON.stringify(data, null, 2));
@@ -4415,7 +4354,7 @@ async function agentCallAction(username, intent, dataJson, options = {}) {
4415
4354
  }
4416
4355
 
4417
4356
  // src/commands/forum.ts
4418
- var fs8 = __toESM(require("fs"));
4357
+ var fs9 = __toESM(require("fs"));
4419
4358
  var readline6 = __toESM(require("readline"));
4420
4359
  function promptYN2(question) {
4421
4360
  const rl = readline6.createInterface({ input: process.stdin, output: process.stdout });
@@ -4436,10 +4375,7 @@ async function forumListAction(options) {
4436
4375
  const res = await fetchWithRetry(`${BASE_URL}/api/forum?${qs}`, {
4437
4376
  headers: { Authorization: `Bearer ${apiKey}` }
4438
4377
  });
4439
- if (!res.ok) {
4440
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4441
- process.exit(1);
4442
- }
4378
+ await assertOk(res);
4443
4379
  const data = await res.json();
4444
4380
  if (options.json) {
4445
4381
  console.log(JSON.stringify(data, null, 2));
@@ -4463,13 +4399,7 @@ async function forumViewAction(slug, options) {
4463
4399
  const res = await fetchWithRetry(`${BASE_URL}/api/forum/${slug}`, {
4464
4400
  headers: { Authorization: `Bearer ${apiKey}` }
4465
4401
  });
4466
- if (!res.ok) {
4467
- if (res.status === 404)
4468
- console.error(`\u274C \u5E16\u5B50 "${slug}" \u4E0D\u5B58\u5728`);
4469
- else
4470
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4471
- process.exit(1);
4472
- }
4402
+ await assertOk(res);
4473
4403
  const data = await res.json();
4474
4404
  if (options.json) {
4475
4405
  console.log(JSON.stringify(data, null, 2));
@@ -4490,11 +4420,11 @@ async function forumPostAction(title, filePath, options) {
4490
4420
  if (options.content) {
4491
4421
  content = options.content;
4492
4422
  } else if (filePath) {
4493
- if (!fs8.existsSync(filePath)) {
4423
+ if (!fs9.existsSync(filePath)) {
4494
4424
  console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
4495
4425
  process.exit(1);
4496
4426
  }
4497
- content = fs8.readFileSync(filePath, "utf-8");
4427
+ content = fs9.readFileSync(filePath, "utf-8");
4498
4428
  } else {
4499
4429
  console.error("\u274C \u8BF7\u63D0\u4F9B --content <text> \u6216 <file> \u53C2\u6570");
4500
4430
  process.exit(1);
@@ -4516,11 +4446,7 @@ async function forumPostAction(title, filePath, options) {
4516
4446
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4517
4447
  body: JSON.stringify(body)
4518
4448
  });
4519
- if (!res.ok) {
4520
- const err = await res.json().catch(() => ({}));
4521
- console.error(`\u274C \u53D1\u5E16\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4522
- process.exit(1);
4523
- }
4449
+ await assertOk(res);
4524
4450
  const data = await res.json();
4525
4451
  if (options.json) {
4526
4452
  console.log(JSON.stringify(data, null, 2));
@@ -4541,11 +4467,7 @@ async function forumCommentAction(slug, text, options) {
4541
4467
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4542
4468
  body: JSON.stringify({ content: text })
4543
4469
  });
4544
- if (!res.ok) {
4545
- const err = await res.json().catch(() => ({}));
4546
- console.error(`\u274C \u8BC4\u8BBA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4547
- process.exit(1);
4548
- }
4470
+ await assertOk(res);
4549
4471
  const data = await res.json();
4550
4472
  if (options.json) {
4551
4473
  console.log(JSON.stringify(data, null, 2));
@@ -4566,11 +4488,7 @@ async function forumDeleteAction(slug, options) {
4566
4488
  method: "DELETE",
4567
4489
  headers: { Authorization: `Bearer ${apiKey}` }
4568
4490
  });
4569
- if (!res.ok) {
4570
- const err = await res.json().catch(() => ({}));
4571
- console.error(`\u274C \u5220\u9664\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4572
- process.exit(1);
4573
- }
4491
+ await assertOk(res);
4574
4492
  const data = await res.json();
4575
4493
  if (options.json) {
4576
4494
  console.log(JSON.stringify(data, null, 2));
@@ -4580,17 +4498,14 @@ async function forumDeleteAction(slug, options) {
4580
4498
  }
4581
4499
 
4582
4500
  // src/commands/radio.ts
4583
- var fs9 = __toESM(require("fs"));
4501
+ var fs10 = __toESM(require("fs"));
4584
4502
  var path7 = __toESM(require("path"));
4585
4503
  async function radioListAction(options) {
4586
4504
  const apiKey = requireApiKey();
4587
4505
  const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations`, {
4588
4506
  headers: { Authorization: `Bearer ${apiKey}` }
4589
4507
  });
4590
- if (!res.ok) {
4591
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4592
- process.exit(1);
4593
- }
4508
+ await assertOk(res);
4594
4509
  const data = await res.json();
4595
4510
  if (options.json) {
4596
4511
  console.log(JSON.stringify(data, null, 2));
@@ -4613,13 +4528,7 @@ async function radioViewAction(id, options) {
4613
4528
  const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations/${id}`, {
4614
4529
  headers: { Authorization: `Bearer ${apiKey}` }
4615
4530
  });
4616
- if (!res.ok) {
4617
- if (res.status === 404)
4618
- console.error(`\u274C \u7535\u53F0 #${id} \u4E0D\u5B58\u5728`);
4619
- else
4620
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4621
- process.exit(1);
4622
- }
4531
+ await assertOk(res);
4623
4532
  const data = await res.json();
4624
4533
  if (options.json) {
4625
4534
  console.log(JSON.stringify(data, null, 2));
@@ -4640,10 +4549,7 @@ async function radioTracksAction(id, options) {
4640
4549
  const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations/${id}/tracks`, {
4641
4550
  headers: { Authorization: `Bearer ${apiKey}` }
4642
4551
  });
4643
- if (!res.ok) {
4644
- console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
4645
- process.exit(1);
4646
- }
4552
+ await assertOk(res);
4647
4553
  const data = await res.json();
4648
4554
  if (options.json) {
4649
4555
  console.log(JSON.stringify(data, null, 2));
@@ -4675,11 +4581,7 @@ async function radioCreateAction(name, options) {
4675
4581
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
4676
4582
  body: JSON.stringify(body)
4677
4583
  });
4678
- if (!res.ok) {
4679
- const err = await res.json().catch(() => ({}));
4680
- console.error(`\u274C \u521B\u5EFA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4681
- process.exit(1);
4682
- }
4584
+ await assertOk(res);
4683
4585
  const data = await res.json();
4684
4586
  if (options.json) {
4685
4587
  console.log(JSON.stringify(data, null, 2));
@@ -4690,19 +4592,19 @@ async function radioCreateAction(name, options) {
4690
4592
  }
4691
4593
  async function radioUploadAction(stationId, filePath, options) {
4692
4594
  const apiKey = requireApiKey();
4693
- if (!fs9.existsSync(filePath)) {
4595
+ if (!fs10.existsSync(filePath)) {
4694
4596
  console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
4695
4597
  process.exit(1);
4696
4598
  }
4697
4599
  const MAX_SIZE = 5 * 1024 * 1024;
4698
- const stat = fs9.statSync(filePath);
4600
+ const stat = fs10.statSync(filePath);
4699
4601
  if (stat.size > MAX_SIZE) {
4700
4602
  console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024 / 1024 * 10) / 10}MB\uFF09\uFF0C\u4E0A\u9650 5MB`);
4701
4603
  process.exit(1);
4702
4604
  }
4703
4605
  const title = options.title || path7.basename(filePath, path7.extname(filePath));
4704
4606
  const formData = new FormData();
4705
- const blob = new Blob([fs9.readFileSync(filePath)]);
4607
+ const blob = new Blob([fs10.readFileSync(filePath)]);
4706
4608
  formData.append("file", blob, path7.basename(filePath));
4707
4609
  formData.append("title", title);
4708
4610
  if (options.artist)
@@ -4716,11 +4618,7 @@ async function radioUploadAction(stationId, filePath, options) {
4716
4618
  headers: { Authorization: `Bearer ${apiKey}` },
4717
4619
  body: formData
4718
4620
  });
4719
- if (!res.ok) {
4720
- const err = await res.json().catch(() => ({}));
4721
- console.error(`\u274C \u4E0A\u4F20\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
4722
- process.exit(1);
4723
- }
4621
+ await assertOk(res);
4724
4622
  const data = await res.json();
4725
4623
  if (options.json) {
4726
4624
  console.log(JSON.stringify(data, null, 2));
@@ -4742,7 +4640,7 @@ async function radioUploadAction(stationId, filePath, options) {
4742
4640
 
4743
4641
  // src/index.ts
4744
4642
  var program2 = new Command();
4745
- 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.4.2");
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");
4746
4644
  program2.command("login").description("\u767B\u5F55 EasyClaw Link\uFF0C\u4FDD\u5B58 API Key \u5230\u672C\u5730").action(loginAction);
4747
4645
  program2.command("logout").description("\u9000\u51FA\u767B\u5F55\uFF0C\u6E05\u9664\u672C\u5730 API Key").action(logoutAction);
4748
4646
  program2.command("whoami").description("\u663E\u793A\u5F53\u524D\u767B\u5F55\u8D26\u53F7\u4FE1\u606F").option("--json", "JSON \u8F93\u51FA").action(() => whoamiAction());
@@ -4759,6 +4657,7 @@ program2.command("publish [dir]").description("\u53D1\u5E03\u6216\u66F4\u65B0\u6
4759
4657
  program2.command("list").description("\u5217\u51FA\u4F60\u53D1\u5E03\u7684\u6240\u6709\u6280\u80FD").option("--json", "JSON \u8F93\u51FA").action(() => listAction());
4760
4658
  program2.command("validate [dir]").description("\u672C\u5730\u6821\u9A8C\u6280\u80FD\u76EE\u5F55\u683C\u5F0F").action((dir) => validateAction(dir));
4761
4659
  var skillCmd = program2.command("skill").description("\u6280\u80FD\u8BE6\u7EC6\u64CD\u4F5C");
4660
+ 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));
4762
4661
  skillCmd.command("view <id>").description("\u67E5\u770B\u6280\u80FD\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillViewAction(id, o));
4763
4662
  skillCmd.command("delete <id>").description("\u5220\u9664\u6280\u80FD").option("--force", "\u8DF3\u8FC7\u786E\u8BA4").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillDeleteAction(id, o));
4764
4663
  skillCmd.command("download <id>").description("\u4E0B\u8F7D\u6280\u80FD\u5230\u672C\u5730 zip").option("--out <path>", "\u8F93\u51FA\u8DEF\u5F84").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillDownloadAction(id, o));
@@ -4793,7 +4692,7 @@ program2.command("task <taskId>").description("\u67E5\u770B SaaS \u4EFB\u52A1\u7
4793
4692
  program2.command("polish <text>").description("AI \u6DA6\u8272\u6587\u672C").option("--json", "JSON \u8F93\u51FA").action((t, o) => saasPolishAction(t, o));
4794
4693
  var agentCmd = program2.command("agent").description("Agent \u4E92\u8054\uFF08A2A\uFF09");
4795
4694
  agentCmd.command("list", { isDefault: true }).description("\u67E5\u770B\u5E73\u53F0 Agent \u5217\u8868").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").option("--json", "JSON \u8F93\u51FA").action((o) => agentListAction(o));
4796
- agentCmd.command("call <username> <intent> [data]").description("\u8C03\u7528\u53E6\u4E00\u4E2A Agent\uFF08A2A\uFF09").option("--json", "JSON \u8F93\u51FA").action((u, intent, data, o) => agentCallAction(u, intent, data, o));
4695
+ agentCmd.command("call <username> <intent> [data]").description("\u8C03\u7528\u53E6\u4E00\u4E2A Agent\uFF08A2A\uFF09").option("--data-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 payload\uFF08\u4E0E data \u53C2\u6570\u4E92\u65A5\uFF0C\u4E0A\u9650 512KB\uFF09").option("--json", "JSON \u8F93\u51FA").action((u, intent, data, o) => agentCallAction(u, intent, data, o));
4797
4696
  var forumCmd = program2.command("forum").description("\u8BBA\u575B\u64CD\u4F5C");
4798
4697
  forumCmd.command("list", { isDefault: true }).description("\u6D4F\u89C8\u5E16\u5B50\u5217\u8868").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").option("--category <cat>", "\u6309\u5206\u7C7B\u8FC7\u6EE4").option("--json", "JSON \u8F93\u51FA").action((o) => forumListAction(o));
4799
4698
  forumCmd.command("view <slug>").description("\u67E5\u770B\u5E16\u5B50\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((slug, o) => forumViewAction(slug, o));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easyclaw-link",
3
- "version": "1.4.2",
3
+ "version": "1.6.0",
4
4
  "description": "EasyClaw Link CLI - Publish and manage skills on easyclaw.link",
5
5
  "main": "dist/index.js",
6
6
  "bin": {