easyclaw-link 1.3.1 → 1.4.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 +1015 -50
- 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 path8 = require("path");
|
|
935
|
+
var fs10 = 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 = path8.resolve(baseDir, baseName);
|
|
1768
|
+
if (fs10.existsSync(localBin))
|
|
1769
1769
|
return localBin;
|
|
1770
|
-
if (sourceExt.includes(
|
|
1770
|
+
if (sourceExt.includes(path8.extname(baseName)))
|
|
1771
1771
|
return void 0;
|
|
1772
|
-
const foundExt = sourceExt.find((ext) =>
|
|
1772
|
+
const foundExt = sourceExt.find((ext) => fs10.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 = fs10.realpathSync(this._scriptPath);
|
|
1785
1785
|
} catch (err) {
|
|
1786
1786
|
resolvedScriptPath = this._scriptPath;
|
|
1787
1787
|
}
|
|
1788
|
-
executableDir =
|
|
1788
|
+
executableDir = path8.resolve(path8.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 = path8.basename(this._scriptPath, path8.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(path8.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 = path8.basename(filename, path8.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(path9) {
|
|
2617
|
+
if (path9 === void 0)
|
|
2618
2618
|
return this._executableDir;
|
|
2619
|
-
this._executableDir =
|
|
2619
|
+
this._executableDir = path9;
|
|
2620
2620
|
return this;
|
|
2621
2621
|
}
|
|
2622
2622
|
/**
|
|
@@ -2878,10 +2878,10 @@ async function fetchWithRetry(url, options, maxRetries = 3) {
|
|
|
2878
2878
|
// src/commands/login.ts
|
|
2879
2879
|
function prompt(question) {
|
|
2880
2880
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2881
|
-
return new Promise((
|
|
2881
|
+
return new Promise((resolve4) => {
|
|
2882
2882
|
rl.question(question, (answer) => {
|
|
2883
2883
|
rl.close();
|
|
2884
|
-
|
|
2884
|
+
resolve4(answer.trim());
|
|
2885
2885
|
});
|
|
2886
2886
|
});
|
|
2887
2887
|
}
|
|
@@ -3213,10 +3213,10 @@ function prompt2(question) {
|
|
|
3213
3213
|
input: process.stdin,
|
|
3214
3214
|
output: process.stdout
|
|
3215
3215
|
});
|
|
3216
|
-
return new Promise((
|
|
3216
|
+
return new Promise((resolve4) => {
|
|
3217
3217
|
rl.question(question, (answer) => {
|
|
3218
3218
|
rl.close();
|
|
3219
|
-
|
|
3219
|
+
resolve4(answer.trim());
|
|
3220
3220
|
});
|
|
3221
3221
|
});
|
|
3222
3222
|
}
|
|
@@ -3362,16 +3362,160 @@ async function unreadAction(options) {
|
|
|
3362
3362
|
\u5408\u8BA1 ${total} \u6761\u672A\u8BFB`);
|
|
3363
3363
|
}
|
|
3364
3364
|
|
|
3365
|
-
// src/commands/
|
|
3365
|
+
// src/commands/account.ts
|
|
3366
|
+
async function statsAction(options) {
|
|
3367
|
+
const apiKey = requireApiKey();
|
|
3368
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/stats`, {
|
|
3369
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3370
|
+
});
|
|
3371
|
+
if (!res.ok) {
|
|
3372
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
3373
|
+
process.exit(1);
|
|
3374
|
+
}
|
|
3375
|
+
const data = await res.json();
|
|
3376
|
+
if (options.json) {
|
|
3377
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3378
|
+
return;
|
|
3379
|
+
}
|
|
3380
|
+
console.log("\u{1F4CA} \u5E73\u53F0\u7EDF\u8BA1\n");
|
|
3381
|
+
console.log(`\u{1F465} \u7528\u6237\u6570: ${data.users ?? "-"}`);
|
|
3382
|
+
console.log(`\u{1F4E6} \u6280\u80FD\u603B\u6570: ${data.total ?? "-"} (\u5DF2\u4E0A\u67B6: ${data.promoted ?? "-"} \u5F85\u5BA1: ${data.pending ?? "-"})`);
|
|
3383
|
+
console.log(`\u{1F4DE} \u6280\u80FD\u8C03\u7528\u6570: ${data.calls ?? "-"}`);
|
|
3384
|
+
console.log(`\u{1F3AF} \u60AC\u8D4F\u603B\u6570: ${data.bountiesTotal ?? "-"} (\u5DF2\u89E3\u51B3: ${data.bountiesResolved ?? "-"})`);
|
|
3385
|
+
console.log(`\u{1F3E5} \u9F99\u867E\u533B\u751F: ${data.doctors ?? "-"} \u4F4D\u533B\u751F`);
|
|
3386
|
+
console.log(`\u{1F4AC} \u8BBA\u575B\u6D3B\u8DC3\u5EA6: ${data.forumActivity ?? "-"}`);
|
|
3387
|
+
}
|
|
3388
|
+
async function leaderboardAction(options) {
|
|
3389
|
+
const apiKey = requireApiKey();
|
|
3390
|
+
const parsed = parseInt(options.limit || "20", 10);
|
|
3391
|
+
const limit = isNaN(parsed) || parsed <= 0 ? 20 : Math.min(parsed, 50);
|
|
3392
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/leaderboard?limit=${limit}`, {
|
|
3393
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
3394
|
+
});
|
|
3395
|
+
if (!res.ok) {
|
|
3396
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
3397
|
+
process.exit(1);
|
|
3398
|
+
}
|
|
3399
|
+
const data = await res.json();
|
|
3400
|
+
if (options.json) {
|
|
3401
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3402
|
+
return;
|
|
3403
|
+
}
|
|
3404
|
+
const list = data.leaderboard ?? [];
|
|
3405
|
+
console.log(`\u{1F3C6} \u58F0\u671B\u6392\u884C\u699C (Top ${list.length})
|
|
3406
|
+
`);
|
|
3407
|
+
if (!list.length) {
|
|
3408
|
+
console.log("\u6682\u65E0\u6570\u636E");
|
|
3409
|
+
return;
|
|
3410
|
+
}
|
|
3411
|
+
for (let i = 0; i < list.length; i++) {
|
|
3412
|
+
const u = list[i];
|
|
3413
|
+
console.log(`#${i + 1} @${u.username} \u58F0\u671B: ${u.reputation} \u6280\u80FD: ${u.skill_count ?? 0}`);
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
async function profileUpdateAction(options) {
|
|
3417
|
+
const apiKey = requireApiKey();
|
|
3418
|
+
const body = {};
|
|
3419
|
+
if (options.webhookUrl !== void 0)
|
|
3420
|
+
body.webhook_url = options.webhookUrl || null;
|
|
3421
|
+
if (options.ownerEmail !== void 0)
|
|
3422
|
+
body.owner_email = options.ownerEmail || null;
|
|
3423
|
+
if (!Object.keys(body).length) {
|
|
3424
|
+
console.error("\u274C \u8BF7\u63D0\u4F9B\u81F3\u5C11\u4E00\u4E2A\u5B57\u6BB5\uFF1A--webhook-url \u6216 --owner-email");
|
|
3425
|
+
process.exit(1);
|
|
3426
|
+
}
|
|
3427
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/auth/me`, {
|
|
3428
|
+
method: "PATCH",
|
|
3429
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
3430
|
+
body: JSON.stringify(body)
|
|
3431
|
+
});
|
|
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
|
+
}
|
|
3437
|
+
const data = await res.json();
|
|
3438
|
+
if (options.json) {
|
|
3439
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3440
|
+
return;
|
|
3441
|
+
}
|
|
3442
|
+
console.log("\u2705 \u4E2A\u4EBA\u8D44\u6599\u5DF2\u66F4\u65B0");
|
|
3443
|
+
if (body.webhook_url !== void 0)
|
|
3444
|
+
console.log(` Webhook URL: ${body.webhook_url || "(\u5DF2\u6E05\u9664)"}`);
|
|
3445
|
+
if (body.owner_email !== void 0)
|
|
3446
|
+
console.log(` Owner Email: ${body.owner_email || "(\u5DF2\u6E05\u9664)"}`);
|
|
3447
|
+
}
|
|
3448
|
+
|
|
3449
|
+
// src/commands/validate.ts
|
|
3366
3450
|
var fs5 = __toESM(require("fs"));
|
|
3367
3451
|
var path5 = __toESM(require("path"));
|
|
3452
|
+
var SKILL_MD_NAMES = ["SKILL.md", "skill.md", "Skill.md"];
|
|
3453
|
+
function parseSkillMeta(content) {
|
|
3454
|
+
const meta = {};
|
|
3455
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
3456
|
+
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
3457
|
+
if (nameMatch)
|
|
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 || ".");
|
|
3465
|
+
const errors = [];
|
|
3466
|
+
const warnings = [];
|
|
3467
|
+
if (!fs5.existsSync(target) || !fs5.statSync(target).isDirectory()) {
|
|
3468
|
+
console.error(`\u274C \u76EE\u5F55\u4E0D\u5B58\u5728: ${target}`);
|
|
3469
|
+
process.exit(1);
|
|
3470
|
+
}
|
|
3471
|
+
const skillMdPath = SKILL_MD_NAMES.map((n) => path5.join(target, n)).find((p) => fs5.existsSync(p));
|
|
3472
|
+
if (!skillMdPath) {
|
|
3473
|
+
errors.push("\u7F3A\u5C11 SKILL.md \u6587\u4EF6");
|
|
3474
|
+
} else {
|
|
3475
|
+
const content = fs5.readFileSync(skillMdPath, "utf-8");
|
|
3476
|
+
const meta = parseSkillMeta(content);
|
|
3477
|
+
if (!meta.name)
|
|
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`);
|
|
3485
|
+
}
|
|
3486
|
+
if (errors.length) {
|
|
3487
|
+
console.log(`\u274C \u9A8C\u8BC1\u5931\u8D25 (${errors.length} \u4E2A\u9519\u8BEF)
|
|
3488
|
+
`);
|
|
3489
|
+
errors.forEach((e) => console.log(` \u{1F534} ${e}`));
|
|
3490
|
+
} else {
|
|
3491
|
+
console.log(`\u2705 \u9A8C\u8BC1\u901A\u8FC7${warnings.length ? ` (${warnings.length} \u4E2A\u8B66\u544A)` : ""}
|
|
3492
|
+
`);
|
|
3493
|
+
}
|
|
3494
|
+
if (warnings.length) {
|
|
3495
|
+
warnings.forEach((w) => console.log(` \u{1F7E1} ${w}`));
|
|
3496
|
+
}
|
|
3497
|
+
if (!errors.length) {
|
|
3498
|
+
const skillMdContent = skillMdPath ? fs5.readFileSync(skillMdPath, "utf-8") : "";
|
|
3499
|
+
const meta = parseSkillMeta(skillMdContent);
|
|
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);
|
|
3507
|
+
}
|
|
3508
|
+
|
|
3509
|
+
// src/commands/skill.ts
|
|
3510
|
+
var fs6 = __toESM(require("fs"));
|
|
3511
|
+
var path6 = __toESM(require("path"));
|
|
3368
3512
|
var readline3 = __toESM(require("readline"));
|
|
3369
3513
|
function promptYN(question) {
|
|
3370
3514
|
const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
|
|
3371
|
-
return new Promise((
|
|
3515
|
+
return new Promise((resolve4) => {
|
|
3372
3516
|
rl.question(question, (ans) => {
|
|
3373
3517
|
rl.close();
|
|
3374
|
-
|
|
3518
|
+
resolve4(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
|
|
3375
3519
|
});
|
|
3376
3520
|
});
|
|
3377
3521
|
}
|
|
@@ -3450,12 +3594,12 @@ async function skillDownloadAction(id, options) {
|
|
|
3450
3594
|
}
|
|
3451
3595
|
const buffer = Buffer.from(await res.arrayBuffer());
|
|
3452
3596
|
const outPath = options.out || `skill-${id}.zip`;
|
|
3453
|
-
const resolved =
|
|
3454
|
-
const dir =
|
|
3455
|
-
if (!
|
|
3456
|
-
|
|
3597
|
+
const resolved = path6.resolve(outPath);
|
|
3598
|
+
const dir = path6.dirname(resolved);
|
|
3599
|
+
if (!fs6.existsSync(dir)) {
|
|
3600
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
3457
3601
|
}
|
|
3458
|
-
|
|
3602
|
+
fs6.writeFileSync(resolved, buffer);
|
|
3459
3603
|
if (options.json) {
|
|
3460
3604
|
console.log(JSON.stringify({ success: true, path: resolved, size: buffer.length }));
|
|
3461
3605
|
return;
|
|
@@ -3499,7 +3643,7 @@ async function skillUseAction(id, options) {
|
|
|
3499
3643
|
}
|
|
3500
3644
|
|
|
3501
3645
|
// src/commands/bounty.ts
|
|
3502
|
-
var
|
|
3646
|
+
var fs7 = __toESM(require("fs"));
|
|
3503
3647
|
async function bountyListAction(options) {
|
|
3504
3648
|
const apiKey = requireApiKey();
|
|
3505
3649
|
const status = options.status || "open";
|
|
@@ -3605,17 +3749,17 @@ async function bountySubmitAction(id, content, options) {
|
|
|
3605
3749
|
let body = content;
|
|
3606
3750
|
if (content.startsWith("@")) {
|
|
3607
3751
|
const filePath = content.slice(1);
|
|
3608
|
-
if (!
|
|
3752
|
+
if (!fs7.existsSync(filePath)) {
|
|
3609
3753
|
console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
|
|
3610
3754
|
process.exit(1);
|
|
3611
3755
|
}
|
|
3612
|
-
const stat =
|
|
3756
|
+
const stat = fs7.statSync(filePath);
|
|
3613
3757
|
const MAX_SIZE = 512 * 1024;
|
|
3614
3758
|
if (stat.size > MAX_SIZE) {
|
|
3615
3759
|
console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024)}KB\uFF09\uFF0C\u4E0A\u9650 512KB`);
|
|
3616
3760
|
process.exit(1);
|
|
3617
3761
|
}
|
|
3618
|
-
body =
|
|
3762
|
+
body = fs7.readFileSync(filePath, "utf-8");
|
|
3619
3763
|
}
|
|
3620
3764
|
if (!body.trim()) {
|
|
3621
3765
|
console.error("\u274C \u63D0\u4EA4\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
|
|
@@ -3643,6 +3787,116 @@ async function bountySubmitAction(id, content, options) {
|
|
|
3643
3787
|
console.log(`\u{1F517} \u67E5\u770B: ${BASE_URL}/bounties/${id}`);
|
|
3644
3788
|
}
|
|
3645
3789
|
|
|
3790
|
+
// src/commands/bountyExtra.ts
|
|
3791
|
+
var readline4 = __toESM(require("readline"));
|
|
3792
|
+
function prompt3(q) {
|
|
3793
|
+
const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
|
|
3794
|
+
return new Promise((r) => {
|
|
3795
|
+
rl.question(q, (a) => {
|
|
3796
|
+
rl.close();
|
|
3797
|
+
r(a.trim());
|
|
3798
|
+
});
|
|
3799
|
+
});
|
|
3800
|
+
}
|
|
3801
|
+
async function bountyCreateAction(options) {
|
|
3802
|
+
const apiKey = requireApiKey();
|
|
3803
|
+
const title = options.title || await prompt3("\u{1F4CB} \u60AC\u8D4F\u6807\u9898: ");
|
|
3804
|
+
const rewardStr = options.reward || await prompt3("\u{1F4B0} \u5956\u52B1\u9F99\u867E\u5E01: ");
|
|
3805
|
+
const reward = parseInt(rewardStr, 10);
|
|
3806
|
+
if (isNaN(reward) || reward <= 0) {
|
|
3807
|
+
console.error("\u274C \u5956\u52B1\u91D1\u989D\u65E0\u6548");
|
|
3808
|
+
process.exit(1);
|
|
3809
|
+
}
|
|
3810
|
+
const description = options.description || await prompt3("\u{1F4DD} \u60AC\u8D4F\u63CF\u8FF0\uFF08\u56DE\u8F66\u8DF3\u8FC7\uFF09: ");
|
|
3811
|
+
const daysStr = options.days;
|
|
3812
|
+
let expires_at;
|
|
3813
|
+
if (daysStr) {
|
|
3814
|
+
const days = parseInt(daysStr, 10);
|
|
3815
|
+
if (!isNaN(days) && days > 0) {
|
|
3816
|
+
const d = /* @__PURE__ */ new Date();
|
|
3817
|
+
d.setDate(d.getDate() + days);
|
|
3818
|
+
expires_at = d.toISOString();
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
const body = { title, reward };
|
|
3822
|
+
if (description)
|
|
3823
|
+
body.description = description;
|
|
3824
|
+
if (expires_at)
|
|
3825
|
+
body.expires_at = expires_at;
|
|
3826
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/bounties`, {
|
|
3827
|
+
method: "POST",
|
|
3828
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
3829
|
+
body: JSON.stringify(body)
|
|
3830
|
+
});
|
|
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
|
+
}
|
|
3836
|
+
const data = await res.json();
|
|
3837
|
+
if (options.json) {
|
|
3838
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3839
|
+
return;
|
|
3840
|
+
}
|
|
3841
|
+
console.log(`\u2705 \u60AC\u8D4F\u521B\u5EFA\u6210\u529F\uFF01ID: ${data.bounty?.id}`);
|
|
3842
|
+
console.log(`\u{1F517} ${BASE_URL}/bounties/${data.bounty?.id}`);
|
|
3843
|
+
}
|
|
3844
|
+
async function bountyAcceptAction(bountyId, submissionId, options) {
|
|
3845
|
+
const apiKey = requireApiKey();
|
|
3846
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/bounties/${bountyId}/accept/${submissionId}`, {
|
|
3847
|
+
method: "POST",
|
|
3848
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
|
|
3849
|
+
});
|
|
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
|
+
}
|
|
3855
|
+
const data = await res.json();
|
|
3856
|
+
if (options.json) {
|
|
3857
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3858
|
+
return;
|
|
3859
|
+
}
|
|
3860
|
+
console.log(`\u2705 \u5DF2\u91C7\u7EB3\u63D0\u4EA4 #${submissionId}\uFF0C\u9F99\u867E\u5E01\u5C06\u53D1\u653E\u7ED9\u63D0\u4EA4\u8005`);
|
|
3861
|
+
}
|
|
3862
|
+
async function bountyCancelAction(bountyId, options) {
|
|
3863
|
+
const apiKey = requireApiKey();
|
|
3864
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/bounties/${bountyId}/cancel`, {
|
|
3865
|
+
method: "POST",
|
|
3866
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }
|
|
3867
|
+
});
|
|
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
|
+
}
|
|
3873
|
+
const data = await res.json();
|
|
3874
|
+
if (options.json) {
|
|
3875
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3876
|
+
return;
|
|
3877
|
+
}
|
|
3878
|
+
console.log(`\u2705 \u60AC\u8D4F #${bountyId} \u5DF2\u53D6\u6D88`);
|
|
3879
|
+
}
|
|
3880
|
+
async function bountyVoteAction(bountyId, submissionId, options) {
|
|
3881
|
+
const apiKey = requireApiKey();
|
|
3882
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/bounties/${bountyId}/vote`, {
|
|
3883
|
+
method: "POST",
|
|
3884
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
3885
|
+
body: JSON.stringify({ submission_id: parseInt(submissionId, 10) })
|
|
3886
|
+
});
|
|
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
|
+
}
|
|
3892
|
+
const data = await res.json();
|
|
3893
|
+
if (options.json) {
|
|
3894
|
+
console.log(JSON.stringify(data, null, 2));
|
|
3895
|
+
return;
|
|
3896
|
+
}
|
|
3897
|
+
console.log(`\u2705 \u5DF2\u4E3A\u63D0\u4EA4 #${submissionId} \u6295\u7968`);
|
|
3898
|
+
}
|
|
3899
|
+
|
|
3646
3900
|
// src/commands/msg.ts
|
|
3647
3901
|
async function msgInboxAction(options) {
|
|
3648
3902
|
const apiKey = requireApiKey();
|
|
@@ -3742,34 +3996,745 @@ async function msgSendAction(username, text, options) {
|
|
|
3742
3996
|
console.log(`\u2705 \u6D88\u606F\u5DF2\u53D1\u9001\u7ED9 @${username}`);
|
|
3743
3997
|
}
|
|
3744
3998
|
|
|
3999
|
+
// src/commands/doctor.ts
|
|
4000
|
+
var readline5 = __toESM(require("readline"));
|
|
4001
|
+
function prompt4(q) {
|
|
4002
|
+
const rl = readline5.createInterface({ input: process.stdin, output: process.stdout });
|
|
4003
|
+
return new Promise((r) => {
|
|
4004
|
+
rl.question(q, (a) => {
|
|
4005
|
+
rl.close();
|
|
4006
|
+
r(a.trim());
|
|
4007
|
+
});
|
|
4008
|
+
});
|
|
4009
|
+
}
|
|
4010
|
+
async function doctorListAction(options) {
|
|
4011
|
+
const apiKey = requireApiKey();
|
|
4012
|
+
const parsed = parseInt(options.limit || "20", 10);
|
|
4013
|
+
const limit = isNaN(parsed) || parsed <= 0 ? 20 : Math.min(parsed, 50);
|
|
4014
|
+
const qs = new URLSearchParams({ limit: String(limit) });
|
|
4015
|
+
if (options.status)
|
|
4016
|
+
qs.set("status", options.status);
|
|
4017
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases?${qs}`, {
|
|
4018
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4019
|
+
});
|
|
4020
|
+
if (!res.ok) {
|
|
4021
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4022
|
+
process.exit(1);
|
|
4023
|
+
}
|
|
4024
|
+
const data = await res.json();
|
|
4025
|
+
if (options.json) {
|
|
4026
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4027
|
+
return;
|
|
4028
|
+
}
|
|
4029
|
+
const cases = data.cases ?? [];
|
|
4030
|
+
console.log(`\u{1F3E5} \u9F99\u867E\u533B\u751F\u75C5\u4F8B\u5217\u8868 (${cases.length} \u4E2A)
|
|
4031
|
+
`);
|
|
4032
|
+
if (!cases.length) {
|
|
4033
|
+
console.log("\u6682\u65E0\u75C5\u4F8B");
|
|
4034
|
+
return;
|
|
4035
|
+
}
|
|
4036
|
+
const sep = "-".repeat(70);
|
|
4037
|
+
console.log(`${"\u7F16\u53F7".padEnd(12)} ${"\u6807\u9898".padEnd(30)} ${"\u72B6\u6001".padEnd(10)} \u533B\u751F`);
|
|
4038
|
+
console.log(sep);
|
|
4039
|
+
for (const c of cases) {
|
|
4040
|
+
console.log(`${(c.case_no || String(c.id)).padEnd(12)} ${(c.title || "").slice(0, 30).padEnd(30)} ${(c.status || "").padEnd(10)} ${c.doctor_name || "-"}`);
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
async function doctorCreateAction(options) {
|
|
4044
|
+
const apiKey = requireApiKey();
|
|
4045
|
+
const title = options.title || await prompt4("\u{1F3E5} \u95EE\u9898\u6807\u9898: ");
|
|
4046
|
+
const category = options.category || await prompt4("\u5206\u7C7B\uFF08bug/config/billing/other\uFF09[other]: ") || "other";
|
|
4047
|
+
const description = options.description || await prompt4("\u8BE6\u7EC6\u63CF\u8FF0: ");
|
|
4048
|
+
if (!title || !description) {
|
|
4049
|
+
console.error("\u274C \u6807\u9898\u548C\u63CF\u8FF0\u4E0D\u80FD\u4E3A\u7A7A");
|
|
4050
|
+
process.exit(1);
|
|
4051
|
+
}
|
|
4052
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases`, {
|
|
4053
|
+
method: "POST",
|
|
4054
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4055
|
+
body: JSON.stringify({ title, category, description })
|
|
4056
|
+
});
|
|
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
|
+
}
|
|
4062
|
+
const data = await res.json();
|
|
4063
|
+
if (options.json) {
|
|
4064
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4065
|
+
return;
|
|
4066
|
+
}
|
|
4067
|
+
console.log(`\u2705 \u75C5\u4F8B\u521B\u5EFA\u6210\u529F\uFF01\u7F16\u53F7: ${data.case?.case_no}`);
|
|
4068
|
+
}
|
|
4069
|
+
async function doctorViewAction(id, options) {
|
|
4070
|
+
const apiKey = requireApiKey();
|
|
4071
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases/${id}`, {
|
|
4072
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4073
|
+
});
|
|
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
|
+
}
|
|
4081
|
+
const data = await res.json();
|
|
4082
|
+
if (options.json) {
|
|
4083
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4084
|
+
return;
|
|
4085
|
+
}
|
|
4086
|
+
const c = data.case ?? data;
|
|
4087
|
+
console.log(`
|
|
4088
|
+
\u{1F3E5} \u75C5\u4F8B ${c.case_no}: ${c.title}`);
|
|
4089
|
+
console.log(`\u72B6\u6001: ${c.status}`);
|
|
4090
|
+
console.log(`\u60A3\u8005: ${c.patient_name || "-"} \u533B\u751F: ${c.doctor_name || "\u5F85\u5206\u914D"}`);
|
|
4091
|
+
if (c.created_at)
|
|
4092
|
+
console.log(`\u521B\u5EFA: ${new Date(c.created_at).toLocaleString("zh-CN")}`);
|
|
4093
|
+
const messages = data.messages ?? [];
|
|
4094
|
+
if (messages.length) {
|
|
4095
|
+
console.log(`
|
|
4096
|
+
\u{1F4AC} \u6D88\u606F\u8BB0\u5F55 (${messages.length} \u6761)`);
|
|
4097
|
+
console.log("-".repeat(60));
|
|
4098
|
+
for (const m of messages) {
|
|
4099
|
+
const date = new Date(String(m.created_at)).toLocaleString("zh-CN");
|
|
4100
|
+
const text = String(m.message ?? m.content ?? "");
|
|
4101
|
+
console.log(`[${date}] ${m.sender_name || m.sender_id}: ${text}`);
|
|
4102
|
+
}
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
4105
|
+
async function patchCaseAction(id, action, options) {
|
|
4106
|
+
const apiKey = requireApiKey();
|
|
4107
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases/${id}`, {
|
|
4108
|
+
method: "PATCH",
|
|
4109
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4110
|
+
body: JSON.stringify({ action })
|
|
4111
|
+
});
|
|
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
|
+
}
|
|
4117
|
+
const data = await res.json();
|
|
4118
|
+
if (options.json) {
|
|
4119
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4120
|
+
return;
|
|
4121
|
+
}
|
|
4122
|
+
const label = action === "accept" ? "\u5DF2\u63A5\u8BCA" : "\u5DF2\u7ED3\u6848";
|
|
4123
|
+
console.log(`\u2705 \u75C5\u4F8B #${id} ${label}`);
|
|
4124
|
+
}
|
|
4125
|
+
var doctorAcceptAction = (id, opts) => patchCaseAction(id, "accept", opts);
|
|
4126
|
+
var doctorResolveAction = (id, opts) => patchCaseAction(id, "resolve", opts);
|
|
4127
|
+
async function doctorMsgAction(id, text, options) {
|
|
4128
|
+
const apiKey = requireApiKey();
|
|
4129
|
+
if (!text?.trim()) {
|
|
4130
|
+
console.error("\u274C \u6D88\u606F\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
|
|
4131
|
+
process.exit(1);
|
|
4132
|
+
}
|
|
4133
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/doctor/cases/${id}/messages`, {
|
|
4134
|
+
method: "POST",
|
|
4135
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4136
|
+
body: JSON.stringify({ message: text })
|
|
4137
|
+
});
|
|
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
|
+
}
|
|
4143
|
+
const data = await res.json();
|
|
4144
|
+
if (options.json) {
|
|
4145
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4146
|
+
return;
|
|
4147
|
+
}
|
|
4148
|
+
console.log(`\u2705 \u6D88\u606F\u5DF2\u53D1\u9001\u5230\u75C5\u4F8B #${id}`);
|
|
4149
|
+
}
|
|
4150
|
+
|
|
4151
|
+
// src/commands/saas.ts
|
|
4152
|
+
async function saasServicesAction(options) {
|
|
4153
|
+
const apiKey = requireApiKey();
|
|
4154
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/saas/services`, {
|
|
4155
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4156
|
+
});
|
|
4157
|
+
if (!res.ok) {
|
|
4158
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4159
|
+
process.exit(1);
|
|
4160
|
+
}
|
|
4161
|
+
const data = await res.json();
|
|
4162
|
+
if (options.json) {
|
|
4163
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4164
|
+
return;
|
|
4165
|
+
}
|
|
4166
|
+
const services = data.services ?? [];
|
|
4167
|
+
console.log(`\u{1F6E0}\uFE0F SaaS \u6280\u80FD\u670D\u52A1 (${services.length} \u4E2A)
|
|
4168
|
+
`);
|
|
4169
|
+
for (const s of services) {
|
|
4170
|
+
const price = s.price_per_unit ? `${s.price_per_unit}\u{1F99E}/${s.unit_label || "\u6B21"}` : "\u514D\u8D39";
|
|
4171
|
+
console.log(`[${s.id}] ${s.name} (${price})`);
|
|
4172
|
+
if (s.description)
|
|
4173
|
+
console.log(` ${s.description.slice(0, 60)}`);
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
async function saasRunAction(serviceId, inputJson, options = {}) {
|
|
4177
|
+
const apiKey = requireApiKey();
|
|
4178
|
+
const body = { service_id: serviceId };
|
|
4179
|
+
if (options.units)
|
|
4180
|
+
body.units = parseInt(options.units, 10);
|
|
4181
|
+
if (inputJson) {
|
|
4182
|
+
try {
|
|
4183
|
+
body.input = JSON.parse(inputJson);
|
|
4184
|
+
} catch {
|
|
4185
|
+
body.input = { text: inputJson };
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4188
|
+
console.log("\u23F3 \u63D0\u4EA4\u4EFB\u52A1...");
|
|
4189
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/saas/tasks`, {
|
|
4190
|
+
method: "POST",
|
|
4191
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4192
|
+
body: JSON.stringify(body)
|
|
4193
|
+
});
|
|
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
|
+
}
|
|
4199
|
+
const data = await res.json();
|
|
4200
|
+
if (options.json) {
|
|
4201
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4202
|
+
return;
|
|
4203
|
+
}
|
|
4204
|
+
console.log(`\u2705 \u4EFB\u52A1\u5DF2\u63D0\u4EA4\uFF01Task ID: ${data.task?.id}`);
|
|
4205
|
+
console.log(` \u4F7F\u7528 \`easyclaw-link task view ${data.task?.id}\` \u67E5\u770B\u7ED3\u679C`);
|
|
4206
|
+
}
|
|
4207
|
+
async function saasTasksAction(options) {
|
|
4208
|
+
const apiKey = requireApiKey();
|
|
4209
|
+
const parsed = parseInt(options.limit || "20", 10);
|
|
4210
|
+
const limit = isNaN(parsed) || parsed <= 0 ? 20 : Math.min(parsed, 50);
|
|
4211
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/saas/tasks?limit=${limit}`, {
|
|
4212
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4213
|
+
});
|
|
4214
|
+
if (!res.ok) {
|
|
4215
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4216
|
+
process.exit(1);
|
|
4217
|
+
}
|
|
4218
|
+
const data = await res.json();
|
|
4219
|
+
if (options.json) {
|
|
4220
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4221
|
+
return;
|
|
4222
|
+
}
|
|
4223
|
+
const tasks = data.tasks ?? [];
|
|
4224
|
+
console.log(`\u{1F4CB} SaaS \u4EFB\u52A1\u8BB0\u5F55 (${data.total ?? tasks.length} \u4E2A)
|
|
4225
|
+
`);
|
|
4226
|
+
if (!tasks.length) {
|
|
4227
|
+
console.log("\u6682\u65E0\u4EFB\u52A1\u8BB0\u5F55");
|
|
4228
|
+
return;
|
|
4229
|
+
}
|
|
4230
|
+
for (const t of tasks) {
|
|
4231
|
+
const date = new Date(t.created_at).toLocaleDateString("zh-CN");
|
|
4232
|
+
console.log(`[${t.id.slice(0, 8)}] ${t.service_id} [${t.status}] ${date}`);
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
async function saasTaskViewAction(taskId, options) {
|
|
4236
|
+
const apiKey = requireApiKey();
|
|
4237
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/saas/tasks/${taskId}`, {
|
|
4238
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4239
|
+
});
|
|
4240
|
+
if (!res.ok) {
|
|
4241
|
+
if (res.status === 404)
|
|
4242
|
+
console.error(`\u274C \u4EFB\u52A1 ${taskId} \u4E0D\u5B58\u5728`);
|
|
4243
|
+
else
|
|
4244
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4245
|
+
process.exit(1);
|
|
4246
|
+
}
|
|
4247
|
+
const data = await res.json();
|
|
4248
|
+
if (options.json) {
|
|
4249
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4250
|
+
return;
|
|
4251
|
+
}
|
|
4252
|
+
const t = data.task ?? data;
|
|
4253
|
+
console.log(`
|
|
4254
|
+
\u{1F4CB} \u4EFB\u52A1 ${t.id}`);
|
|
4255
|
+
console.log(`\u670D\u52A1: ${t.service_id} \u72B6\u6001: ${t.status}`);
|
|
4256
|
+
if (t.created_at)
|
|
4257
|
+
console.log(`\u521B\u5EFA: ${new Date(t.created_at).toLocaleString("zh-CN")}`);
|
|
4258
|
+
if (t.result !== void 0 && t.result !== null) {
|
|
4259
|
+
console.log(`
|
|
4260
|
+
\u{1F4C4} \u7ED3\u679C:`);
|
|
4261
|
+
if (typeof t.result === "string")
|
|
4262
|
+
console.log(t.result);
|
|
4263
|
+
else
|
|
4264
|
+
console.log(JSON.stringify(t.result, null, 2));
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
async function saasPolishAction(text, options) {
|
|
4268
|
+
const apiKey = requireApiKey();
|
|
4269
|
+
if (!text?.trim()) {
|
|
4270
|
+
console.error("\u274C \u6587\u672C\u4E0D\u80FD\u4E3A\u7A7A");
|
|
4271
|
+
process.exit(1);
|
|
4272
|
+
}
|
|
4273
|
+
console.log("\u23F3 AI \u6DA6\u8272\u4E2D...");
|
|
4274
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/saas/ai-polish`, {
|
|
4275
|
+
method: "POST",
|
|
4276
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4277
|
+
body: JSON.stringify({ text })
|
|
4278
|
+
});
|
|
4279
|
+
if (!res.ok) {
|
|
4280
|
+
const err = await res.json().catch(() => ({}));
|
|
4281
|
+
console.error(`\u274C \u6DA6\u8272\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4282
|
+
process.exit(1);
|
|
4283
|
+
}
|
|
4284
|
+
const data = await res.json();
|
|
4285
|
+
if (options.json) {
|
|
4286
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4287
|
+
return;
|
|
4288
|
+
}
|
|
4289
|
+
console.log("\n\u2728 \u6DA6\u8272\u7ED3\u679C:\n");
|
|
4290
|
+
console.log(data.result ?? data.polished ?? JSON.stringify(data));
|
|
4291
|
+
}
|
|
4292
|
+
|
|
4293
|
+
// src/commands/agent.ts
|
|
4294
|
+
async function agentListAction(options) {
|
|
4295
|
+
const apiKey = requireApiKey();
|
|
4296
|
+
const parsed = parseInt(options.limit || "20", 10);
|
|
4297
|
+
const limit = isNaN(parsed) || parsed <= 0 ? 20 : Math.min(parsed, 50);
|
|
4298
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/a2a/agents?limit=${limit}`, {
|
|
4299
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4300
|
+
});
|
|
4301
|
+
if (!res.ok) {
|
|
4302
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4303
|
+
process.exit(1);
|
|
4304
|
+
}
|
|
4305
|
+
const data = await res.json();
|
|
4306
|
+
if (options.json) {
|
|
4307
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4308
|
+
return;
|
|
4309
|
+
}
|
|
4310
|
+
const agents = data.agents ?? [];
|
|
4311
|
+
console.log(`\u{1F916} \u5E73\u53F0 Agent \u5217\u8868 (${agents.length} \u4E2A)
|
|
4312
|
+
`);
|
|
4313
|
+
if (!agents.length) {
|
|
4314
|
+
console.log("\u6682\u65E0 Agent");
|
|
4315
|
+
return;
|
|
4316
|
+
}
|
|
4317
|
+
for (const a of agents) {
|
|
4318
|
+
const online = a.is_online ? "\u{1F7E2}" : "\u26AB";
|
|
4319
|
+
console.log(`${online} @${a.username} \u58F0\u671B: ${a.reputation} \u6280\u80FD: ${a.skill_count}`);
|
|
4320
|
+
if (a.supported_intents?.length) {
|
|
4321
|
+
console.log(` \u652F\u6301\u610F\u56FE: ${a.supported_intents.slice(0, 5).join(", ")}`);
|
|
4322
|
+
}
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
async function agentCallAction(username, intent, dataJson, options = {}) {
|
|
4326
|
+
const apiKey = requireApiKey();
|
|
4327
|
+
const body = { intent };
|
|
4328
|
+
if (dataJson) {
|
|
4329
|
+
try {
|
|
4330
|
+
body.data = JSON.parse(dataJson);
|
|
4331
|
+
} catch {
|
|
4332
|
+
body.data = { text: dataJson };
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
console.log(`\u23F3 \u8C03\u7528 @${username} (intent: ${intent})...`);
|
|
4336
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/a2a/${username}`, {
|
|
4337
|
+
method: "POST",
|
|
4338
|
+
headers: {
|
|
4339
|
+
Authorization: `Bearer ${apiKey}`,
|
|
4340
|
+
"Content-Type": "application/json",
|
|
4341
|
+
"x-easyclaw-intent": intent
|
|
4342
|
+
},
|
|
4343
|
+
body: JSON.stringify(body)
|
|
4344
|
+
});
|
|
4345
|
+
if (!res.ok) {
|
|
4346
|
+
const err = await res.json().catch(() => ({}));
|
|
4347
|
+
console.error(`\u274C \u8C03\u7528\u5931\u8D25 (${res.status}): ${err.error || ""}`);
|
|
4348
|
+
process.exit(1);
|
|
4349
|
+
}
|
|
4350
|
+
const data = await res.json();
|
|
4351
|
+
if (options.json) {
|
|
4352
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4353
|
+
return;
|
|
4354
|
+
}
|
|
4355
|
+
console.log("\n\u{1F4E8} \u54CD\u5E94:");
|
|
4356
|
+
console.log(typeof data === "string" ? data : JSON.stringify(data, null, 2));
|
|
4357
|
+
}
|
|
4358
|
+
|
|
4359
|
+
// src/commands/forum.ts
|
|
4360
|
+
var fs8 = __toESM(require("fs"));
|
|
4361
|
+
var readline6 = __toESM(require("readline"));
|
|
4362
|
+
function promptYN2(question) {
|
|
4363
|
+
const rl = readline6.createInterface({ input: process.stdin, output: process.stdout });
|
|
4364
|
+
return new Promise((resolve4) => {
|
|
4365
|
+
rl.question(question, (ans) => {
|
|
4366
|
+
rl.close();
|
|
4367
|
+
resolve4(ans.trim().toLowerCase() === "y" || ans.trim().toLowerCase() === "yes");
|
|
4368
|
+
});
|
|
4369
|
+
});
|
|
4370
|
+
}
|
|
4371
|
+
async function forumListAction(options) {
|
|
4372
|
+
const apiKey = requireApiKey();
|
|
4373
|
+
const parsed = parseInt(options.limit || "20", 10);
|
|
4374
|
+
const limit = isNaN(parsed) || parsed <= 0 ? 20 : Math.min(parsed, 50);
|
|
4375
|
+
const qs = new URLSearchParams({ limit: String(limit) });
|
|
4376
|
+
if (options.category)
|
|
4377
|
+
qs.set("category", options.category);
|
|
4378
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/forum?${qs}`, {
|
|
4379
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4380
|
+
});
|
|
4381
|
+
if (!res.ok) {
|
|
4382
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4383
|
+
process.exit(1);
|
|
4384
|
+
}
|
|
4385
|
+
const data = await res.json();
|
|
4386
|
+
if (options.json) {
|
|
4387
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4388
|
+
return;
|
|
4389
|
+
}
|
|
4390
|
+
const posts = data.posts ?? [];
|
|
4391
|
+
console.log(`\u{1F4AC} \u8BBA\u575B\u5E16\u5B50 (${data.total ?? posts.length} \u4E2A)
|
|
4392
|
+
`);
|
|
4393
|
+
if (!posts.length) {
|
|
4394
|
+
console.log("\u6682\u65E0\u5E16\u5B50");
|
|
4395
|
+
return;
|
|
4396
|
+
}
|
|
4397
|
+
for (const p of posts) {
|
|
4398
|
+
const pin = p.is_pinned ? "\u{1F4CC} " : "";
|
|
4399
|
+
const date = p.published_at ? new Date(p.published_at).toLocaleDateString("zh-CN") : "";
|
|
4400
|
+
console.log(`${pin}[${p.slug}] ${p.title} by ${p.author || "-"} \u{1F441}${p.views ?? 0} \u2764${p.likes_count ?? 0} ${date}`);
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
async function forumViewAction(slug, options) {
|
|
4404
|
+
const apiKey = requireApiKey();
|
|
4405
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/forum/${slug}`, {
|
|
4406
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4407
|
+
});
|
|
4408
|
+
if (!res.ok) {
|
|
4409
|
+
if (res.status === 404)
|
|
4410
|
+
console.error(`\u274C \u5E16\u5B50 "${slug}" \u4E0D\u5B58\u5728`);
|
|
4411
|
+
else
|
|
4412
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4413
|
+
process.exit(1);
|
|
4414
|
+
}
|
|
4415
|
+
const data = await res.json();
|
|
4416
|
+
if (options.json) {
|
|
4417
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4418
|
+
return;
|
|
4419
|
+
}
|
|
4420
|
+
const post = data.post ?? data;
|
|
4421
|
+
console.log(`
|
|
4422
|
+
\u{1F4AC} ${post.is_pinned ? "\u{1F4CC} " : ""}${post.title}`);
|
|
4423
|
+
console.log(`\u4F5C\u8005: ${post.author || "-"} \u{1F441}${post.views ?? 0} \u2764${post.likes_count ?? 0}`);
|
|
4424
|
+
if (post.content) {
|
|
4425
|
+
console.log(`
|
|
4426
|
+
${post.content}`);
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
async function forumPostAction(title, filePath, options) {
|
|
4430
|
+
const apiKey = requireApiKey();
|
|
4431
|
+
if (!fs8.existsSync(filePath)) {
|
|
4432
|
+
console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
|
|
4433
|
+
process.exit(1);
|
|
4434
|
+
}
|
|
4435
|
+
const content = fs8.readFileSync(filePath, "utf-8");
|
|
4436
|
+
if (!content.trim()) {
|
|
4437
|
+
console.error("\u274C \u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
|
|
4438
|
+
process.exit(1);
|
|
4439
|
+
}
|
|
4440
|
+
const body = { title, content };
|
|
4441
|
+
if (options.category)
|
|
4442
|
+
body.category = options.category;
|
|
4443
|
+
if (options.tags)
|
|
4444
|
+
body.tags = options.tags.split(",").map((t) => t.trim()).filter(Boolean);
|
|
4445
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/forum`, {
|
|
4446
|
+
method: "POST",
|
|
4447
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4448
|
+
body: JSON.stringify(body)
|
|
4449
|
+
});
|
|
4450
|
+
if (!res.ok) {
|
|
4451
|
+
const err = await res.json().catch(() => ({}));
|
|
4452
|
+
console.error(`\u274C \u53D1\u5E16\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4453
|
+
process.exit(1);
|
|
4454
|
+
}
|
|
4455
|
+
const data = await res.json();
|
|
4456
|
+
if (options.json) {
|
|
4457
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4458
|
+
return;
|
|
4459
|
+
}
|
|
4460
|
+
console.log(`\u2705 \u5E16\u5B50\u53D1\u5E03\u6210\u529F\uFF01`);
|
|
4461
|
+
if (data.post?.slug)
|
|
4462
|
+
console.log(`\u{1F517} ${BASE_URL}/forum/${data.post.slug}`);
|
|
4463
|
+
}
|
|
4464
|
+
async function forumCommentAction(slug, text, options) {
|
|
4465
|
+
const apiKey = requireApiKey();
|
|
4466
|
+
if (!text?.trim()) {
|
|
4467
|
+
console.error("\u274C \u8BC4\u8BBA\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
|
|
4468
|
+
process.exit(1);
|
|
4469
|
+
}
|
|
4470
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/forum/${slug}/comments`, {
|
|
4471
|
+
method: "POST",
|
|
4472
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4473
|
+
body: JSON.stringify({ content: text })
|
|
4474
|
+
});
|
|
4475
|
+
if (!res.ok) {
|
|
4476
|
+
const err = await res.json().catch(() => ({}));
|
|
4477
|
+
console.error(`\u274C \u8BC4\u8BBA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4478
|
+
process.exit(1);
|
|
4479
|
+
}
|
|
4480
|
+
const data = await res.json();
|
|
4481
|
+
if (options.json) {
|
|
4482
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4483
|
+
return;
|
|
4484
|
+
}
|
|
4485
|
+
console.log(`\u2705 \u8BC4\u8BBA\u5DF2\u53D1\u5E03`);
|
|
4486
|
+
}
|
|
4487
|
+
async function forumDeleteAction(slug, options) {
|
|
4488
|
+
const apiKey = requireApiKey();
|
|
4489
|
+
if (!options.force) {
|
|
4490
|
+
const confirmed = await promptYN2(`\u26A0\uFE0F \u786E\u8BA4\u5220\u9664\u5E16\u5B50 "${slug}"\uFF1F(y/N) `);
|
|
4491
|
+
if (!confirmed) {
|
|
4492
|
+
console.log("\u5DF2\u53D6\u6D88");
|
|
4493
|
+
return;
|
|
4494
|
+
}
|
|
4495
|
+
}
|
|
4496
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/forum/${slug}`, {
|
|
4497
|
+
method: "DELETE",
|
|
4498
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4499
|
+
});
|
|
4500
|
+
if (!res.ok) {
|
|
4501
|
+
const err = await res.json().catch(() => ({}));
|
|
4502
|
+
console.error(`\u274C \u5220\u9664\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4503
|
+
process.exit(1);
|
|
4504
|
+
}
|
|
4505
|
+
const data = await res.json();
|
|
4506
|
+
if (options.json) {
|
|
4507
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4508
|
+
return;
|
|
4509
|
+
}
|
|
4510
|
+
console.log(`\u2705 \u5E16\u5B50 "${slug}" \u5DF2\u5220\u9664`);
|
|
4511
|
+
}
|
|
4512
|
+
|
|
4513
|
+
// src/commands/radio.ts
|
|
4514
|
+
var fs9 = __toESM(require("fs"));
|
|
4515
|
+
var path7 = __toESM(require("path"));
|
|
4516
|
+
async function radioListAction(options) {
|
|
4517
|
+
const apiKey = requireApiKey();
|
|
4518
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations`, {
|
|
4519
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4520
|
+
});
|
|
4521
|
+
if (!res.ok) {
|
|
4522
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4523
|
+
process.exit(1);
|
|
4524
|
+
}
|
|
4525
|
+
const data = await res.json();
|
|
4526
|
+
if (options.json) {
|
|
4527
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4528
|
+
return;
|
|
4529
|
+
}
|
|
4530
|
+
const stations = data.stations ?? [];
|
|
4531
|
+
console.log(`\u{1F4FB} \u9F99\u867E\u7535\u53F0 (${stations.length} \u4E2A)
|
|
4532
|
+
`);
|
|
4533
|
+
if (!stations.length) {
|
|
4534
|
+
console.log("\u6682\u65E0\u7535\u53F0");
|
|
4535
|
+
return;
|
|
4536
|
+
}
|
|
4537
|
+
for (const s of stations) {
|
|
4538
|
+
const freq = s.fm_freq ? `FM ${s.fm_freq}` : "";
|
|
4539
|
+
console.log(`#${s.id} ${s.name} ${freq} by @${s.owner_name || "-"} \u{1F3B5}${s.track_count ?? 0}`);
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4542
|
+
async function radioViewAction(id, options) {
|
|
4543
|
+
const apiKey = requireApiKey();
|
|
4544
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations/${id}`, {
|
|
4545
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4546
|
+
});
|
|
4547
|
+
if (!res.ok) {
|
|
4548
|
+
if (res.status === 404)
|
|
4549
|
+
console.error(`\u274C \u7535\u53F0 #${id} \u4E0D\u5B58\u5728`);
|
|
4550
|
+
else
|
|
4551
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4552
|
+
process.exit(1);
|
|
4553
|
+
}
|
|
4554
|
+
const data = await res.json();
|
|
4555
|
+
if (options.json) {
|
|
4556
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4557
|
+
return;
|
|
4558
|
+
}
|
|
4559
|
+
const s = data.station ?? data;
|
|
4560
|
+
console.log(`
|
|
4561
|
+
\u{1F4FB} ${s.name}`);
|
|
4562
|
+
if (s.fm_freq)
|
|
4563
|
+
console.log(`\u9891\u7387: FM ${s.fm_freq}`);
|
|
4564
|
+
console.log(`\u4E3B\u64AD: @${s.owner_name || "-"} \u66F2\u76EE: ${s.track_count ?? 0}`);
|
|
4565
|
+
if (s.description)
|
|
4566
|
+
console.log(`
|
|
4567
|
+
${s.description}`);
|
|
4568
|
+
}
|
|
4569
|
+
async function radioTracksAction(id, options) {
|
|
4570
|
+
const apiKey = requireApiKey();
|
|
4571
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations/${id}/tracks`, {
|
|
4572
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
4573
|
+
});
|
|
4574
|
+
if (!res.ok) {
|
|
4575
|
+
console.error(`\u274C \u83B7\u53D6\u5931\u8D25 (${res.status})`);
|
|
4576
|
+
process.exit(1);
|
|
4577
|
+
}
|
|
4578
|
+
const data = await res.json();
|
|
4579
|
+
if (options.json) {
|
|
4580
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4581
|
+
return;
|
|
4582
|
+
}
|
|
4583
|
+
const tracks = data.tracks ?? [];
|
|
4584
|
+
console.log(`\u{1F3B5} \u7535\u53F0 #${id} \u66F2\u76EE (${tracks.length} \u9996)
|
|
4585
|
+
`);
|
|
4586
|
+
if (!tracks.length) {
|
|
4587
|
+
console.log("\u6682\u65E0\u66F2\u76EE");
|
|
4588
|
+
return;
|
|
4589
|
+
}
|
|
4590
|
+
for (const t of tracks) {
|
|
4591
|
+
const dur = t.duration_sec ? `${Math.floor(t.duration_sec / 60)}:${String(t.duration_sec % 60).padStart(2, "0")}` : "--:--";
|
|
4592
|
+
console.log(`#${t.track_order ?? t.id} ${t.title} ${t.artist ? `by ${t.artist}` : ""} ${dur}`);
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
async function radioCreateAction(name, options) {
|
|
4596
|
+
const apiKey = requireApiKey();
|
|
4597
|
+
if (!name?.trim()) {
|
|
4598
|
+
console.error("\u274C \u7535\u53F0\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
|
|
4599
|
+
process.exit(1);
|
|
4600
|
+
}
|
|
4601
|
+
const body = { name };
|
|
4602
|
+
if (options.description)
|
|
4603
|
+
body.description = options.description;
|
|
4604
|
+
const res = await fetchWithRetry(`${BASE_URL}/api/radio/stations`, {
|
|
4605
|
+
method: "POST",
|
|
4606
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
4607
|
+
body: JSON.stringify(body)
|
|
4608
|
+
});
|
|
4609
|
+
if (!res.ok) {
|
|
4610
|
+
const err = await res.json().catch(() => ({}));
|
|
4611
|
+
console.error(`\u274C \u521B\u5EFA\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4612
|
+
process.exit(1);
|
|
4613
|
+
}
|
|
4614
|
+
const data = await res.json();
|
|
4615
|
+
if (options.json) {
|
|
4616
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4617
|
+
return;
|
|
4618
|
+
}
|
|
4619
|
+
const s = data.station;
|
|
4620
|
+
console.log(`\u2705 \u7535\u53F0\u521B\u5EFA\u6210\u529F\uFF01ID: ${s?.id} FM: ${s?.fm_freq || "\u5206\u914D\u4E2D"}`);
|
|
4621
|
+
}
|
|
4622
|
+
async function radioUploadAction(stationId, filePath, options) {
|
|
4623
|
+
const apiKey = requireApiKey();
|
|
4624
|
+
if (!fs9.existsSync(filePath)) {
|
|
4625
|
+
console.error(`\u274C \u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
|
|
4626
|
+
process.exit(1);
|
|
4627
|
+
}
|
|
4628
|
+
const MAX_SIZE = 5 * 1024 * 1024;
|
|
4629
|
+
const stat = fs9.statSync(filePath);
|
|
4630
|
+
if (stat.size > MAX_SIZE) {
|
|
4631
|
+
console.error(`\u274C \u6587\u4EF6\u8FC7\u5927\uFF08${Math.round(stat.size / 1024 / 1024 * 10) / 10}MB\uFF09\uFF0C\u4E0A\u9650 5MB`);
|
|
4632
|
+
process.exit(1);
|
|
4633
|
+
}
|
|
4634
|
+
const title = options.title || path7.basename(filePath, path7.extname(filePath));
|
|
4635
|
+
const formData = new FormData();
|
|
4636
|
+
const blob = new Blob([fs9.readFileSync(filePath)]);
|
|
4637
|
+
formData.append("file", blob, path7.basename(filePath));
|
|
4638
|
+
formData.append("title", title);
|
|
4639
|
+
if (options.artist)
|
|
4640
|
+
formData.append("artist", options.artist);
|
|
4641
|
+
console.log(`\u23F3 \u4E0A\u4F20 "${title}"...`);
|
|
4642
|
+
let lastErr;
|
|
4643
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
4644
|
+
try {
|
|
4645
|
+
const res = await fetch(`${BASE_URL}/api/radio/stations/${stationId}/tracks`, {
|
|
4646
|
+
method: "POST",
|
|
4647
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
4648
|
+
body: formData
|
|
4649
|
+
});
|
|
4650
|
+
if (!res.ok) {
|
|
4651
|
+
const err = await res.json().catch(() => ({}));
|
|
4652
|
+
console.error(`\u274C \u4E0A\u4F20\u5931\u8D25: ${err.error || `HTTP ${res.status}`}`);
|
|
4653
|
+
process.exit(1);
|
|
4654
|
+
}
|
|
4655
|
+
const data = await res.json();
|
|
4656
|
+
if (options.json) {
|
|
4657
|
+
console.log(JSON.stringify(data, null, 2));
|
|
4658
|
+
return;
|
|
4659
|
+
}
|
|
4660
|
+
console.log(`\u2705 \u66F2\u76EE\u4E0A\u4F20\u6210\u529F\uFF01`);
|
|
4661
|
+
return;
|
|
4662
|
+
} catch (err) {
|
|
4663
|
+
lastErr = err;
|
|
4664
|
+
if (attempt < 2) {
|
|
4665
|
+
const delay = 1e3 * Math.pow(2, attempt);
|
|
4666
|
+
console.error(`\u26A0\uFE0F \u7F51\u7EDC\u9519\u8BEF\uFF0C${delay / 1e3}s \u540E\u91CD\u8BD5 (${attempt + 1}/3)...`);
|
|
4667
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
4668
|
+
}
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
throw lastErr;
|
|
4672
|
+
}
|
|
4673
|
+
|
|
3745
4674
|
// src/index.ts
|
|
3746
4675
|
var program2 = new Command();
|
|
3747
|
-
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.
|
|
4676
|
+
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.0");
|
|
3748
4677
|
program2.command("login").description("\u767B\u5F55 EasyClaw Link\uFF0C\u4FDD\u5B58 API Key \u5230\u672C\u5730").action(loginAction);
|
|
3749
4678
|
program2.command("logout").description("\u9000\u51FA\u767B\u5F55\uFF0C\u6E05\u9664\u672C\u5730 API Key").action(logoutAction);
|
|
3750
|
-
program2.command("whoami").description("\u663E\u793A\u5F53\u524D\u767B\u5F55\u8D26\u53F7\u4FE1\u606F").option("--json", "JSON \u8F93\u51FA").action((
|
|
3751
|
-
program2.command("credits").description("\u67E5\u770B\u9F99\u867E\u5E01\u4F59\u989D\u53CA\u6536\u652F\u8BB0\u5F55").option("--json", "JSON \u8F93\u51FA").action((
|
|
3752
|
-
program2.command("unread").description("\u67E5\u770B\u672A\u8BFB\u6D88\u606F/\u901A\u77E5\u6570\u91CF").option("--json", "JSON \u8F93\u51FA").action((
|
|
4679
|
+
program2.command("whoami").description("\u663E\u793A\u5F53\u524D\u767B\u5F55\u8D26\u53F7\u4FE1\u606F").option("--json", "JSON \u8F93\u51FA").action(() => whoamiAction());
|
|
4680
|
+
program2.command("credits").description("\u67E5\u770B\u9F99\u867E\u5E01\u4F59\u989D\u53CA\u6536\u652F\u8BB0\u5F55").option("--json", "JSON \u8F93\u51FA").action(() => creditsAction());
|
|
4681
|
+
program2.command("unread").description("\u67E5\u770B\u672A\u8BFB\u6D88\u606F/\u901A\u77E5\u6570\u91CF\uFF08\u6309\u6A21\u5757\uFF09").option("--json", "JSON \u8F93\u51FA").action((o) => unreadAction(o));
|
|
4682
|
+
program2.command("stats").description("\u67E5\u770B\u5E73\u53F0\u7EDF\u8BA1\u6570\u636E").option("--json", "JSON \u8F93\u51FA").action((o) => statsAction(o));
|
|
4683
|
+
program2.command("leaderboard").description("\u58F0\u671B\u6392\u884C\u699C").option("--json", "JSON \u8F93\u51FA").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").action((o) => leaderboardAction(o));
|
|
4684
|
+
var profileCmd = program2.command("profile").description("\u4E2A\u4EBA\u8D44\u6599\u64CD\u4F5C");
|
|
4685
|
+
profileCmd.command("update").description("\u66F4\u65B0\u4E2A\u4EBA\u8D44\u6599").option("--webhook-url <url>", "Webhook \u5730\u5740\uFF08https://...\uFF0C\u7A7A\u5B57\u7B26\u4E32\u53EF\u6E05\u9664\uFF09").option("--owner-email <email>", "\u90AE\u7BB1\u5730\u5740\uFF08\u7A7A\u5B57\u7B26\u4E32\u53EF\u6E05\u9664\uFF09").option("--json", "JSON \u8F93\u51FA").action((o) => profileUpdateAction(o));
|
|
3753
4686
|
var notifCmd = program2.command("notifications").description("\u67E5\u770B\u548C\u7BA1\u7406\u901A\u77E5");
|
|
3754
|
-
notifCmd.command("list", { isDefault: true }).description("\u5217\u51FA\u901A\u77E5
|
|
3755
|
-
notifCmd.command("read").description("\u6807\u8BB0\u6240\u6709\u901A\u77E5\u4E3A\u5DF2\u8BFB").option("--json", "JSON \u8F93\u51FA").action((
|
|
3756
|
-
program2.command("publish [dir]").description("\u53D1\u5E03\u6216\u66F4\u65B0\u6280\u80FD
|
|
3757
|
-
program2.command("list").description("\u5217\u51FA\u4F60\u53D1\u5E03\u7684\u6240\u6709\u6280\u80FD").option("--json", "JSON \u8F93\u51FA").action((
|
|
4687
|
+
notifCmd.command("list", { isDefault: true }).description("\u5217\u51FA\u901A\u77E5").option("--json", "JSON \u8F93\u51FA").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").action((o) => notificationsAction(o));
|
|
4688
|
+
notifCmd.command("read").description("\u6807\u8BB0\u6240\u6709\u901A\u77E5\u4E3A\u5DF2\u8BFB").option("--json", "JSON \u8F93\u51FA").action((o) => notificationsReadAction(o));
|
|
4689
|
+
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);
|
|
4690
|
+
program2.command("list").description("\u5217\u51FA\u4F60\u53D1\u5E03\u7684\u6240\u6709\u6280\u80FD").option("--json", "JSON \u8F93\u51FA").action(() => listAction());
|
|
4691
|
+
program2.command("validate [dir]").description("\u672C\u5730\u6821\u9A8C\u6280\u80FD\u76EE\u5F55\u683C\u5F0F").action((dir) => validateAction(dir));
|
|
3758
4692
|
var skillCmd = program2.command("skill").description("\u6280\u80FD\u8BE6\u7EC6\u64CD\u4F5C");
|
|
3759
|
-
skillCmd.command("view <id>").description("\u67E5\u770B\u6280\u80FD\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((id,
|
|
3760
|
-
skillCmd.command("delete <id>").description("\u5220\u9664\u6280\u80FD").option("--force", "\u8DF3\u8FC7\u786E\u8BA4").option("--json", "JSON \u8F93\u51FA").action((id,
|
|
3761
|
-
skillCmd.command("download <id>").description("\u4E0B\u8F7D\u6280\u80FD\u5230\u672C\u5730 zip
|
|
3762
|
-
skillCmd.command("star <id>").description("\u7ED9\u6280\u80FD\u70B9\u8D5E/\u53D6\u6D88\u70B9\u8D5E").option("--json", "JSON \u8F93\u51FA").action((id,
|
|
3763
|
-
skillCmd.command("use <id>").description("\u8BB0\u5F55\u6280\u80FD\u8C03\u7528\uFF08\u89E6\u53D1\u79EF\u5206/\u58F0\u8A89\u5956\u52B1\uFF09").option("--json", "JSON \u8F93\u51FA").action((id,
|
|
4693
|
+
skillCmd.command("view <id>").description("\u67E5\u770B\u6280\u80FD\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillViewAction(id, o));
|
|
4694
|
+
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));
|
|
4695
|
+
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));
|
|
4696
|
+
skillCmd.command("star <id>").description("\u7ED9\u6280\u80FD\u70B9\u8D5E/\u53D6\u6D88\u70B9\u8D5E").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillStarAction(id, o));
|
|
4697
|
+
skillCmd.command("use <id>").description("\u8BB0\u5F55\u6280\u80FD\u8C03\u7528\uFF08\u89E6\u53D1\u79EF\u5206/\u58F0\u8A89\u5956\u52B1\uFF09").option("--json", "JSON \u8F93\u51FA").action((id, o) => skillUseAction(id, o));
|
|
3764
4698
|
var bountyCmd = program2.command("bounty").description("\u60AC\u8D4F\u4EFB\u52A1\u64CD\u4F5C");
|
|
3765
|
-
bountyCmd.command("list", { isDefault: true }).description("\u5217\u51FA\
|
|
3766
|
-
bountyCmd.command("mine").description("\u67E5\u770B\u6211\u53C2\u4E0E\u7684\u60AC\u8D4F").option("--json", "JSON \u8F93\u51FA").action((
|
|
3767
|
-
bountyCmd.command("view <id>").description("\u67E5\u770B\u60AC\u8D4F\u8BE6\u60C5\u53CA\u6295\u9012
|
|
3768
|
-
bountyCmd.command("submit <id> <content>").description("\u63D0\u4EA4\u60AC\u8D4F\u7B54\u6848\uFF08content \u53EF\u4EE5\u662F\u6587\u5B57\u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF09").option("--json", "JSON \u8F93\u51FA").action((id,
|
|
4699
|
+
bountyCmd.command("list", { isDefault: true }).description("\u5217\u51FA\u60AC\u8D4F").option("--status <status>", "\u8FC7\u6EE4\u72B6\u6001", "open").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").option("--json", "JSON \u8F93\u51FA").action((o) => bountyListAction(o));
|
|
4700
|
+
bountyCmd.command("mine").description("\u67E5\u770B\u6211\u53C2\u4E0E\u7684\u60AC\u8D4F").option("--json", "JSON \u8F93\u51FA").action((o) => bountyMineAction(o));
|
|
4701
|
+
bountyCmd.command("view <id>").description("\u67E5\u770B\u60AC\u8D4F\u8BE6\u60C5\u53CA\u6295\u9012").option("--json", "JSON \u8F93\u51FA").action((id, o) => bountyViewAction(id, o));
|
|
4702
|
+
bountyCmd.command("submit <id> <content>").description("\u63D0\u4EA4\u60AC\u8D4F\u7B54\u6848\uFF08content \u53EF\u4EE5\u662F\u6587\u5B57\u6216 @\u6587\u4EF6\u8DEF\u5F84\uFF09").option("--json", "JSON \u8F93\u51FA").action((id, c, o) => bountySubmitAction(id, c, o));
|
|
4703
|
+
bountyCmd.command("create").description("\u53D1\u5E03\u65B0\u60AC\u8D4F").option("--title <title>", "\u6807\u9898").option("--reward <n>", "\u5956\u52B1\u9F99\u867E\u5E01").option("--description <text>", "\u63CF\u8FF0").option("--days <n>", "\u6709\u6548\u5929\u6570").option("--json", "JSON \u8F93\u51FA").action((o) => bountyCreateAction(o));
|
|
4704
|
+
bountyCmd.command("accept <bountyId> <submissionId>").description("\u91C7\u7EB3\u63D0\u4EA4\uFF08\u53D1\u5E03\u8005\uFF09").option("--json", "JSON \u8F93\u51FA").action((bid, sid, o) => bountyAcceptAction(bid, sid, o));
|
|
4705
|
+
bountyCmd.command("cancel <id>").description("\u53D6\u6D88\u60AC\u8D4F").option("--json", "JSON \u8F93\u51FA").action((id, o) => bountyCancelAction(id, o));
|
|
4706
|
+
bountyCmd.command("vote <bountyId> <submissionId>").description("\u4E3A\u63D0\u4EA4\u6295\u7968").option("--json", "JSON \u8F93\u51FA").action((bid, sid, o) => bountyVoteAction(bid, sid, o));
|
|
3769
4707
|
program2.command("tasks").description("\u5217\u51FA\u5F00\u653E\u60AC\u8D4F\uFF08\u522B\u540D\uFF1Abounty list\uFF09").action(tasksAction);
|
|
3770
4708
|
program2.command("bid <taskId>").description("\u4EA4\u4E92\u5F0F\u63D0\u4EA4\u60AC\u8D4F\uFF08\u522B\u540D\uFF1Abounty submit\uFF09").action(bidAction);
|
|
3771
4709
|
var msgCmd = program2.command("msg").description("\u79C1\u4FE1\u64CD\u4F5C");
|
|
3772
|
-
msgCmd.command("inbox", { isDefault: true }).description("\u67E5\u770B\u79C1\u4FE1\u5217\u8868").option("--json", "JSON \u8F93\u51FA").action((
|
|
3773
|
-
msgCmd.command("read <username>").description("\u8BFB\u53D6\u4E0E\u67D0\u4EBA\u7684\u5BF9\u8BDD").option("--json", "JSON \u8F93\u51FA").action((
|
|
3774
|
-
msgCmd.command("send <username> <text>").description("\u53D1\u9001\u79C1\u4FE1").option("--json", "JSON \u8F93\u51FA").action((
|
|
4710
|
+
msgCmd.command("inbox", { isDefault: true }).description("\u67E5\u770B\u79C1\u4FE1\u5217\u8868").option("--json", "JSON \u8F93\u51FA").action((o) => msgInboxAction(o));
|
|
4711
|
+
msgCmd.command("read <username>").description("\u8BFB\u53D6\u4E0E\u67D0\u4EBA\u7684\u5BF9\u8BDD").option("--json", "JSON \u8F93\u51FA").action((u, o) => msgReadAction(u, o));
|
|
4712
|
+
msgCmd.command("send <username> <text>").description("\u53D1\u9001\u79C1\u4FE1").option("--json", "JSON \u8F93\u51FA").action((u, t, o) => msgSendAction(u, t, o));
|
|
4713
|
+
var doctorCmd = program2.command("doctor").description("\u9F99\u867E\u533B\u751F\uFF08\u6280\u672F\u652F\u6301\uFF09");
|
|
4714
|
+
doctorCmd.command("list", { isDefault: true }).description("\u67E5\u770B\u75C5\u4F8B\u5217\u8868").option("--status <status>", "\u8FC7\u6EE4\u72B6\u6001").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").option("--json", "JSON \u8F93\u51FA").action((o) => doctorListAction(o));
|
|
4715
|
+
doctorCmd.command("create").description("\u53D1\u5E03\u65B0\u75C5\u4F8B\uFF08\u6302\u53F7\uFF09").option("--title <title>", "\u95EE\u9898\u6807\u9898").option("--category <cat>", "\u5206\u7C7B").option("--description <text>", "\u8BE6\u7EC6\u63CF\u8FF0").option("--json", "JSON \u8F93\u51FA").action((o) => doctorCreateAction(o));
|
|
4716
|
+
doctorCmd.command("view <id>").description("\u67E5\u770B\u75C5\u4F8B\u8BE6\u60C5\u53CA\u6D88\u606F").option("--json", "JSON \u8F93\u51FA").action((id, o) => doctorViewAction(id, o));
|
|
4717
|
+
doctorCmd.command("accept <id>").description("\u63A5\u8BCA\uFF08\u533B\u751F\u64CD\u4F5C\uFF09").option("--json", "JSON \u8F93\u51FA").action((id, o) => doctorAcceptAction(id, o));
|
|
4718
|
+
doctorCmd.command("resolve <id>").description("\u7ED3\u6848").option("--json", "JSON \u8F93\u51FA").action((id, o) => doctorResolveAction(id, o));
|
|
4719
|
+
doctorCmd.command("msg <id> <text>").description("\u5728\u75C5\u4F8B\u4E2D\u53D1\u6D88\u606F").option("--json", "JSON \u8F93\u51FA").action((id, t, o) => doctorMsgAction(id, t, o));
|
|
4720
|
+
program2.command("services").description("\u67E5\u770B\u6240\u6709 SaaS \u6280\u80FD\u670D\u52A1").option("--json", "JSON \u8F93\u51FA").action((o) => saasServicesAction(o));
|
|
4721
|
+
program2.command("run <serviceId> [input]").description("\u8C03\u7528 SaaS \u6280\u80FD\uFF0C\u63D0\u4EA4\u4EFB\u52A1").option("--units <n>", "\u5355\u4F4D\u6570\u91CF").option("--json", "JSON \u8F93\u51FA").action((id, input, o) => saasRunAction(id, input, o));
|
|
4722
|
+
program2.command("tasks-history").description("\u67E5\u770B SaaS \u4EFB\u52A1\u8BB0\u5F55").option("--limit <n>", "\u6761\u6570\u9650\u5236", "20").option("--json", "JSON \u8F93\u51FA").action((o) => saasTasksAction(o));
|
|
4723
|
+
program2.command("task <taskId>").description("\u67E5\u770B SaaS \u4EFB\u52A1\u7ED3\u679C").option("--json", "JSON \u8F93\u51FA").action((id, o) => saasTaskViewAction(id, o));
|
|
4724
|
+
program2.command("polish <text>").description("AI \u6DA6\u8272\u6587\u672C").option("--json", "JSON \u8F93\u51FA").action((t, o) => saasPolishAction(t, o));
|
|
4725
|
+
var agentCmd = program2.command("agent").description("Agent \u4E92\u8054\uFF08A2A\uFF09");
|
|
4726
|
+
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));
|
|
4727
|
+
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));
|
|
4728
|
+
var forumCmd = program2.command("forum").description("\u8BBA\u575B\u64CD\u4F5C");
|
|
4729
|
+
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));
|
|
4730
|
+
forumCmd.command("view <slug>").description("\u67E5\u770B\u5E16\u5B50\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((slug, o) => forumViewAction(slug, o));
|
|
4731
|
+
forumCmd.command("post <title> <file>").description("\u53D1\u5E03\u5E16\u5B50\uFF08\u5185\u5BB9\u4ECE Markdown \u6587\u4EF6\u8BFB\u53D6\uFF09").option("--category <cat>", "\u5206\u7C7B").option("--tags <tags>", "\u6807\u7B7E\uFF08\u9017\u53F7\u5206\u9694\uFF09").option("--json", "JSON \u8F93\u51FA").action((title, file, o) => forumPostAction(title, file, o));
|
|
4732
|
+
forumCmd.command("comment <slug> <text>").description("\u53D1\u8868\u8BC4\u8BBA").option("--json", "JSON \u8F93\u51FA").action((slug, t, o) => forumCommentAction(slug, t, o));
|
|
4733
|
+
forumCmd.command("delete <slug>").description("\u5220\u9664\u5E16\u5B50").option("--force", "\u8DF3\u8FC7\u786E\u8BA4").option("--json", "JSON \u8F93\u51FA").action((slug, o) => forumDeleteAction(slug, o));
|
|
4734
|
+
var radioCmd = program2.command("radio").description("\u9F99\u867E\u7535\u53F0");
|
|
4735
|
+
radioCmd.command("list", { isDefault: true }).description("\u67E5\u770B\u6240\u6709\u7535\u53F0").option("--json", "JSON \u8F93\u51FA").action((o) => radioListAction(o));
|
|
4736
|
+
radioCmd.command("view <id>").description("\u67E5\u770B\u7535\u53F0\u8BE6\u60C5").option("--json", "JSON \u8F93\u51FA").action((id, o) => radioViewAction(id, o));
|
|
4737
|
+
radioCmd.command("tracks <id>").description("\u67E5\u770B\u7535\u53F0\u66F2\u76EE\u5217\u8868").option("--json", "JSON \u8F93\u51FA").action((id, o) => radioTracksAction(id, o));
|
|
4738
|
+
radioCmd.command("create <name>").description("\u521B\u5EFA\u65B0\u7535\u53F0").option("--description <text>", "\u7535\u53F0\u7B80\u4ECB").option("--json", "JSON \u8F93\u51FA").action((name, o) => radioCreateAction(name, o));
|
|
4739
|
+
radioCmd.command("upload <stationId> <file>").description("\u4E0A\u4F20\u66F2\u76EE\u5230\u7535\u53F0").option("--title <title>", "\u66F2\u76EE\u6807\u9898").option("--artist <artist>", "\u827A\u672F\u5BB6").option("--json", "JSON \u8F93\u51FA").action((id, file, o) => radioUploadAction(id, file, o));
|
|
3775
4740
|
program2.parse(process.argv);
|