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,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
activateMilestone,
|
|
3
|
+
addMilestone,
|
|
4
|
+
doneMilestone,
|
|
5
|
+
getMilestone,
|
|
6
|
+
getRoadmap,
|
|
7
|
+
listMilestones
|
|
8
|
+
} from "./chunk-OPZYEVYR.js";
|
|
9
|
+
import "./chunk-MGLJ53QN.js";
|
|
10
|
+
export {
|
|
11
|
+
activateMilestone,
|
|
12
|
+
addMilestone,
|
|
13
|
+
doneMilestone,
|
|
14
|
+
getMilestone,
|
|
15
|
+
getRoadmap,
|
|
16
|
+
listMilestones
|
|
17
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildWebServer,
|
|
3
|
+
canAccessApiPath,
|
|
4
|
+
canAccessWebSocketPath,
|
|
5
|
+
createWebServer,
|
|
6
|
+
createWebServerAutoPort,
|
|
7
|
+
getActivePort,
|
|
8
|
+
isLanAllowedApiPath,
|
|
9
|
+
isLanTeamMode,
|
|
10
|
+
isLocalHostname,
|
|
11
|
+
isLocalOrigin,
|
|
12
|
+
isLocalRequest,
|
|
13
|
+
parseBody,
|
|
14
|
+
parseHostnameFromHostHeader,
|
|
15
|
+
registerWSRoute,
|
|
16
|
+
resolveBrowserHost,
|
|
17
|
+
sendError,
|
|
18
|
+
sendJSON,
|
|
19
|
+
setActivePort
|
|
20
|
+
} from "./chunk-AUHU7ALH.js";
|
|
21
|
+
import "./chunk-2LJ2DVEB.js";
|
|
22
|
+
import "./chunk-6OL3GA3P.js";
|
|
23
|
+
import "./chunk-XOS6HPEF.js";
|
|
24
|
+
import "./chunk-XDRCBMZZ.js";
|
|
25
|
+
import "./chunk-MV4TTRYX.js";
|
|
26
|
+
import "./chunk-IXOIOGR5.js";
|
|
27
|
+
import "./chunk-KRPOPWGA.js";
|
|
28
|
+
import "./chunk-GU2FZQ6A.js";
|
|
29
|
+
import "./chunk-R3GPQC7I.js";
|
|
30
|
+
import "./chunk-BE46C7JW.js";
|
|
31
|
+
import "./chunk-RNG3K465.js";
|
|
32
|
+
import "./chunk-43OLRXM5.js";
|
|
33
|
+
import "./chunk-GOOTEPBK.js";
|
|
34
|
+
import "./chunk-B6A2AKLN.js";
|
|
35
|
+
import "./chunk-V5UHPPSY.js";
|
|
36
|
+
import "./chunk-WHLVZCQY.js";
|
|
37
|
+
import "./chunk-TGTYKBGC.js";
|
|
38
|
+
export {
|
|
39
|
+
buildWebServer,
|
|
40
|
+
canAccessApiPath,
|
|
41
|
+
canAccessWebSocketPath,
|
|
42
|
+
createWebServer,
|
|
43
|
+
createWebServerAutoPort,
|
|
44
|
+
getActivePort,
|
|
45
|
+
isLanAllowedApiPath,
|
|
46
|
+
isLanTeamMode,
|
|
47
|
+
isLocalHostname,
|
|
48
|
+
isLocalOrigin,
|
|
49
|
+
isLocalRequest,
|
|
50
|
+
parseBody,
|
|
51
|
+
parseHostnameFromHostHeader,
|
|
52
|
+
registerWSRoute,
|
|
53
|
+
resolveBrowserHost,
|
|
54
|
+
sendError,
|
|
55
|
+
sendJSON,
|
|
56
|
+
setActivePort
|
|
57
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deleteSession,
|
|
3
|
+
exportSession,
|
|
4
|
+
forkSession,
|
|
5
|
+
generateSessionId,
|
|
6
|
+
listSessions,
|
|
7
|
+
loadSession,
|
|
8
|
+
renameSession,
|
|
9
|
+
saveSession
|
|
10
|
+
} from "./chunk-XOS6HPEF.js";
|
|
11
|
+
import "./chunk-V5UHPPSY.js";
|
|
12
|
+
export {
|
|
13
|
+
deleteSession,
|
|
14
|
+
exportSession,
|
|
15
|
+
forkSession,
|
|
16
|
+
generateSessionId,
|
|
17
|
+
listSessions,
|
|
18
|
+
loadSession,
|
|
19
|
+
renameSession,
|
|
20
|
+
saveSession
|
|
21
|
+
};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runSubAgent
|
|
3
|
+
} from "./chunk-QTSLP47C.js";
|
|
4
|
+
import {
|
|
5
|
+
renderMarkdown
|
|
6
|
+
} from "./chunk-GH7E2OJE.js";
|
|
7
|
+
import "./chunk-GU2FZQ6A.js";
|
|
8
|
+
import "./chunk-BE46C7JW.js";
|
|
9
|
+
import {
|
|
10
|
+
HYPERCORE_DIR
|
|
11
|
+
} from "./chunk-V5UHPPSY.js";
|
|
12
|
+
|
|
13
|
+
// src/repl/skills.ts
|
|
14
|
+
import { existsSync } from "fs";
|
|
15
|
+
import { readFile, readdir } from "fs/promises";
|
|
16
|
+
import { join } from "path";
|
|
17
|
+
import chalk from "chalk";
|
|
18
|
+
function parseSkillMd(content) {
|
|
19
|
+
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n([\s\S]*)/);
|
|
20
|
+
if (!fmMatch) return null;
|
|
21
|
+
const [, frontmatter, body] = fmMatch;
|
|
22
|
+
const meta = {};
|
|
23
|
+
for (const line of frontmatter.split("\n")) {
|
|
24
|
+
const colonIdx = line.indexOf(":");
|
|
25
|
+
if (colonIdx === -1) continue;
|
|
26
|
+
const key = line.slice(0, colonIdx).trim().toLowerCase();
|
|
27
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
28
|
+
switch (key) {
|
|
29
|
+
case "name":
|
|
30
|
+
meta.name = value;
|
|
31
|
+
break;
|
|
32
|
+
case "description":
|
|
33
|
+
meta.description = value;
|
|
34
|
+
break;
|
|
35
|
+
case "aliases":
|
|
36
|
+
meta.aliases = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
37
|
+
break;
|
|
38
|
+
case "tools":
|
|
39
|
+
meta.tools = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
40
|
+
break;
|
|
41
|
+
case "type":
|
|
42
|
+
meta.type = value;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!meta.name) return null;
|
|
47
|
+
let systemPrompt = "";
|
|
48
|
+
let taskTemplate = "";
|
|
49
|
+
const sections = body.split(/^##\s+/m);
|
|
50
|
+
for (const section of sections) {
|
|
51
|
+
const firstLine = section.split("\n")[0]?.trim().toLowerCase() || "";
|
|
52
|
+
const sectionBody = section.split("\n").slice(1).join("\n").trim();
|
|
53
|
+
if (firstLine.includes("\u7CFB\u7EDF\u63D0\u793A") || firstLine.includes("system")) {
|
|
54
|
+
systemPrompt = sectionBody;
|
|
55
|
+
} else if (firstLine.includes("\u4EFB\u52A1\u6A21\u677F") || firstLine.includes("task") || firstLine.includes("template")) {
|
|
56
|
+
taskTemplate = sectionBody;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!taskTemplate && !systemPrompt) {
|
|
60
|
+
taskTemplate = body.trim();
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
meta: {
|
|
64
|
+
name: meta.name,
|
|
65
|
+
description: meta.description || `\u6280\u80FD: ${meta.name}`,
|
|
66
|
+
aliases: meta.aliases,
|
|
67
|
+
tools: meta.tools,
|
|
68
|
+
type: meta.type || "general"
|
|
69
|
+
},
|
|
70
|
+
systemPrompt,
|
|
71
|
+
taskTemplate
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async function loadFromDir(dir) {
|
|
75
|
+
if (!existsSync(dir)) return [];
|
|
76
|
+
const files = await readdir(dir);
|
|
77
|
+
const results = [];
|
|
78
|
+
for (const file of files) {
|
|
79
|
+
if (!file.endsWith(".skill.md")) continue;
|
|
80
|
+
try {
|
|
81
|
+
const content = await readFile(join(dir, file), "utf-8");
|
|
82
|
+
const parsed = parseSkillMd(content);
|
|
83
|
+
if (parsed) results.push(parsed);
|
|
84
|
+
} catch {
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return results;
|
|
88
|
+
}
|
|
89
|
+
async function loadSkills() {
|
|
90
|
+
const commands = [];
|
|
91
|
+
const systemDir = join(HYPERCORE_DIR, "skills");
|
|
92
|
+
const systemSkills = await loadFromDir(systemDir);
|
|
93
|
+
const projectDir = join(process.cwd(), ".hypercore", "skills");
|
|
94
|
+
const projectSkills = await loadFromDir(projectDir);
|
|
95
|
+
const all = [...systemSkills, ...projectSkills];
|
|
96
|
+
const seen = /* @__PURE__ */ new Set();
|
|
97
|
+
for (const skill of all.reverse()) {
|
|
98
|
+
if (seen.has(skill.meta.name)) continue;
|
|
99
|
+
seen.add(skill.meta.name);
|
|
100
|
+
commands.push({
|
|
101
|
+
name: skill.meta.name,
|
|
102
|
+
aliases: skill.meta.aliases,
|
|
103
|
+
description: `[\u6280\u80FD] ${skill.meta.description}`,
|
|
104
|
+
category: "util",
|
|
105
|
+
usage: skill.taskTemplate ? `/${skill.meta.name} <\u53C2\u6570>` : void 0,
|
|
106
|
+
handler: createSkillHandler(skill)
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return commands;
|
|
110
|
+
}
|
|
111
|
+
async function listAvailableSkills() {
|
|
112
|
+
const results = [];
|
|
113
|
+
const systemDir = join(HYPERCORE_DIR, "skills");
|
|
114
|
+
const projectDir = join(process.cwd(), ".hypercore", "skills");
|
|
115
|
+
const systemSkills = await loadFromDir(systemDir);
|
|
116
|
+
for (const s of systemSkills) {
|
|
117
|
+
results.push({ ...s.meta, source: "\u7CFB\u7EDF\u7EA7" });
|
|
118
|
+
}
|
|
119
|
+
const projectSkills = await loadFromDir(projectDir);
|
|
120
|
+
for (const s of projectSkills) {
|
|
121
|
+
results.push({ ...s.meta, source: "\u9879\u76EE\u7EA7" });
|
|
122
|
+
}
|
|
123
|
+
return results;
|
|
124
|
+
}
|
|
125
|
+
function createSkillHandler(skill) {
|
|
126
|
+
return async (args, ctx) => {
|
|
127
|
+
const argsStr = args.join(" ");
|
|
128
|
+
const rawTemplate = skill.taskTemplate || skill.meta.description;
|
|
129
|
+
const requiresArgs = rawTemplate.includes("$ARGS");
|
|
130
|
+
if (!argsStr && requiresArgs) {
|
|
131
|
+
console.log(chalk.dim("\n \u8BE5\u6280\u80FD\u9700\u8981\u53C2\u6570"));
|
|
132
|
+
console.log(chalk.dim(` \u7528\u6CD5: /${skill.meta.name} <\u53C2\u6570>`));
|
|
133
|
+
console.log();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
let taskDescription = rawTemplate;
|
|
137
|
+
taskDescription = taskDescription.replace(/\$ARGS/g, argsStr).replace(/\$CWD/g, process.cwd()).replace(/\$MODEL/g, ctx.config.modelConfig.model).replace(/\$SESSION/g, ctx.sessionId);
|
|
138
|
+
console.log(chalk.bold(`
|
|
139
|
+
\u{1F3AF} \u6280\u80FD: ${skill.meta.name} [${skill.meta.type || "general"}]
|
|
140
|
+
`));
|
|
141
|
+
const task = {
|
|
142
|
+
description: taskDescription,
|
|
143
|
+
type: skill.meta.type || "general",
|
|
144
|
+
systemPrompt: skill.systemPrompt || void 0,
|
|
145
|
+
allowedTools: skill.meta.tools
|
|
146
|
+
};
|
|
147
|
+
const result = await runSubAgent(
|
|
148
|
+
task,
|
|
149
|
+
ctx.getClient(),
|
|
150
|
+
ctx.config,
|
|
151
|
+
ctx.tools,
|
|
152
|
+
ctx.systemPrompt
|
|
153
|
+
);
|
|
154
|
+
console.log();
|
|
155
|
+
if (result.output && result.output !== "[\u5B50\u4EE3\u7406\u8D85\u65F6]") {
|
|
156
|
+
console.log(chalk.dim(" \u2500\u2500\u2500"));
|
|
157
|
+
const rendered = renderMarkdown(result.output);
|
|
158
|
+
process.stdout.write(rendered);
|
|
159
|
+
}
|
|
160
|
+
console.log(chalk.dim(`
|
|
161
|
+
\u6280\u80FD\u5B8C\u6210: ${(result.elapsed / 1e3).toFixed(1)}s | ${result.toolCalls.length} \u6B21\u5DE5\u5177 | ${result.tokenUsage.inputTokens + result.tokenUsage.outputTokens} tokens`));
|
|
162
|
+
if (result.timedOut) {
|
|
163
|
+
console.log(chalk.yellow(" \u26A0\uFE0F \u5B50\u4EE3\u7406\u8D85\u65F6"));
|
|
164
|
+
}
|
|
165
|
+
console.log();
|
|
166
|
+
ctx.sessionTokens.inputTokens += result.tokenUsage.inputTokens;
|
|
167
|
+
ctx.sessionTokens.outputTokens += result.tokenUsage.outputTokens;
|
|
168
|
+
ctx.chatHistory.push({ role: "user", content: `[\u6280\u80FD: ${skill.meta.name}] ${taskDescription}` });
|
|
169
|
+
ctx.chatHistory.push({ role: "assistant", content: result.output });
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
listAvailableSkills,
|
|
174
|
+
loadSkills
|
|
175
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addMemory,
|
|
3
|
+
generateMemoryId,
|
|
4
|
+
getMemoryStats,
|
|
5
|
+
listMemories,
|
|
6
|
+
loadStore,
|
|
7
|
+
markExtraction,
|
|
8
|
+
readMemoryMarkdown,
|
|
9
|
+
removeMemory,
|
|
10
|
+
saveStore,
|
|
11
|
+
searchMemories
|
|
12
|
+
} from "./chunk-KRPOPWGA.js";
|
|
13
|
+
import "./chunk-V5UHPPSY.js";
|
|
14
|
+
export {
|
|
15
|
+
addMemory,
|
|
16
|
+
generateMemoryId,
|
|
17
|
+
getMemoryStats,
|
|
18
|
+
listMemories,
|
|
19
|
+
loadStore,
|
|
20
|
+
markExtraction,
|
|
21
|
+
readMemoryMarkdown,
|
|
22
|
+
removeMemory,
|
|
23
|
+
saveStore,
|
|
24
|
+
searchMemories
|
|
25
|
+
};
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createTeam
|
|
3
|
+
} from "./chunk-6OL3GA3P.js";
|
|
4
|
+
import {
|
|
5
|
+
clearLocalToken,
|
|
6
|
+
loadLocalToken,
|
|
7
|
+
saveLocalToken
|
|
8
|
+
} from "./chunk-XDRCBMZZ.js";
|
|
9
|
+
import {
|
|
10
|
+
showError,
|
|
11
|
+
showTaskList,
|
|
12
|
+
showTeamBanner,
|
|
13
|
+
showTeamStatus
|
|
14
|
+
} from "./chunk-R3GPQC7I.js";
|
|
15
|
+
import "./chunk-BE46C7JW.js";
|
|
16
|
+
import "./chunk-RNG3K465.js";
|
|
17
|
+
import "./chunk-V5UHPPSY.js";
|
|
18
|
+
|
|
19
|
+
// src/commands/team.ts
|
|
20
|
+
import chalk from "chalk";
|
|
21
|
+
import { input as inquirerInput, confirm } from "@inquirer/prompts";
|
|
22
|
+
import WebSocket from "ws";
|
|
23
|
+
import { networkInterfaces } from "os";
|
|
24
|
+
function getLocalIP() {
|
|
25
|
+
try {
|
|
26
|
+
const nets = networkInterfaces();
|
|
27
|
+
for (const name of Object.keys(nets)) {
|
|
28
|
+
for (const net of nets[name] || []) {
|
|
29
|
+
if (net.family === "IPv4" && !net.internal) {
|
|
30
|
+
return net.address;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
return "localhost";
|
|
37
|
+
}
|
|
38
|
+
async function connectWS(token) {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
const wsUrl = token.serverUrl.replace(/^http/, "ws") + "/ws/team";
|
|
41
|
+
const ws = new WebSocket(wsUrl);
|
|
42
|
+
const timeout = setTimeout(() => {
|
|
43
|
+
ws.close();
|
|
44
|
+
reject(new Error("\u8FDE\u63A5\u8D85\u65F6"));
|
|
45
|
+
}, 1e4);
|
|
46
|
+
ws.on("open", () => {
|
|
47
|
+
ws.send(JSON.stringify({
|
|
48
|
+
type: "auth",
|
|
49
|
+
payload: { teamId: token.teamId, token: token.token },
|
|
50
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
51
|
+
}));
|
|
52
|
+
});
|
|
53
|
+
ws.on("message", (data) => {
|
|
54
|
+
const msg = JSON.parse(data.toString());
|
|
55
|
+
if (msg.type === "auth_ok") {
|
|
56
|
+
clearTimeout(timeout);
|
|
57
|
+
resolve(ws);
|
|
58
|
+
} else if (msg.type === "auth_fail") {
|
|
59
|
+
clearTimeout(timeout);
|
|
60
|
+
ws.close();
|
|
61
|
+
reject(new Error(`\u8BA4\u8BC1\u5931\u8D25: ${msg.payload.reason}`));
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
ws.on("error", (err) => {
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
reject(err);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function teamCreateCommand(teamName, options) {
|
|
71
|
+
const ownerName = await inquirerInput({
|
|
72
|
+
message: "\u{1F464} \u4F60\u7684\u6635\u79F0\uFF1A",
|
|
73
|
+
default: process.env.USER || "owner"
|
|
74
|
+
});
|
|
75
|
+
const port = parseInt(options.port || "3210", 10);
|
|
76
|
+
const { team, ownerToken } = await createTeam(teamName, ownerName);
|
|
77
|
+
const localIP = getLocalIP();
|
|
78
|
+
const serverUrl = `http://${localIP}:${port}`;
|
|
79
|
+
await saveLocalToken({
|
|
80
|
+
teamId: team.id,
|
|
81
|
+
memberId: team.members[0].id,
|
|
82
|
+
memberName: ownerName,
|
|
83
|
+
token: ownerToken,
|
|
84
|
+
serverUrl
|
|
85
|
+
});
|
|
86
|
+
showTeamBanner();
|
|
87
|
+
console.log();
|
|
88
|
+
console.log(chalk.bold(` \u2705 \u56E2\u961F "${teamName}" \u5DF2\u521B\u5EFA`));
|
|
89
|
+
console.log();
|
|
90
|
+
console.log(` ${chalk.dim("\u52A0\u5165\u7801:")} ${chalk.bold.cyan(team.joinCode)}`);
|
|
91
|
+
console.log(` ${chalk.dim("\u56E2\u961FID:")} ${chalk.white(team.id)}`);
|
|
92
|
+
console.log(` ${chalk.dim("\u5C40\u57DF\u7F51:")} ${chalk.white(serverUrl)}`);
|
|
93
|
+
console.log();
|
|
94
|
+
console.log(chalk.dim(" \u2500\u2500 \u961F\u53CB\u52A0\u5165\uFF08\u590D\u5236\u53D1\u7ED9\u961F\u53CB\uFF09\u2500\u2500"));
|
|
95
|
+
console.log();
|
|
96
|
+
console.log(chalk.cyan(` hypercore team join ${team.joinCode} --server ${serverUrl}`));
|
|
97
|
+
console.log();
|
|
98
|
+
console.log(chalk.dim(" \u2500\u2500 \u542F\u52A8\u56E2\u961F\u670D\u52A1 \u2500\u2500"));
|
|
99
|
+
console.log();
|
|
100
|
+
console.log(chalk.dim(" \u65B9\u5F0F\u4E00\uFF08\u63A8\u8350\uFF09\uFF1AREPL + LAN \u4E00\u4F53\u5316"));
|
|
101
|
+
console.log(chalk.cyan(` hypercore --host 0.0.0.0`));
|
|
102
|
+
console.log();
|
|
103
|
+
console.log(chalk.dim(" \u65B9\u5F0F\u4E8C\uFF1A\u4EC5\u542F\u52A8 Web Dashboard"));
|
|
104
|
+
console.log(chalk.cyan(` hypercore web --port ${port} --host 0.0.0.0`));
|
|
105
|
+
console.log();
|
|
106
|
+
}
|
|
107
|
+
async function teamJoinCommand(joinCode, options) {
|
|
108
|
+
const memberName = await inquirerInput({
|
|
109
|
+
message: "\u{1F464} \u4F60\u7684\u6635\u79F0\uFF1A",
|
|
110
|
+
default: process.env.USER || "member"
|
|
111
|
+
});
|
|
112
|
+
const serverUrl = options.server || "http://localhost:3210";
|
|
113
|
+
try {
|
|
114
|
+
const resp = await fetch(`${serverUrl}/api/team/join`, {
|
|
115
|
+
method: "POST",
|
|
116
|
+
headers: { "Content-Type": "application/json" },
|
|
117
|
+
body: JSON.stringify({ joinCode: joinCode.toUpperCase(), memberName })
|
|
118
|
+
});
|
|
119
|
+
if (!resp.ok) {
|
|
120
|
+
const err = await resp.json();
|
|
121
|
+
showError(err.error || "\u52A0\u5165\u5931\u8D25");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const data = await resp.json();
|
|
125
|
+
await saveLocalToken({
|
|
126
|
+
teamId: data.team.id,
|
|
127
|
+
memberId: data.member.id,
|
|
128
|
+
memberName,
|
|
129
|
+
token: data.token,
|
|
130
|
+
serverUrl
|
|
131
|
+
});
|
|
132
|
+
showTeamBanner();
|
|
133
|
+
console.log();
|
|
134
|
+
console.log(chalk.bold(` \u2705 \u5DF2\u52A0\u5165\u56E2\u961F "${data.team.name}"`));
|
|
135
|
+
console.log(chalk.dim(` \u8EAB\u4EFD: ${memberName} (${data.member.id})`));
|
|
136
|
+
console.log();
|
|
137
|
+
} catch (err) {
|
|
138
|
+
showError(`\u65E0\u6CD5\u8FDE\u63A5\u670D\u52A1\u5668 ${serverUrl}: ${err instanceof Error ? err.message : String(err)}`);
|
|
139
|
+
console.log(chalk.dim(" \u8BF7\u68C0\u67E5\uFF1A"));
|
|
140
|
+
console.log(chalk.dim(" 1. \u56E2\u961F\u521B\u5EFA\u8005\u662F\u5426\u5DF2\u542F\u52A8\u670D\u52A1\uFF1F\uFF08hypercore --host 0.0.0.0\uFF09"));
|
|
141
|
+
console.log(chalk.dim(" 2. \u662F\u5426\u5728\u540C\u4E00\u5C40\u57DF\u7F51\uFF1F"));
|
|
142
|
+
console.log(chalk.dim(" 3. \u670D\u52A1\u5668\u5730\u5740\u662F\u5426\u6B63\u786E\uFF1F\u4F7F\u7528 --server http://<IP>:<\u7AEF\u53E3> \u6307\u5B9A"));
|
|
143
|
+
console.log(chalk.dim(` \u5F53\u524D\u8FDE\u63A5: ${serverUrl}`));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async function teamStatusCommand() {
|
|
147
|
+
const token = await loadLocalToken();
|
|
148
|
+
if (!token) {
|
|
149
|
+
showError("\u672A\u52A0\u5165\u4EFB\u4F55\u56E2\u961F\u3002\u8BF7\u5148 hyper team create \u6216 hyper team join");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const resp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/status`, {
|
|
154
|
+
headers: { "Authorization": `Bearer ${token.token}` }
|
|
155
|
+
});
|
|
156
|
+
if (!resp.ok) {
|
|
157
|
+
const err = await resp.json();
|
|
158
|
+
showError(err.error || "\u83B7\u53D6\u72B6\u6001\u5931\u8D25");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const data = await resp.json();
|
|
162
|
+
showTeamStatus(data.team, data.members, token);
|
|
163
|
+
} catch (err) {
|
|
164
|
+
showError(`\u65E0\u6CD5\u8FDE\u63A5\u670D\u52A1\u5668: ${err instanceof Error ? err.message : String(err)}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function teamTaskAddCommand(title, options) {
|
|
168
|
+
const token = await loadLocalToken();
|
|
169
|
+
if (!token) {
|
|
170
|
+
showError("\u672A\u52A0\u5165\u4EFB\u4F55\u56E2\u961F");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
const resp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/tasks`, {
|
|
175
|
+
method: "POST",
|
|
176
|
+
headers: {
|
|
177
|
+
"Content-Type": "application/json",
|
|
178
|
+
"Authorization": `Bearer ${token.token}`
|
|
179
|
+
},
|
|
180
|
+
body: JSON.stringify({
|
|
181
|
+
title,
|
|
182
|
+
priority: options.priority || "B",
|
|
183
|
+
assignee: options.assignee,
|
|
184
|
+
description: options.description
|
|
185
|
+
})
|
|
186
|
+
});
|
|
187
|
+
if (!resp.ok) {
|
|
188
|
+
const err = await resp.json();
|
|
189
|
+
showError(err.error);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const data = await resp.json();
|
|
193
|
+
console.log(chalk.green(`
|
|
194
|
+
\u2705 \u4EFB\u52A1 #${data.task.id} \u5DF2\u521B\u5EFA: ${data.task.title}
|
|
195
|
+
`));
|
|
196
|
+
} catch (err) {
|
|
197
|
+
showError(`\u8BF7\u6C42\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function teamTaskListCommand() {
|
|
201
|
+
const token = await loadLocalToken();
|
|
202
|
+
if (!token) {
|
|
203
|
+
showError("\u672A\u52A0\u5165\u4EFB\u4F55\u56E2\u961F");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
const resp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/tasks`, {
|
|
208
|
+
headers: { "Authorization": `Bearer ${token.token}` }
|
|
209
|
+
});
|
|
210
|
+
if (!resp.ok) {
|
|
211
|
+
const err = await resp.json();
|
|
212
|
+
showError(err.error);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const data = await resp.json();
|
|
216
|
+
showTaskList(data.tasks);
|
|
217
|
+
} catch (err) {
|
|
218
|
+
showError(`\u8BF7\u6C42\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async function teamTaskAssignCommand(taskId, memberName) {
|
|
222
|
+
const token = await loadLocalToken();
|
|
223
|
+
if (!token) {
|
|
224
|
+
showError("\u672A\u52A0\u5165\u4EFB\u4F55\u56E2\u961F");
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
const statusResp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/status`, {
|
|
229
|
+
headers: { "Authorization": `Bearer ${token.token}` }
|
|
230
|
+
});
|
|
231
|
+
const statusData = await statusResp.json();
|
|
232
|
+
const target = statusData.members.find(
|
|
233
|
+
(m) => m.name === memberName || m.id === memberName
|
|
234
|
+
);
|
|
235
|
+
if (!target) {
|
|
236
|
+
showError(`\u672A\u627E\u5230\u6210\u5458: ${memberName}`);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const resp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/tasks/${taskId}`, {
|
|
240
|
+
method: "PUT",
|
|
241
|
+
headers: {
|
|
242
|
+
"Content-Type": "application/json",
|
|
243
|
+
"Authorization": `Bearer ${token.token}`
|
|
244
|
+
},
|
|
245
|
+
body: JSON.stringify({ assignee: target.id, status: "doing" })
|
|
246
|
+
});
|
|
247
|
+
if (!resp.ok) {
|
|
248
|
+
const err = await resp.json();
|
|
249
|
+
showError(err.error);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
console.log(chalk.green(`
|
|
253
|
+
\u2705 \u4EFB\u52A1 #${taskId} \u5DF2\u5206\u914D\u7ED9 ${target.name}
|
|
254
|
+
`));
|
|
255
|
+
} catch (err) {
|
|
256
|
+
showError(`\u8BF7\u6C42\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function teamTaskDoneCommand(taskId) {
|
|
260
|
+
const token = await loadLocalToken();
|
|
261
|
+
if (!token) {
|
|
262
|
+
showError("\u672A\u52A0\u5165\u4EFB\u4F55\u56E2\u961F");
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
const resp = await fetch(`${token.serverUrl}/api/team/${token.teamId}/tasks/${taskId}`, {
|
|
267
|
+
method: "PUT",
|
|
268
|
+
headers: {
|
|
269
|
+
"Content-Type": "application/json",
|
|
270
|
+
"Authorization": `Bearer ${token.token}`
|
|
271
|
+
},
|
|
272
|
+
body: JSON.stringify({ status: "done" })
|
|
273
|
+
});
|
|
274
|
+
if (!resp.ok) {
|
|
275
|
+
const err = await resp.json();
|
|
276
|
+
showError(err.error);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
console.log(chalk.green(`
|
|
280
|
+
\u2705 \u4EFB\u52A1 #${taskId} \u5DF2\u5B8C\u6210
|
|
281
|
+
`));
|
|
282
|
+
} catch (err) {
|
|
283
|
+
showError(`\u8BF7\u6C42\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
async function teamLeaveCommand() {
|
|
287
|
+
const token = await loadLocalToken();
|
|
288
|
+
if (!token) {
|
|
289
|
+
showError("\u672A\u52A0\u5165\u4EFB\u4F55\u56E2\u961F");
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
const yes = await confirm({
|
|
293
|
+
message: `\u786E\u8BA4\u79BB\u5F00\u56E2\u961F\uFF1F`,
|
|
294
|
+
default: false
|
|
295
|
+
});
|
|
296
|
+
if (yes) {
|
|
297
|
+
await clearLocalToken();
|
|
298
|
+
console.log(chalk.dim("\n \u5DF2\u79BB\u5F00\u56E2\u961F\n"));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
async function teamChatCommand() {
|
|
302
|
+
const token = await loadLocalToken();
|
|
303
|
+
if (!token) {
|
|
304
|
+
showError("\u672A\u52A0\u5165\u4EFB\u4F55\u56E2\u961F");
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
console.log(chalk.dim("\n \u6B63\u5728\u8FDE\u63A5\u56E2\u961F\u804A\u5929\u2026"));
|
|
308
|
+
let ws;
|
|
309
|
+
try {
|
|
310
|
+
ws = await connectWS(token);
|
|
311
|
+
} catch (err) {
|
|
312
|
+
showError(`\u8FDE\u63A5\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
console.log(chalk.green(" \u2705 \u5DF2\u8FDE\u63A5\u56E2\u961F\u804A\u5929"));
|
|
316
|
+
console.log(chalk.dim(" \u8F93\u5165\u6D88\u606F\u53D1\u9001\uFF0CCtrl+C \u9000\u51FA\n"));
|
|
317
|
+
ws.on("message", (data) => {
|
|
318
|
+
const msg = JSON.parse(data.toString());
|
|
319
|
+
switch (msg.type) {
|
|
320
|
+
case "chat_message": {
|
|
321
|
+
const { senderName, content, senderId } = msg.payload;
|
|
322
|
+
if (senderId !== token.memberId) {
|
|
323
|
+
console.log(` ${chalk.cyan(senderName)}: ${content}`);
|
|
324
|
+
}
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
case "chat_ai_text": {
|
|
328
|
+
const { text } = msg.payload;
|
|
329
|
+
process.stdout.write(chalk.dim(text));
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
case "chat_ai_done":
|
|
333
|
+
console.log();
|
|
334
|
+
break;
|
|
335
|
+
case "member_joined": {
|
|
336
|
+
const { memberName } = msg.payload;
|
|
337
|
+
console.log(chalk.dim(` \u2192 ${memberName} \u52A0\u5165\u4E86\u804A\u5929`));
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
case "member_left": {
|
|
341
|
+
const { memberName } = msg.payload;
|
|
342
|
+
console.log(chalk.dim(` \u2190 ${memberName} \u79BB\u5F00\u4E86\u804A\u5929`));
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
ws.on("close", () => {
|
|
348
|
+
console.log(chalk.dim("\n \u8FDE\u63A5\u5DF2\u65AD\u5F00"));
|
|
349
|
+
process.exit(0);
|
|
350
|
+
});
|
|
351
|
+
const readline = await import("readline");
|
|
352
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
353
|
+
const promptChat = () => {
|
|
354
|
+
rl.question(chalk.dim(" > "), (input) => {
|
|
355
|
+
if (!input.trim()) {
|
|
356
|
+
promptChat();
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (input.trim() === "/quit" || input.trim() === "/exit") {
|
|
360
|
+
ws.close();
|
|
361
|
+
rl.close();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
ws.send(JSON.stringify({
|
|
365
|
+
type: "chat_message",
|
|
366
|
+
payload: { content: input.trim() },
|
|
367
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
368
|
+
}));
|
|
369
|
+
console.log(` ${chalk.cyan(token.memberName)}: ${input.trim()}`);
|
|
370
|
+
promptChat();
|
|
371
|
+
});
|
|
372
|
+
};
|
|
373
|
+
promptChat();
|
|
374
|
+
}
|
|
375
|
+
export {
|
|
376
|
+
teamChatCommand,
|
|
377
|
+
teamCreateCommand,
|
|
378
|
+
teamJoinCommand,
|
|
379
|
+
teamLeaveCommand,
|
|
380
|
+
teamStatusCommand,
|
|
381
|
+
teamTaskAddCommand,
|
|
382
|
+
teamTaskAssignCommand,
|
|
383
|
+
teamTaskDoneCommand,
|
|
384
|
+
teamTaskListCommand
|
|
385
|
+
};
|