easyclaw-link 1.5.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.
- package/dist/index.js +318 -363
- 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
|
|
935
|
-
var
|
|
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 =
|
|
1768
|
-
if (
|
|
1767
|
+
const localBin = path9.resolve(baseDir, baseName);
|
|
1768
|
+
if (fs12.existsSync(localBin))
|
|
1769
1769
|
return localBin;
|
|
1770
|
-
if (sourceExt.includes(
|
|
1770
|
+
if (sourceExt.includes(path9.extname(baseName)))
|
|
1771
1771
|
return void 0;
|
|
1772
|
-
const foundExt = sourceExt.find((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 =
|
|
1784
|
+
resolvedScriptPath = fs12.realpathSync(this._scriptPath);
|
|
1785
1785
|
} catch (err) {
|
|
1786
1786
|
resolvedScriptPath = this._scriptPath;
|
|
1787
1787
|
}
|
|
1788
|
-
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
2617
|
-
if (
|
|
2616
|
+
executableDir(path10) {
|
|
2617
|
+
if (path10 === void 0)
|
|
2618
2618
|
return this._executableDir;
|
|
2619
|
-
this._executableDir =
|
|
2619
|
+
this._executableDir = path10;
|
|
2620
2620
|
return this;
|
|
2621
2621
|
}
|
|
2622
2622
|
/**
|
|
@@ -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:
|
|
2856
|
-
process.exit(
|
|
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
|
}
|
|
@@ -2878,10 +2926,10 @@ async function fetchWithRetry(url, options, maxRetries = 3) {
|
|
|
2878
2926
|
// src/commands/login.ts
|
|
2879
2927
|
function prompt(question) {
|
|
2880
2928
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2881
|
-
return new Promise((
|
|
2929
|
+
return new Promise((resolve5) => {
|
|
2882
2930
|
rl.question(question, (answer) => {
|
|
2883
2931
|
rl.close();
|
|
2884
|
-
|
|
2932
|
+
resolve5(answer.trim());
|
|
2885
2933
|
});
|
|
2886
2934
|
});
|
|
2887
2935
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|
|
@@ -3213,10 +3234,10 @@ function prompt2(question) {
|
|
|
3213
3234
|
input: process.stdin,
|
|
3214
3235
|
output: process.stdout
|
|
3215
3236
|
});
|
|
3216
|
-
return new Promise((
|
|
3237
|
+
return new Promise((resolve5) => {
|
|
3217
3238
|
rl.question(question, (answer) => {
|
|
3218
3239
|
rl.close();
|
|
3219
|
-
|
|
3240
|
+
resolve5(answer.trim());
|
|
3220
3241
|
});
|
|
3221
3242
|
});
|
|
3222
3243
|
}
|
|
@@ -3267,12 +3288,7 @@ ${bounty.description}
|
|
|
3267
3288
|
},
|
|
3268
3289
|
body: JSON.stringify({ content })
|
|
3269
3290
|
});
|
|
3270
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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));
|
|
@@ -3449,73 +3446,189 @@ async function profileUpdateAction(options) {
|
|
|
3449
3446
|
// src/commands/validate.ts
|
|
3450
3447
|
var fs5 = __toESM(require("fs"));
|
|
3451
3448
|
var path5 = __toESM(require("path"));
|
|
3452
|
-
var
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
meta.name = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
3459
|
-
if (descMatch)
|
|
3460
|
-
meta.description = descMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
3461
|
-
return meta;
|
|
3462
|
-
}
|
|
3463
|
-
async function validateAction(dir) {
|
|
3464
|
-
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) {
|
|
3465
3455
|
const errors = [];
|
|
3466
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 || ".");
|
|
3467
3508
|
if (!fs5.existsSync(target) || !fs5.statSync(target).isDirectory()) {
|
|
3468
3509
|
console.error(`\u274C \u76EE\u5F55\u4E0D\u5B58\u5728: ${target}`);
|
|
3469
|
-
process.exit(
|
|
3510
|
+
process.exit(EXIT.NOT_FOUND);
|
|
3470
3511
|
}
|
|
3471
|
-
const
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
warnings.push("SKILL.md \u7F3A\u5C11 name \u5B57\u6BB5\uFF08\u5EFA\u8BAE\u5728 frontmatter \u4E2D\u6DFB\u52A0\uFF09");
|
|
3479
|
-
if (!meta.description)
|
|
3480
|
-
warnings.push("SKILL.md \u7F3A\u5C11 description \u5B57\u6BB5");
|
|
3481
|
-
if (content.length < 50)
|
|
3482
|
-
warnings.push("SKILL.md \u5185\u5BB9\u8FC7\u77ED\uFF08\u5C11\u4E8E 50 \u5B57\u7B26\uFF09\uFF0C\u5EFA\u8BAE\u8865\u5145\u8BF4\u660E");
|
|
3483
|
-
if (content.length > 5e4)
|
|
3484
|
-
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;
|
|
3485
3519
|
}
|
|
3486
|
-
|
|
3487
|
-
console.log(`\u274C \u9A8C\u8BC1\u5931\u8D25 (${errors.length} \u4E2A\u9519\u8BEF)
|
|
3520
|
+
console.log(`\u{1F50D} \u6821\u9A8C\u76EE\u5F55: ${target}
|
|
3488
3521
|
`);
|
|
3489
|
-
|
|
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}`);
|
|
3490
3538
|
} else {
|
|
3491
|
-
console.log(
|
|
3492
|
-
`);
|
|
3539
|
+
console.log(`
|
|
3540
|
+
\u274C \u6821\u9A8C\u5931\u8D25\uFF08${errors.length} \u4E2A\u9519\u8BEF\uFF09`);
|
|
3541
|
+
process.exit(EXIT.VALIDATION);
|
|
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 });
|
|
3493
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);
|
|
3494
3613
|
if (warnings.length) {
|
|
3495
|
-
|
|
3614
|
+
for (const w of warnings)
|
|
3615
|
+
console.log(` \u{1F7E1} ${w}`);
|
|
3496
3616
|
}
|
|
3497
3617
|
if (!errors.length) {
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
if (meta.name)
|
|
3501
|
-
console.log(`
|
|
3502
|
-
\u6280\u80FD\u540D\u79F0: ${meta.name}`);
|
|
3503
|
-
if (meta.description)
|
|
3504
|
-
console.log(`\u63CF\u8FF0: ${meta.description}`);
|
|
3505
|
-
}
|
|
3506
|
-
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
|
+
}
|
|
3507
3620
|
}
|
|
3508
3621
|
|
|
3509
3622
|
// src/commands/skill.ts
|
|
3510
|
-
var
|
|
3511
|
-
var
|
|
3623
|
+
var fs7 = __toESM(require("fs"));
|
|
3624
|
+
var path7 = __toESM(require("path"));
|
|
3512
3625
|
var readline3 = __toESM(require("readline"));
|
|
3513
3626
|
function promptYN(question) {
|
|
3514
3627
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
3515
|
-
return new Promise((
|
|
3628
|
+
return new Promise((resolve5) => {
|
|
3516
3629
|
rl.question(question, (ans) => {
|
|
3517
3630
|
rl.close();
|
|
3518
|
-
|
|
3631
|
+
resolve5(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
|
|
3519
3632
|
});
|
|
3520
3633
|
});
|
|
3521
3634
|
}
|
|
@@ -3524,13 +3637,7 @@ async function skillViewAction(id, options) {
|
|
|
3524
3637
|
const res = await fetchWithRetry(`${BASE_URL}/api/assets/${id}`, {
|
|
3525
3638
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3526
3639
|
});
|
|
3527
|
-
|
|
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
|
-
}
|
|
3640
|
+
await assertOk(res);
|
|
3534
3641
|
const data = await res.json();
|
|
3535
3642
|
const asset = data.asset ?? data;
|
|
3536
3643
|
if (options.json) {
|
|
@@ -3565,15 +3672,7 @@ async function skillDeleteAction(id, options) {
|
|
|
3565
3672
|
method: "DELETE",
|
|
3566
3673
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3567
3674
|
});
|
|
3568
|
-
|
|
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
|
-
}
|
|
3675
|
+
await assertOk(res);
|
|
3577
3676
|
if (options.json) {
|
|
3578
3677
|
console.log(JSON.stringify({ success: true, id }));
|
|
3579
3678
|
return;
|
|
@@ -3585,21 +3684,15 @@ async function skillDownloadAction(id, options) {
|
|
|
3585
3684
|
const res = await fetchWithRetry(`${BASE_URL}/api/assets/${id}/download`, {
|
|
3586
3685
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3587
3686
|
});
|
|
3588
|
-
|
|
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
|
-
}
|
|
3687
|
+
await assertOk(res);
|
|
3595
3688
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
3596
3689
|
const outPath = options.out || `skill-${id}.zip`;
|
|
3597
|
-
const resolved =
|
|
3598
|
-
const dir =
|
|
3599
|
-
if (!
|
|
3600
|
-
|
|
3690
|
+
const resolved = path7.resolve(outPath);
|
|
3691
|
+
const dir = path7.dirname(resolved);
|
|
3692
|
+
if (!fs7.existsSync(dir)) {
|
|
3693
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
3601
3694
|
}
|
|
3602
|
-
|
|
3695
|
+
fs7.writeFileSync(resolved, buffer);
|
|
3603
3696
|
if (options.json) {
|
|
3604
3697
|
console.log(JSON.stringify({ success: true, path: resolved, size: buffer.length }));
|
|
3605
3698
|
return;
|
|
@@ -3612,10 +3705,7 @@ async function skillStarAction(id, options) {
|
|
|
3612
3705
|
method: "POST",
|
|
3613
3706
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
|
|
3614
3707
|
});
|
|
3615
|
-
|
|
3616
|
-
console.error(`\u274C \u64CD\u4F5C\u5931\u8D25 (${res.status})`);
|
|
3617
|
-
process.exit(1);
|
|
3618
|
-
}
|
|
3708
|
+
await assertOk(res);
|
|
3619
3709
|
const data = await res.json();
|
|
3620
3710
|
if (options.json) {
|
|
3621
3711
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3630,10 +3720,7 @@ async function skillUseAction(id, options) {
|
|
|
3630
3720
|
method: "POST",
|
|
3631
3721
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
|
|
3632
3722
|
});
|
|
3633
|
-
|
|
3634
|
-
console.error(`\u274C \u64CD\u4F5C\u5931\u8D25 (${res.status})`);
|
|
3635
|
-
process.exit(1);
|
|
3636
|
-
}
|
|
3723
|
+
await assertOk(res);
|
|
3637
3724
|
const data = await res.json();
|
|
3638
3725
|
if (options.json) {
|
|
3639
3726
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3644,19 +3731,20 @@ async function skillUseAction(id, options) {
|
|
|
3644
3731
|
async function skillSearchAction(keyword, options) {
|
|
3645
3732
|
if (!keyword?.trim()) {
|
|
3646
3733
|
console.error("\u274C \u8BF7\u63D0\u4F9B\u641C\u7D22\u5173\u952E\u8BCD");
|
|
3647
|
-
process.exit(
|
|
3734
|
+
process.exit(EXIT.VALIDATION);
|
|
3648
3735
|
}
|
|
3649
3736
|
const apiKey = requireApiKey();
|
|
3650
3737
|
const parsed = parseInt(options.limit || "20", 10);
|
|
3651
3738
|
const limit = isNaN(parsed) || parsed <= 0 ? 20 : Math.min(parsed, 50);
|
|
3652
3739
|
const qs = new URLSearchParams({ q: keyword, limit: String(limit) });
|
|
3740
|
+
if (options.category)
|
|
3741
|
+
qs.set("category", options.category);
|
|
3742
|
+
if (options.grade)
|
|
3743
|
+
qs.set("grade", options.grade.toUpperCase());
|
|
3653
3744
|
const res = await fetchWithRetry(`${BASE_URL}/api/assets?${qs}`, {
|
|
3654
3745
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3655
3746
|
});
|
|
3656
|
-
|
|
3657
|
-
console.error(`\u274C \u641C\u7D22\u5931\u8D25 (${res.status})`);
|
|
3658
|
-
process.exit(1);
|
|
3659
|
-
}
|
|
3747
|
+
await assertOk(res);
|
|
3660
3748
|
const data = await res.json();
|
|
3661
3749
|
if (options.json) {
|
|
3662
3750
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3681,7 +3769,7 @@ async function skillSearchAction(keyword, options) {
|
|
|
3681
3769
|
}
|
|
3682
3770
|
|
|
3683
3771
|
// src/commands/bounty.ts
|
|
3684
|
-
var
|
|
3772
|
+
var fs8 = __toESM(require("fs"));
|
|
3685
3773
|
async function bountyListAction(options) {
|
|
3686
3774
|
const apiKey = requireApiKey();
|
|
3687
3775
|
const status = options.status || "open";
|
|
@@ -3691,10 +3779,7 @@ async function bountyListAction(options) {
|
|
|
3691
3779
|
`${BASE_URL}/api/bounties?status=${status}&limit=${limit}&sort=date_desc`,
|
|
3692
3780
|
{ headers: { Authorization: `Bearer ${apiKey}` } }
|
|
3693
3781
|
);
|
|
3694
|
-
|
|
3695
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
3696
|
-
process.exit(1);
|
|
3697
|
-
}
|
|
3782
|
+
await assertOk(res);
|
|
3698
3783
|
const data = await res.json();
|
|
3699
3784
|
if (options.json) {
|
|
3700
3785
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3722,10 +3807,7 @@ async function bountyMineAction(options) {
|
|
|
3722
3807
|
const res = await fetchWithRetry(`${BASE_URL}/api/bounties?mine=true`, {
|
|
3723
3808
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3724
3809
|
});
|
|
3725
|
-
|
|
3726
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
3727
|
-
process.exit(1);
|
|
3728
|
-
}
|
|
3810
|
+
await assertOk(res);
|
|
3729
3811
|
const data = await res.json();
|
|
3730
3812
|
if (options.json) {
|
|
3731
3813
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3747,13 +3829,7 @@ async function bountyViewAction(id, options) {
|
|
|
3747
3829
|
const res = await fetchWithRetry(`${BASE_URL}/api/bounties/${id}`, {
|
|
3748
3830
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3749
3831
|
});
|
|
3750
|
-
|
|
3751
|
-
if (res.status === 404)
|
|
3752
|
-
console.error(`\u274C \u60AC\u8D4F #${id} \u4E0D\u5B58\u5728`);
|
|
3753
|
-
else
|
|
3754
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
3755
|
-
process.exit(1);
|
|
3756
|
-
}
|
|
3832
|
+
await assertOk(res);
|
|
3757
3833
|
const data = await res.json();
|
|
3758
3834
|
const bounty = data.bounty ?? data;
|
|
3759
3835
|
if (options.json) {
|
|
@@ -3787,17 +3863,17 @@ async function bountySubmitAction(id, content, options) {
|
|
|
3787
3863
|
let body = content;
|
|
3788
3864
|
if (content.startsWith("@")) {
|
|
3789
3865
|
const filePath = content.slice(1);
|
|
3790
|
-
if (!
|
|
3866
|
+
if (!fs8.existsSync(filePath)) {
|
|
3791
3867
|
console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
|
|
3792
3868
|
process.exit(1);
|
|
3793
3869
|
}
|
|
3794
|
-
const stat =
|
|
3870
|
+
const stat = fs8.statSync(filePath);
|
|
3795
3871
|
const MAX_SIZE = 512 * 1024;
|
|
3796
3872
|
if (stat.size > MAX_SIZE) {
|
|
3797
3873
|
console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024)}KB\uFF09\uFF0C\u4E0A\u9650 512KB`);
|
|
3798
3874
|
process.exit(1);
|
|
3799
3875
|
}
|
|
3800
|
-
body =
|
|
3876
|
+
body = fs8.readFileSync(filePath, "utf-8");
|
|
3801
3877
|
}
|
|
3802
3878
|
if (!body.trim()) {
|
|
3803
3879
|
console.error("\u274C \u63D0\u4EA4\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
|
|
@@ -3811,11 +3887,7 @@ async function bountySubmitAction(id, content, options) {
|
|
|
3811
3887
|
},
|
|
3812
3888
|
body: JSON.stringify({ content: body })
|
|
3813
3889
|
});
|
|
3814
|
-
|
|
3815
|
-
const err = await res.json().catch(() => ({}));
|
|
3816
|
-
console.error(`\u274C \u63D0\u4EA4\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
3817
|
-
process.exit(1);
|
|
3818
|
-
}
|
|
3890
|
+
await assertOk(res);
|
|
3819
3891
|
const data = await res.json();
|
|
3820
3892
|
if (options.json) {
|
|
3821
3893
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3866,11 +3938,7 @@ async function bountyCreateAction(options) {
|
|
|
3866
3938
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
3867
3939
|
body: JSON.stringify(body)
|
|
3868
3940
|
});
|
|
3869
|
-
|
|
3870
|
-
const err = await res.json().catch(() => ({}));
|
|
3871
|
-
console.error(`\u274C \u521B\u5EFA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
3872
|
-
process.exit(1);
|
|
3873
|
-
}
|
|
3941
|
+
await assertOk(res);
|
|
3874
3942
|
const data = await res.json();
|
|
3875
3943
|
if (options.json) {
|
|
3876
3944
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3885,11 +3953,7 @@ async function bountyAcceptAction(bountyId, submissionId, options) {
|
|
|
3885
3953
|
method: "POST",
|
|
3886
3954
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
|
|
3887
3955
|
});
|
|
3888
|
-
|
|
3889
|
-
const err = await res.json().catch(() => ({}));
|
|
3890
|
-
console.error(`\u274C \u91C7\u7EB3\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
3891
|
-
process.exit(1);
|
|
3892
|
-
}
|
|
3956
|
+
await assertOk(res);
|
|
3893
3957
|
const data = await res.json();
|
|
3894
3958
|
if (options.json) {
|
|
3895
3959
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3903,11 +3967,7 @@ async function bountyCancelAction(bountyId, options) {
|
|
|
3903
3967
|
method: "POST",
|
|
3904
3968
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
|
|
3905
3969
|
});
|
|
3906
|
-
|
|
3907
|
-
const err = await res.json().catch(() => ({}));
|
|
3908
|
-
console.error(`\u274C \u53D6\u6D88\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
3909
|
-
process.exit(1);
|
|
3910
|
-
}
|
|
3970
|
+
await assertOk(res);
|
|
3911
3971
|
const data = await res.json();
|
|
3912
3972
|
if (options.json) {
|
|
3913
3973
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3922,11 +3982,7 @@ async function bountyVoteAction(bountyId, submissionId, options) {
|
|
|
3922
3982
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
3923
3983
|
body: JSON.stringify({ submission_id: parseInt(submissionId, 10) })
|
|
3924
3984
|
});
|
|
3925
|
-
|
|
3926
|
-
const err = await res.json().catch(() => ({}));
|
|
3927
|
-
console.error(`\u274C \u6295\u7968\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
3928
|
-
process.exit(1);
|
|
3929
|
-
}
|
|
3985
|
+
await assertOk(res);
|
|
3930
3986
|
const data = await res.json();
|
|
3931
3987
|
if (options.json) {
|
|
3932
3988
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3941,10 +3997,7 @@ async function msgInboxAction(options) {
|
|
|
3941
3997
|
const res = await fetchWithRetry(`${BASE_URL}/api/messages`, {
|
|
3942
3998
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3943
3999
|
});
|
|
3944
|
-
|
|
3945
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
3946
|
-
process.exit(1);
|
|
3947
|
-
}
|
|
4000
|
+
await assertOk(res);
|
|
3948
4001
|
const data = await res.json();
|
|
3949
4002
|
if (options.json) {
|
|
3950
4003
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -3971,13 +4024,7 @@ async function msgReadAction(username, options) {
|
|
|
3971
4024
|
const res = await fetchWithRetry(`${BASE_URL}/api/messages/${username}`, {
|
|
3972
4025
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3973
4026
|
});
|
|
3974
|
-
|
|
3975
|
-
if (res.status === 404)
|
|
3976
|
-
console.error(`\u274C \u672A\u627E\u5230\u4E0E @${username} \u7684\u5BF9\u8BDD`);
|
|
3977
|
-
else
|
|
3978
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
3979
|
-
process.exit(1);
|
|
3980
|
-
}
|
|
4027
|
+
await assertOk(res);
|
|
3981
4028
|
const data = await res.json();
|
|
3982
4029
|
if (options.json) {
|
|
3983
4030
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4021,11 +4068,7 @@ async function msgSendAction(username, text, options) {
|
|
|
4021
4068
|
},
|
|
4022
4069
|
body: JSON.stringify({ content: text })
|
|
4023
4070
|
});
|
|
4024
|
-
|
|
4025
|
-
const err = await res.json().catch(() => ({}));
|
|
4026
|
-
console.error(`\u274C \u53D1\u9001\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4027
|
-
process.exit(1);
|
|
4028
|
-
}
|
|
4071
|
+
await assertOk(res);
|
|
4029
4072
|
const data = await res.json();
|
|
4030
4073
|
if (options.json) {
|
|
4031
4074
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4055,10 +4098,7 @@ async function doctorListAction(options) {
|
|
|
4055
4098
|
const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases?${qs}`, {
|
|
4056
4099
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4057
4100
|
});
|
|
4058
|
-
|
|
4059
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4060
|
-
process.exit(1);
|
|
4061
|
-
}
|
|
4101
|
+
await assertOk(res);
|
|
4062
4102
|
const data = await res.json();
|
|
4063
4103
|
if (options.json) {
|
|
4064
4104
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4092,11 +4132,7 @@ async function doctorCreateAction(options) {
|
|
|
4092
4132
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4093
4133
|
body: JSON.stringify({ title, category, description })
|
|
4094
4134
|
});
|
|
4095
|
-
|
|
4096
|
-
const err = await res.json().catch(() => ({}));
|
|
4097
|
-
console.error(`\u274C \u521B\u5EFA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4098
|
-
process.exit(1);
|
|
4099
|
-
}
|
|
4135
|
+
await assertOk(res);
|
|
4100
4136
|
const data = await res.json();
|
|
4101
4137
|
if (options.json) {
|
|
4102
4138
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4109,13 +4145,7 @@ async function doctorViewAction(id, options) {
|
|
|
4109
4145
|
const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases/${id}`, {
|
|
4110
4146
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4111
4147
|
});
|
|
4112
|
-
|
|
4113
|
-
if (res.status === 404)
|
|
4114
|
-
console.error(`\u274C \u75C5\u4F8B #${id} \u4E0D\u5B58\u5728`);
|
|
4115
|
-
else
|
|
4116
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4117
|
-
process.exit(1);
|
|
4118
|
-
}
|
|
4148
|
+
await assertOk(res);
|
|
4119
4149
|
const data = await res.json();
|
|
4120
4150
|
if (options.json) {
|
|
4121
4151
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4147,11 +4177,7 @@ async function patchCaseAction(id, action, options) {
|
|
|
4147
4177
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4148
4178
|
body: JSON.stringify({ action })
|
|
4149
4179
|
});
|
|
4150
|
-
|
|
4151
|
-
const err = await res.json().catch(() => ({}));
|
|
4152
|
-
console.error(`\u274C \u64CD\u4F5C\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4153
|
-
process.exit(1);
|
|
4154
|
-
}
|
|
4180
|
+
await assertOk(res);
|
|
4155
4181
|
const data = await res.json();
|
|
4156
4182
|
if (options.json) {
|
|
4157
4183
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4173,11 +4199,7 @@ async function doctorMsgAction(id, text, options) {
|
|
|
4173
4199
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4174
4200
|
body: JSON.stringify({ message: text })
|
|
4175
4201
|
});
|
|
4176
|
-
|
|
4177
|
-
const err = await res.json().catch(() => ({}));
|
|
4178
|
-
console.error(`\u274C \u53D1\u9001\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4179
|
-
process.exit(1);
|
|
4180
|
-
}
|
|
4202
|
+
await assertOk(res);
|
|
4181
4203
|
const data = await res.json();
|
|
4182
4204
|
if (options.json) {
|
|
4183
4205
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4192,10 +4214,7 @@ async function saasServicesAction(options) {
|
|
|
4192
4214
|
const res = await fetchWithRetry(`${BASE_URL}/api/saas/services`, {
|
|
4193
4215
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4194
4216
|
});
|
|
4195
|
-
|
|
4196
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4197
|
-
process.exit(1);
|
|
4198
|
-
}
|
|
4217
|
+
await assertOk(res);
|
|
4199
4218
|
const data = await res.json();
|
|
4200
4219
|
if (options.json) {
|
|
4201
4220
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4229,11 +4248,7 @@ async function saasRunAction(serviceId, inputJson, options = {}) {
|
|
|
4229
4248
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4230
4249
|
body: JSON.stringify(body)
|
|
4231
4250
|
});
|
|
4232
|
-
|
|
4233
|
-
const err = await res.json().catch(() => ({}));
|
|
4234
|
-
console.error(`\u274C \u63D0\u4EA4\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4235
|
-
process.exit(1);
|
|
4236
|
-
}
|
|
4251
|
+
await assertOk(res);
|
|
4237
4252
|
const data = await res.json();
|
|
4238
4253
|
const taskId = data.task?.id;
|
|
4239
4254
|
if (!taskId) {
|
|
@@ -4307,10 +4322,7 @@ async function saasTasksAction(options) {
|
|
|
4307
4322
|
const res = await fetchWithRetry(`${BASE_URL}/api/saas/tasks?limit=${limit}`, {
|
|
4308
4323
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4309
4324
|
});
|
|
4310
|
-
|
|
4311
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4312
|
-
process.exit(1);
|
|
4313
|
-
}
|
|
4325
|
+
await assertOk(res);
|
|
4314
4326
|
const data = await res.json();
|
|
4315
4327
|
if (options.json) {
|
|
4316
4328
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4333,13 +4345,7 @@ async function saasTaskViewAction(taskId, options) {
|
|
|
4333
4345
|
const res = await fetchWithRetry(`${BASE_URL}/api/saas/tasks/${taskId}`, {
|
|
4334
4346
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4335
4347
|
});
|
|
4336
|
-
|
|
4337
|
-
if (res.status === 404)
|
|
4338
|
-
console.error(`\u274C \u4EFB\u52A1 ${taskId} \u4E0D\u5B58\u5728`);
|
|
4339
|
-
else
|
|
4340
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4341
|
-
process.exit(1);
|
|
4342
|
-
}
|
|
4348
|
+
await assertOk(res);
|
|
4343
4349
|
const data = await res.json();
|
|
4344
4350
|
if (options.json) {
|
|
4345
4351
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4372,11 +4378,7 @@ async function saasPolishAction(text, options) {
|
|
|
4372
4378
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4373
4379
|
body: JSON.stringify({ text })
|
|
4374
4380
|
});
|
|
4375
|
-
|
|
4376
|
-
const err = await res.json().catch(() => ({}));
|
|
4377
|
-
console.error(`\u274C \u6DA6\u8272\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4378
|
-
process.exit(1);
|
|
4379
|
-
}
|
|
4381
|
+
await assertOk(res);
|
|
4380
4382
|
const data = await res.json();
|
|
4381
4383
|
if (options.json) {
|
|
4382
4384
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4387,7 +4389,7 @@ async function saasPolishAction(text, options) {
|
|
|
4387
4389
|
}
|
|
4388
4390
|
|
|
4389
4391
|
// src/commands/agent.ts
|
|
4390
|
-
var
|
|
4392
|
+
var fs9 = __toESM(require("fs"));
|
|
4391
4393
|
async function agentListAction(options) {
|
|
4392
4394
|
const apiKey = requireApiKey();
|
|
4393
4395
|
const parsed = parseInt(options.limit || "20", 10);
|
|
@@ -4395,10 +4397,7 @@ async function agentListAction(options) {
|
|
|
4395
4397
|
const res = await fetchWithRetry(`${BASE_URL}/api/a2a/agents?limit=${limit}`, {
|
|
4396
4398
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4397
4399
|
});
|
|
4398
|
-
|
|
4399
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4400
|
-
process.exit(1);
|
|
4401
|
-
}
|
|
4400
|
+
await assertOk(res);
|
|
4402
4401
|
const data = await res.json();
|
|
4403
4402
|
if (options.json) {
|
|
4404
4403
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4427,17 +4426,17 @@ async function agentCallAction(username, intent, dataJson, options = {}) {
|
|
|
4427
4426
|
}
|
|
4428
4427
|
const body = { intent };
|
|
4429
4428
|
if (options.dataFile) {
|
|
4430
|
-
if (!
|
|
4429
|
+
if (!fs9.existsSync(options.dataFile)) {
|
|
4431
4430
|
console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${options.dataFile}`);
|
|
4432
4431
|
process.exit(1);
|
|
4433
4432
|
}
|
|
4434
4433
|
const MAX_SIZE = 512 * 1024;
|
|
4435
|
-
const stat =
|
|
4434
|
+
const stat = fs9.statSync(options.dataFile);
|
|
4436
4435
|
if (stat.size > MAX_SIZE) {
|
|
4437
4436
|
console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024)}KB\uFF09\uFF0C\u4E0A\u9650 512KB`);
|
|
4438
4437
|
process.exit(1);
|
|
4439
4438
|
}
|
|
4440
|
-
const raw =
|
|
4439
|
+
const raw = fs9.readFileSync(options.dataFile, "utf-8");
|
|
4441
4440
|
try {
|
|
4442
4441
|
body.data = JSON.parse(raw);
|
|
4443
4442
|
} catch {
|
|
@@ -4460,11 +4459,7 @@ async function agentCallAction(username, intent, dataJson, options = {}) {
|
|
|
4460
4459
|
},
|
|
4461
4460
|
body: JSON.stringify(body)
|
|
4462
4461
|
});
|
|
4463
|
-
|
|
4464
|
-
const err = await res.json().catch(() => ({}));
|
|
4465
|
-
console.error(`\u274C \u8C03\u7528\u5931\u8D25 (${res.status}): ${err.error || ""}`);
|
|
4466
|
-
process.exit(1);
|
|
4467
|
-
}
|
|
4462
|
+
await assertOk(res);
|
|
4468
4463
|
const data = await res.json();
|
|
4469
4464
|
if (options.json) {
|
|
4470
4465
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4475,14 +4470,14 @@ async function agentCallAction(username, intent, dataJson, options = {}) {
|
|
|
4475
4470
|
}
|
|
4476
4471
|
|
|
4477
4472
|
// src/commands/forum.ts
|
|
4478
|
-
var
|
|
4473
|
+
var fs10 = __toESM(require("fs"));
|
|
4479
4474
|
var readline6 = __toESM(require("readline"));
|
|
4480
4475
|
function promptYN2(question) {
|
|
4481
4476
|
const rl = readline6.createInterface({ input: process.stdin, output: process.stdout });
|
|
4482
|
-
return new Promise((
|
|
4477
|
+
return new Promise((resolve5) => {
|
|
4483
4478
|
rl.question(question, (ans) => {
|
|
4484
4479
|
rl.close();
|
|
4485
|
-
|
|
4480
|
+
resolve5(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
|
|
4486
4481
|
});
|
|
4487
4482
|
});
|
|
4488
4483
|
}
|
|
@@ -4496,10 +4491,7 @@ async function forumListAction(options) {
|
|
|
4496
4491
|
const res = await fetchWithRetry(`${BASE_URL}/api/forum?${qs}`, {
|
|
4497
4492
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4498
4493
|
});
|
|
4499
|
-
|
|
4500
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4501
|
-
process.exit(1);
|
|
4502
|
-
}
|
|
4494
|
+
await assertOk(res);
|
|
4503
4495
|
const data = await res.json();
|
|
4504
4496
|
if (options.json) {
|
|
4505
4497
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4523,13 +4515,7 @@ async function forumViewAction(slug, options) {
|
|
|
4523
4515
|
const res = await fetchWithRetry(`${BASE_URL}/api/forum/${slug}`, {
|
|
4524
4516
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4525
4517
|
});
|
|
4526
|
-
|
|
4527
|
-
if (res.status === 404)
|
|
4528
|
-
console.error(`\u274C \u5E16\u5B50 "${slug}" \u4E0D\u5B58\u5728`);
|
|
4529
|
-
else
|
|
4530
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4531
|
-
process.exit(1);
|
|
4532
|
-
}
|
|
4518
|
+
await assertOk(res);
|
|
4533
4519
|
const data = await res.json();
|
|
4534
4520
|
if (options.json) {
|
|
4535
4521
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4550,11 +4536,11 @@ async function forumPostAction(title, filePath, options) {
|
|
|
4550
4536
|
if (options.content) {
|
|
4551
4537
|
content = options.content;
|
|
4552
4538
|
} else if (filePath) {
|
|
4553
|
-
if (!
|
|
4539
|
+
if (!fs10.existsSync(filePath)) {
|
|
4554
4540
|
console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
|
|
4555
4541
|
process.exit(1);
|
|
4556
4542
|
}
|
|
4557
|
-
content =
|
|
4543
|
+
content = fs10.readFileSync(filePath, "utf-8");
|
|
4558
4544
|
} else {
|
|
4559
4545
|
console.error("\u274C \u8BF7\u63D0\u4F9B --content <text> \u6216 <file> \u53C2\u6570");
|
|
4560
4546
|
process.exit(1);
|
|
@@ -4576,11 +4562,7 @@ async function forumPostAction(title, filePath, options) {
|
|
|
4576
4562
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4577
4563
|
body: JSON.stringify(body)
|
|
4578
4564
|
});
|
|
4579
|
-
|
|
4580
|
-
const err = await res.json().catch(() => ({}));
|
|
4581
|
-
console.error(`\u274C \u53D1\u5E16\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4582
|
-
process.exit(1);
|
|
4583
|
-
}
|
|
4565
|
+
await assertOk(res);
|
|
4584
4566
|
const data = await res.json();
|
|
4585
4567
|
if (options.json) {
|
|
4586
4568
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4601,11 +4583,7 @@ async function forumCommentAction(slug, text, options) {
|
|
|
4601
4583
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4602
4584
|
body: JSON.stringify({ content: text })
|
|
4603
4585
|
});
|
|
4604
|
-
|
|
4605
|
-
const err = await res.json().catch(() => ({}));
|
|
4606
|
-
console.error(`\u274C \u8BC4\u8BBA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4607
|
-
process.exit(1);
|
|
4608
|
-
}
|
|
4586
|
+
await assertOk(res);
|
|
4609
4587
|
const data = await res.json();
|
|
4610
4588
|
if (options.json) {
|
|
4611
4589
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4626,11 +4604,7 @@ async function forumDeleteAction(slug, options) {
|
|
|
4626
4604
|
method: "DELETE",
|
|
4627
4605
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4628
4606
|
});
|
|
4629
|
-
|
|
4630
|
-
const err = await res.json().catch(() => ({}));
|
|
4631
|
-
console.error(`\u274C \u5220\u9664\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4632
|
-
process.exit(1);
|
|
4633
|
-
}
|
|
4607
|
+
await assertOk(res);
|
|
4634
4608
|
const data = await res.json();
|
|
4635
4609
|
if (options.json) {
|
|
4636
4610
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4640,17 +4614,14 @@ async function forumDeleteAction(slug, options) {
|
|
|
4640
4614
|
}
|
|
4641
4615
|
|
|
4642
4616
|
// src/commands/radio.ts
|
|
4643
|
-
var
|
|
4644
|
-
var
|
|
4617
|
+
var fs11 = __toESM(require("fs"));
|
|
4618
|
+
var path8 = __toESM(require("path"));
|
|
4645
4619
|
async function radioListAction(options) {
|
|
4646
4620
|
const apiKey = requireApiKey();
|
|
4647
4621
|
const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations`, {
|
|
4648
4622
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4649
4623
|
});
|
|
4650
|
-
|
|
4651
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4652
|
-
process.exit(1);
|
|
4653
|
-
}
|
|
4624
|
+
await assertOk(res);
|
|
4654
4625
|
const data = await res.json();
|
|
4655
4626
|
if (options.json) {
|
|
4656
4627
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4673,13 +4644,7 @@ async function radioViewAction(id, options) {
|
|
|
4673
4644
|
const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations/${id}`, {
|
|
4674
4645
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4675
4646
|
});
|
|
4676
|
-
|
|
4677
|
-
if (res.status === 404)
|
|
4678
|
-
console.error(`\u274C \u7535\u53F0 #${id} \u4E0D\u5B58\u5728`);
|
|
4679
|
-
else
|
|
4680
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4681
|
-
process.exit(1);
|
|
4682
|
-
}
|
|
4647
|
+
await assertOk(res);
|
|
4683
4648
|
const data = await res.json();
|
|
4684
4649
|
if (options.json) {
|
|
4685
4650
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4700,10 +4665,7 @@ async function radioTracksAction(id, options) {
|
|
|
4700
4665
|
const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations/${id}/tracks`, {
|
|
4701
4666
|
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4702
4667
|
});
|
|
4703
|
-
|
|
4704
|
-
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4705
|
-
process.exit(1);
|
|
4706
|
-
}
|
|
4668
|
+
await assertOk(res);
|
|
4707
4669
|
const data = await res.json();
|
|
4708
4670
|
if (options.json) {
|
|
4709
4671
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4735,11 +4697,7 @@ async function radioCreateAction(name, options) {
|
|
|
4735
4697
|
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4736
4698
|
body: JSON.stringify(body)
|
|
4737
4699
|
});
|
|
4738
|
-
|
|
4739
|
-
const err = await res.json().catch(() => ({}));
|
|
4740
|
-
console.error(`\u274C \u521B\u5EFA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4741
|
-
process.exit(1);
|
|
4742
|
-
}
|
|
4700
|
+
await assertOk(res);
|
|
4743
4701
|
const data = await res.json();
|
|
4744
4702
|
if (options.json) {
|
|
4745
4703
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4750,20 +4708,20 @@ async function radioCreateAction(name, options) {
|
|
|
4750
4708
|
}
|
|
4751
4709
|
async function radioUploadAction(stationId, filePath, options) {
|
|
4752
4710
|
const apiKey = requireApiKey();
|
|
4753
|
-
if (!
|
|
4711
|
+
if (!fs11.existsSync(filePath)) {
|
|
4754
4712
|
console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
|
|
4755
4713
|
process.exit(1);
|
|
4756
4714
|
}
|
|
4757
4715
|
const MAX_SIZE = 5 * 1024 * 1024;
|
|
4758
|
-
const stat =
|
|
4716
|
+
const stat = fs11.statSync(filePath);
|
|
4759
4717
|
if (stat.size > MAX_SIZE) {
|
|
4760
4718
|
console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024 / 1024 * 10) / 10}MB\uFF09\uFF0C\u4E0A\u9650 5MB`);
|
|
4761
4719
|
process.exit(1);
|
|
4762
4720
|
}
|
|
4763
|
-
const title = options.title ||
|
|
4721
|
+
const title = options.title || path8.basename(filePath, path8.extname(filePath));
|
|
4764
4722
|
const formData = new FormData();
|
|
4765
|
-
const blob = new Blob([
|
|
4766
|
-
formData.append("file", blob,
|
|
4723
|
+
const blob = new Blob([fs11.readFileSync(filePath)]);
|
|
4724
|
+
formData.append("file", blob, path8.basename(filePath));
|
|
4767
4725
|
formData.append("title", title);
|
|
4768
4726
|
if (options.artist)
|
|
4769
4727
|
formData.append("artist", options.artist);
|
|
@@ -4776,11 +4734,7 @@ async function radioUploadAction(stationId, filePath, options) {
|
|
|
4776
4734
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
4777
4735
|
body: formData
|
|
4778
4736
|
});
|
|
4779
|
-
|
|
4780
|
-
const err = await res.json().catch(() => ({}));
|
|
4781
|
-
console.error(`\u274C \u4E0A\u4F20\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4782
|
-
process.exit(1);
|
|
4783
|
-
}
|
|
4737
|
+
await assertOk(res);
|
|
4784
4738
|
const data = await res.json();
|
|
4785
4739
|
if (options.json) {
|
|
4786
4740
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -4802,7 +4756,7 @@ async function radioUploadAction(stationId, filePath, options) {
|
|
|
4802
4756
|
|
|
4803
4757
|
// src/index.ts
|
|
4804
4758
|
var program2 = new Command();
|
|
4805
|
-
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.
|
|
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");
|
|
4806
4760
|
program2.command("login").description("\u767B\u5F55 EasyClaw Link\uFF0C\u4FDD\u5B58 API Key \u5230\u672C\u5730").action(loginAction);
|
|
4807
4761
|
program2.command("logout").description("\u9000\u51FA\u767B\u5F55\uFF0C\u6E05\u9664\u672C\u5730 API Key").action(logoutAction);
|
|
4808
4762
|
program2.command("whoami").description("\u663E\u793A\u5F53\u524D\u767B\u5F55\u8D26\u53F7\u4FE1\u606F").option("--json", "JSON \u8F93\u51FA").action(() => whoamiAction());
|
|
@@ -4817,9 +4771,10 @@ notifCmd.command("list", { isDefault: true }).description("\u5217\u51FA\u901A\u7
|
|
|
4817
4771
|
notifCmd.command("read").description("\u6807\u8BB0\u6240\u6709\u901A\u77E5\u4E3A\u5DF2\u8BFB").option("--json", "JSON \u8F93\u51FA").action((o) => notificationsReadAction(o));
|
|
4818
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);
|
|
4819
4773
|
program2.command("list").description("\u5217\u51FA\u4F60\u53D1\u5E03\u7684\u6240\u6709\u6280\u80FD").option("--json", "JSON \u8F93\u51FA").action(() => listAction());
|
|
4820
|
-
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));
|
|
4821
4776
|
var skillCmd = program2.command("skill").description("\u6280\u80FD\u8BE6\u7EC6\u64CD\u4F5C");
|
|
4822
|
-
skillCmd.command("search <keyword>").description("\u641C\u7D22\u5E73\u53F0\u6280\u80FD").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").option("--json", "JSON \u8F93\u51FA").action((kw, o) => skillSearchAction(kw, o));
|
|
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));
|
|
4823
4778
|
skillCmd.command("view <id>").description("\u67E5\u770B\u6280\u80FD\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillViewAction(id, o));
|
|
4824
4779
|
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));
|
|
4825
4780
|
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));
|