hypercore-cli 1.1.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/LICENSE +21 -0
- package/README.md +110 -0
- package/dist/api-XGC7D5AW.js +162 -0
- package/dist/auth-DNQWYQKT.js +21 -0
- package/dist/background-2EGCAAQH.js +14 -0
- package/dist/backlog-Q2NZCLNY.js +24 -0
- package/dist/chunk-2CMSCWQW.js +162 -0
- package/dist/chunk-2LJ2DVEB.js +167 -0
- package/dist/chunk-3RPFCQKJ.js +288 -0
- package/dist/chunk-43OLRXM5.js +263 -0
- package/dist/chunk-4DVYJAJL.js +57 -0
- package/dist/chunk-6OL3GA3P.js +173 -0
- package/dist/chunk-AUHU7ALH.js +2023 -0
- package/dist/chunk-B6A2AKLN.js +139 -0
- package/dist/chunk-BE46C7JW.js +46 -0
- package/dist/chunk-CUVAUOXL.js +58 -0
- package/dist/chunk-GH7E2OJE.js +223 -0
- package/dist/chunk-GOOTEPBK.js +271 -0
- package/dist/chunk-GPPMJYSM.js +133 -0
- package/dist/chunk-GU2FZQ6A.js +69 -0
- package/dist/chunk-IOPKN5GD.js +190 -0
- package/dist/chunk-IXOIOGR5.js +1505 -0
- package/dist/chunk-KRPOPWGA.js +251 -0
- package/dist/chunk-MGLJ53QN.js +219 -0
- package/dist/chunk-MV4TTRYX.js +533 -0
- package/dist/chunk-OPZYEVYR.js +150 -0
- package/dist/chunk-QTSLP47C.js +166 -0
- package/dist/chunk-R3GPQC7I.js +393 -0
- package/dist/chunk-RKB2JOV2.js +43 -0
- package/dist/chunk-RNG3K465.js +80 -0
- package/dist/chunk-TGTYKBGC.js +86 -0
- package/dist/chunk-U5SGAIMM.js +681 -0
- package/dist/chunk-V5UHPPSY.js +140 -0
- package/dist/chunk-WHLVZCQY.js +245 -0
- package/dist/chunk-XDRCBMZZ.js +66 -0
- package/dist/chunk-XOS6HPEF.js +134 -0
- package/dist/chunk-ZSBHUGWR.js +262 -0
- package/dist/claude-NSQ442XD.js +12 -0
- package/dist/commands-CK3WFAGI.js +128 -0
- package/dist/commands-U63OEO5J.js +1044 -0
- package/dist/commands-ZE6GD3WC.js +232 -0
- package/dist/config-4EW42BSF.js +8 -0
- package/dist/config-loader-SXO674TF.js +24 -0
- package/dist/diagnose-AFW3ZTZ4.js +12 -0
- package/dist/display-IIUBEYWN.js +58 -0
- package/dist/extractor-QV53W2YJ.js +129 -0
- package/dist/history-WMSCHERZ.js +180 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +406 -0
- package/dist/instance-registry-YSIJXSO7.js +15 -0
- package/dist/keybindings-JAAMLH3G.js +15 -0
- package/dist/loader-WHNTZTLP.js +58 -0
- package/dist/network-MM6YWPGO.js +279 -0
- package/dist/notify-HPTALZDC.js +14 -0
- package/dist/openai-compat-UQWJXBEK.js +12 -0
- package/dist/permissions-JUKXMNDH.js +10 -0
- package/dist/prompt-QV45TXRL.js +166 -0
- package/dist/quality-ST7PPNFR.js +16 -0
- package/dist/repl-RT3AHL7M.js +3375 -0
- package/dist/roadmap-5OBEKROY.js +17 -0
- package/dist/server-PORT7OEG.js +57 -0
- package/dist/session-4VUNDWLH.js +21 -0
- package/dist/skills-V4A35XKG.js +175 -0
- package/dist/store-Y4LU5QTO.js +25 -0
- package/dist/team-HO7Z4SIM.js +385 -0
- package/dist/telemetry-6R4EIE6O.js +30 -0
- package/dist/test-runner-ZQH5Y6OJ.js +619 -0
- package/dist/theme-3SYJ3UQA.js +14 -0
- package/dist/upgrade-7TGI3SXO.js +83 -0
- package/dist/verify-JUDKTPKZ.js +14 -0
- package/dist/web/static/app.js +562 -0
- package/dist/web/static/index.html +132 -0
- package/dist/web/static/mirror.css +1001 -0
- package/dist/web/static/mirror.html +184 -0
- package/dist/web/static/mirror.js +1125 -0
- package/dist/web/static/onboard.css +302 -0
- package/dist/web/static/onboard.html +140 -0
- package/dist/web/static/onboard.js +260 -0
- package/dist/web/static/style.css +602 -0
- package/dist/web/static/workspace.css +1568 -0
- package/dist/web/static/workspace.html +408 -0
- package/dist/web/static/workspace.js +1683 -0
- package/dist/web-Z5HSCQHW.js +39 -0
- package/package.json +67 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// src/admin/quality.ts
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { readFile, stat, readdir } from "fs/promises";
|
|
5
|
+
import { existsSync } from "fs";
|
|
6
|
+
function toText(value) {
|
|
7
|
+
if (typeof value === "string") return value;
|
|
8
|
+
if (value instanceof Uint8Array) return Buffer.from(value).toString("utf-8");
|
|
9
|
+
return "";
|
|
10
|
+
}
|
|
11
|
+
function getExecErrorOutput(err) {
|
|
12
|
+
if (err && typeof err === "object") {
|
|
13
|
+
const stdout = toText(err.stdout);
|
|
14
|
+
const stderr = toText(err.stderr);
|
|
15
|
+
const merged = [stdout, stderr].filter(Boolean).join("\n").trim();
|
|
16
|
+
if (merged) return merged;
|
|
17
|
+
}
|
|
18
|
+
return err instanceof Error ? err.message : String(err);
|
|
19
|
+
}
|
|
20
|
+
async function walkFiles(dir, accept, out = []) {
|
|
21
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
22
|
+
for (const entry of entries) {
|
|
23
|
+
const fullPath = join(dir, entry.name);
|
|
24
|
+
if (entry.isDirectory()) {
|
|
25
|
+
await walkFiles(fullPath, accept, out);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (entry.isFile() && accept(fullPath)) {
|
|
29
|
+
out.push(fullPath);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
async function checkTests(projectRoot) {
|
|
35
|
+
try {
|
|
36
|
+
const output = execSync("npm test -- --reporter=verbose", {
|
|
37
|
+
cwd: projectRoot,
|
|
38
|
+
encoding: "utf-8",
|
|
39
|
+
timeout: 6e4,
|
|
40
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
41
|
+
});
|
|
42
|
+
const passMatch = output.match(/(\d+)\s+passed/);
|
|
43
|
+
const failMatch = output.match(/(\d+)\s+failed/);
|
|
44
|
+
const passed = passMatch ? parseInt(passMatch[1]) : 0;
|
|
45
|
+
const failed = failMatch ? parseInt(failMatch[1]) : 0;
|
|
46
|
+
const total = passed + failed;
|
|
47
|
+
return {
|
|
48
|
+
name: "\u6D4B\u8BD5\u901A\u8FC7\u7387",
|
|
49
|
+
ok: failed === 0 && passed > 0,
|
|
50
|
+
detail: `${passed}/${total} \u901A\u8FC7${failed > 0 ? `\uFF0C${failed} \u5931\u8D25` : ""}`,
|
|
51
|
+
value: total > 0 ? Math.round(passed / total * 100) : 0,
|
|
52
|
+
unit: "%"
|
|
53
|
+
};
|
|
54
|
+
} catch (err) {
|
|
55
|
+
const output = getExecErrorOutput(err);
|
|
56
|
+
const passMatch = output.match(/(\d+)\s+passed/);
|
|
57
|
+
const failMatch = output.match(/(\d+)\s+failed/);
|
|
58
|
+
if (passMatch || failMatch) {
|
|
59
|
+
const passed = passMatch ? parseInt(passMatch[1]) : 0;
|
|
60
|
+
const failed = failMatch ? parseInt(failMatch[1]) : 0;
|
|
61
|
+
return {
|
|
62
|
+
name: "\u6D4B\u8BD5\u901A\u8FC7\u7387",
|
|
63
|
+
ok: false,
|
|
64
|
+
detail: `${passed}/${passed + failed} \u901A\u8FC7\uFF0C${failed} \u5931\u8D25`,
|
|
65
|
+
value: passed + failed > 0 ? Math.round(passed / (passed + failed) * 100) : 0,
|
|
66
|
+
unit: "%"
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
name: "\u6D4B\u8BD5\u901A\u8FC7\u7387",
|
|
71
|
+
ok: false,
|
|
72
|
+
detail: `\u6D4B\u8BD5\u8FD0\u884C\u5931\u8D25: ${output.slice(0, 100)}`
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function checkTodos(projectRoot) {
|
|
77
|
+
try {
|
|
78
|
+
const srcDir = join(projectRoot, "src");
|
|
79
|
+
if (!existsSync(srcDir)) {
|
|
80
|
+
return { name: "TODO \u626B\u63CF", ok: true, detail: "src \u76EE\u5F55\u4E0D\u5B58\u5728", value: 0, unit: "\u4E2A" };
|
|
81
|
+
}
|
|
82
|
+
const todos = [];
|
|
83
|
+
const files = await walkFiles(srcDir, (file) => file.endsWith(".ts") || file.endsWith(".js"));
|
|
84
|
+
for (const file of files) {
|
|
85
|
+
const content = await readFile(file, "utf-8");
|
|
86
|
+
const lines = content.split(/\r?\n/);
|
|
87
|
+
for (let i = 0; i < lines.length; i++) {
|
|
88
|
+
const text = lines[i];
|
|
89
|
+
const typeMatch = text.match(/(TODO|FIXME|HACK|XXX)/i);
|
|
90
|
+
if (!typeMatch) continue;
|
|
91
|
+
todos.push({
|
|
92
|
+
file: file.replace(`${projectRoot}/`, ""),
|
|
93
|
+
line: i + 1,
|
|
94
|
+
text: text.trim().slice(0, 80),
|
|
95
|
+
type: typeMatch[1].toUpperCase()
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const byType = {};
|
|
100
|
+
for (const t of todos) {
|
|
101
|
+
byType[t.type] = (byType[t.type] || 0) + 1;
|
|
102
|
+
}
|
|
103
|
+
const typeSummary = Object.entries(byType).map(([t, c]) => `${t}:${c}`).join(" ");
|
|
104
|
+
return {
|
|
105
|
+
name: "TODO \u626B\u63CF",
|
|
106
|
+
ok: todos.length <= 10,
|
|
107
|
+
detail: todos.length === 0 ? "\u65E0\u672A\u5904\u7406\u6807\u8BB0" : `${todos.length} \u4E2A\u6807\u8BB0 (${typeSummary})`,
|
|
108
|
+
value: todos.length,
|
|
109
|
+
unit: "\u4E2A"
|
|
110
|
+
};
|
|
111
|
+
} catch {
|
|
112
|
+
return { name: "TODO \u626B\u63CF", ok: true, detail: "\u626B\u63CF\u5931\u8D25\uFF0C\u8DF3\u8FC7", value: 0, unit: "\u4E2A" };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function checkDeps(projectRoot) {
|
|
116
|
+
try {
|
|
117
|
+
let auditIssues = 0;
|
|
118
|
+
try {
|
|
119
|
+
execSync("npm audit --json", {
|
|
120
|
+
cwd: projectRoot,
|
|
121
|
+
encoding: "utf-8",
|
|
122
|
+
timeout: 3e4,
|
|
123
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
124
|
+
});
|
|
125
|
+
} catch (err) {
|
|
126
|
+
const msg = getExecErrorOutput(err);
|
|
127
|
+
if (msg) {
|
|
128
|
+
try {
|
|
129
|
+
const audit = JSON.parse(msg);
|
|
130
|
+
auditIssues = audit?.metadata?.vulnerabilities?.total || 0;
|
|
131
|
+
} catch {
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
let outdated = 0;
|
|
136
|
+
try {
|
|
137
|
+
execSync("npm outdated --json", {
|
|
138
|
+
cwd: projectRoot,
|
|
139
|
+
encoding: "utf-8",
|
|
140
|
+
timeout: 3e4,
|
|
141
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
142
|
+
});
|
|
143
|
+
} catch (err) {
|
|
144
|
+
const msg = getExecErrorOutput(err);
|
|
145
|
+
if (msg) {
|
|
146
|
+
try {
|
|
147
|
+
const pkgs = JSON.parse(msg);
|
|
148
|
+
outdated = Object.keys(pkgs).length;
|
|
149
|
+
} catch {
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const parts = [];
|
|
154
|
+
if (auditIssues > 0) parts.push(`${auditIssues} \u5B89\u5168\u6F0F\u6D1E`);
|
|
155
|
+
if (outdated > 0) parts.push(`${outdated} \u8FC7\u671F\u4F9D\u8D56`);
|
|
156
|
+
if (parts.length === 0) parts.push("\u4F9D\u8D56\u5065\u5EB7");
|
|
157
|
+
return {
|
|
158
|
+
name: "\u4F9D\u8D56\u68C0\u67E5",
|
|
159
|
+
ok: auditIssues === 0,
|
|
160
|
+
detail: parts.join(", "),
|
|
161
|
+
value: auditIssues,
|
|
162
|
+
unit: "\u6F0F\u6D1E"
|
|
163
|
+
};
|
|
164
|
+
} catch {
|
|
165
|
+
return { name: "\u4F9D\u8D56\u68C0\u67E5", ok: true, detail: "\u68C0\u67E5\u5931\u8D25\uFF0C\u8DF3\u8FC7" };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
async function checkPackageSize(projectRoot) {
|
|
169
|
+
const distDir = join(projectRoot, "dist");
|
|
170
|
+
if (!existsSync(distDir)) {
|
|
171
|
+
return { name: "\u5305\u4F53\u79EF", ok: false, detail: "dist/ \u4E0D\u5B58\u5728\uFF0C\u5148\u8FD0\u884C build" };
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const files = await walkFiles(
|
|
175
|
+
distDir,
|
|
176
|
+
(file) => file.endsWith(".js") || file.endsWith(".mjs") || file.endsWith(".cjs")
|
|
177
|
+
);
|
|
178
|
+
let totalBytes = 0;
|
|
179
|
+
for (const file of files) {
|
|
180
|
+
const fileStat = await stat(file);
|
|
181
|
+
totalBytes += fileStat.size;
|
|
182
|
+
}
|
|
183
|
+
const sizeMB = (totalBytes / 1024 / 1024).toFixed(2);
|
|
184
|
+
return {
|
|
185
|
+
name: "\u5305\u4F53\u79EF",
|
|
186
|
+
ok: totalBytes < 5 * 1024 * 1024,
|
|
187
|
+
// < 5MB
|
|
188
|
+
detail: `${sizeMB} MB`,
|
|
189
|
+
value: totalBytes,
|
|
190
|
+
unit: "bytes"
|
|
191
|
+
};
|
|
192
|
+
} catch {
|
|
193
|
+
return { name: "\u5305\u4F53\u79EF", ok: true, detail: "\u4F53\u79EF\u8BA1\u7B97\u5931\u8D25\uFF0C\u8DF3\u8FC7" };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async function checkBuild(projectRoot) {
|
|
197
|
+
try {
|
|
198
|
+
execSync("npm run build", {
|
|
199
|
+
cwd: projectRoot,
|
|
200
|
+
encoding: "utf-8",
|
|
201
|
+
timeout: 6e4,
|
|
202
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
203
|
+
});
|
|
204
|
+
return { name: "Build", ok: true, detail: "\u7F16\u8BD1\u6210\u529F" };
|
|
205
|
+
} catch (err) {
|
|
206
|
+
const msg = getExecErrorOutput(err);
|
|
207
|
+
return { name: "Build", ok: false, detail: `\u7F16\u8BD1\u5931\u8D25: ${msg.slice(0, 100)}` };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async function runQualityReport(projectRoot, options) {
|
|
211
|
+
const checks = [];
|
|
212
|
+
const [todoResult, depResult, sizeResult] = await Promise.all([
|
|
213
|
+
checkTodos(projectRoot),
|
|
214
|
+
checkDeps(projectRoot),
|
|
215
|
+
checkPackageSize(projectRoot)
|
|
216
|
+
]);
|
|
217
|
+
checks.push(todoResult, depResult, sizeResult);
|
|
218
|
+
if (!options?.skipBuild) {
|
|
219
|
+
checks.push(await checkBuild(projectRoot));
|
|
220
|
+
}
|
|
221
|
+
if (!options?.skipTests) {
|
|
222
|
+
checks.push(await checkTests(projectRoot));
|
|
223
|
+
}
|
|
224
|
+
const score = calculateScore(checks);
|
|
225
|
+
return {
|
|
226
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
227
|
+
projectRoot,
|
|
228
|
+
checks,
|
|
229
|
+
score
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function calculateScore(checks) {
|
|
233
|
+
if (checks.length === 0) return 0;
|
|
234
|
+
const weights = {
|
|
235
|
+
"\u6D4B\u8BD5\u901A\u8FC7\u7387": 30,
|
|
236
|
+
"Build": 25,
|
|
237
|
+
"\u4F9D\u8D56\u68C0\u67E5": 20,
|
|
238
|
+
"TODO \u626B\u63CF": 15,
|
|
239
|
+
"\u5305\u4F53\u79EF": 10
|
|
240
|
+
};
|
|
241
|
+
let totalWeight = 0;
|
|
242
|
+
let weightedScore = 0;
|
|
243
|
+
for (const c of checks) {
|
|
244
|
+
const w = weights[c.name] || 10;
|
|
245
|
+
totalWeight += w;
|
|
246
|
+
if (c.ok) {
|
|
247
|
+
weightedScore += w;
|
|
248
|
+
} else if (c.value !== void 0 && c.unit === "%") {
|
|
249
|
+
weightedScore += w * (c.value / 100);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return totalWeight > 0 ? Math.round(weightedScore / totalWeight * 100) : 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export {
|
|
256
|
+
checkTests,
|
|
257
|
+
checkTodos,
|
|
258
|
+
checkDeps,
|
|
259
|
+
checkPackageSize,
|
|
260
|
+
checkBuild,
|
|
261
|
+
runQualityReport
|
|
262
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadLocalToken
|
|
3
|
+
} from "./chunk-XDRCBMZZ.js";
|
|
4
|
+
import {
|
|
5
|
+
showError,
|
|
6
|
+
showTaskList,
|
|
7
|
+
showTeamStatus
|
|
8
|
+
} from "./chunk-R3GPQC7I.js";
|
|
9
|
+
import "./chunk-BE46C7JW.js";
|
|
10
|
+
import "./chunk-RNG3K465.js";
|
|
11
|
+
import "./chunk-V5UHPPSY.js";
|
|
12
|
+
|
|
13
|
+
// src/team/commands.ts
|
|
14
|
+
import chalk from "chalk";
|
|
15
|
+
function createTeamSlashCommands() {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
name: "team",
|
|
19
|
+
description: "\u67E5\u770B\u56E2\u961F\u72B6\u6001",
|
|
20
|
+
category: "team",
|
|
21
|
+
handler: async (_args, _ctx) => {
|
|
22
|
+
const token = await loadLocalToken();
|
|
23
|
+
if (!token) {
|
|
24
|
+
console.log(chalk.dim("\n \u672A\u52A0\u5165\u56E2\u961F\u3002\u8BF7\u4F7F\u7528 hyper team create \u6216 hyper team join\n"));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const resp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/status`, {
|
|
29
|
+
headers: { "Authorization": `Bearer ${token.token}` }
|
|
30
|
+
});
|
|
31
|
+
if (!resp.ok) {
|
|
32
|
+
showError("\u65E0\u6CD5\u83B7\u53D6\u56E2\u961F\u72B6\u6001");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const data = await resp.json();
|
|
36
|
+
showTeamStatus(data.team, data.members, token);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
showError(`\u8FDE\u63A5\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
39
|
+
console.log(chalk.dim(" \u8BF7\u786E\u4FDD\u56E2\u961F\u670D\u52A1\u5668\u5DF2\u542F\u52A8\uFF08hypercore web\uFF09"));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "task",
|
|
45
|
+
aliases: ["tasks"],
|
|
46
|
+
description: "\u56E2\u961F\u4EFB\u52A1 (add/list/done)",
|
|
47
|
+
category: "team",
|
|
48
|
+
handler: async (args, _ctx) => {
|
|
49
|
+
const token = await loadLocalToken();
|
|
50
|
+
if (!token) {
|
|
51
|
+
console.log(chalk.dim("\n \u672A\u52A0\u5165\u56E2\u961F\n"));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const sub = args[0] || "list";
|
|
55
|
+
const baseUrl = `${token.serverUrl}/api/team/${token.teamId}`;
|
|
56
|
+
const headers = {
|
|
57
|
+
"Authorization": `Bearer ${token.token}`,
|
|
58
|
+
"Content-Type": "application/json"
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
if (sub === "list" || sub === "ls") {
|
|
62
|
+
const resp = await fetch(`${baseUrl}/tasks`, { headers });
|
|
63
|
+
const data = await resp.json();
|
|
64
|
+
showTaskList(data.tasks);
|
|
65
|
+
} else if (sub === "add") {
|
|
66
|
+
const title = args.slice(1).join(" ");
|
|
67
|
+
if (!title) {
|
|
68
|
+
console.log(chalk.dim("\n \u7528\u6CD5: /task add <\u6807\u9898>\n"));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const resp = await fetch(`${baseUrl}/tasks`, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers,
|
|
74
|
+
body: JSON.stringify({ title })
|
|
75
|
+
});
|
|
76
|
+
const data = await resp.json();
|
|
77
|
+
console.log(chalk.green(`
|
|
78
|
+
\u2705 \u4EFB\u52A1 #${data.task.id} \u5DF2\u521B\u5EFA: ${data.task.title}
|
|
79
|
+
`));
|
|
80
|
+
} else if (sub === "done") {
|
|
81
|
+
const taskId = args[1];
|
|
82
|
+
if (!taskId) {
|
|
83
|
+
console.log(chalk.dim("\n \u7528\u6CD5: /task done <id>\n"));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
await fetch(`${baseUrl}/tasks/${taskId}`, {
|
|
87
|
+
method: "PUT",
|
|
88
|
+
headers,
|
|
89
|
+
body: JSON.stringify({ status: "done" })
|
|
90
|
+
});
|
|
91
|
+
console.log(chalk.green(`
|
|
92
|
+
\u2705 \u4EFB\u52A1 #${taskId} \u5DF2\u5B8C\u6210
|
|
93
|
+
`));
|
|
94
|
+
} else if (sub === "assign") {
|
|
95
|
+
const taskId = args[1];
|
|
96
|
+
const memberName = args[2];
|
|
97
|
+
if (!taskId || !memberName) {
|
|
98
|
+
console.log(chalk.dim("\n \u7528\u6CD5: /task assign <id> <\u6210\u5458>\n"));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const statusResp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/status`, { headers });
|
|
102
|
+
const statusData = await statusResp.json();
|
|
103
|
+
const target = statusData.members.find((m) => m.name === memberName || m.id === memberName);
|
|
104
|
+
if (!target) {
|
|
105
|
+
showError(`\u672A\u627E\u5230\u6210\u5458: ${memberName}`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
await fetch(`${baseUrl}/tasks/${taskId}`, {
|
|
109
|
+
method: "PUT",
|
|
110
|
+
headers,
|
|
111
|
+
body: JSON.stringify({ assignee: target.id, status: "doing" })
|
|
112
|
+
});
|
|
113
|
+
console.log(chalk.green(`
|
|
114
|
+
\u2705 \u4EFB\u52A1 #${taskId} \u5DF2\u5206\u914D\u7ED9 ${target.name}
|
|
115
|
+
`));
|
|
116
|
+
} else {
|
|
117
|
+
console.log(chalk.dim("\n \u7528\u6CD5: /task [list|add|done|assign]\n"));
|
|
118
|
+
}
|
|
119
|
+
} catch (err) {
|
|
120
|
+
showError(`\u8BF7\u6C42\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
export {
|
|
127
|
+
createTeamSlashCommands
|
|
128
|
+
};
|