hocai-connect 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +185 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -29147,6 +29147,96 @@ var StdioServerTransport = class {
|
|
|
29147
29147
|
}
|
|
29148
29148
|
};
|
|
29149
29149
|
|
|
29150
|
+
// apps/mcp/src/daemon.ts
|
|
29151
|
+
var LABEL_MAC = "vn.hocai.connect";
|
|
29152
|
+
var TASK_NAME = "hocai-connect";
|
|
29153
|
+
function daemonPlan(platform2, o) {
|
|
29154
|
+
const log = `${o.home}/.hocai/log/connect.log`;
|
|
29155
|
+
if (platform2 === "darwin") {
|
|
29156
|
+
return {
|
|
29157
|
+
label: LABEL_MAC,
|
|
29158
|
+
file: `${o.home}/Library/LaunchAgents/${LABEL_MAC}.plist`,
|
|
29159
|
+
// `KeepAlive` để launchd dựng lại khi tiến trình sập; `RunAtLoad` để nó
|
|
29160
|
+
// lên ngay lúc đăng nhập, không đợi ai gọi.
|
|
29161
|
+
content: `<?xml version="1.0" encoding="UTF-8"?>
|
|
29162
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
29163
|
+
<plist version="1.0">
|
|
29164
|
+
<dict>
|
|
29165
|
+
<key>Label</key><string>${LABEL_MAC}</string>
|
|
29166
|
+
<key>ProgramArguments</key>
|
|
29167
|
+
<array>
|
|
29168
|
+
<string>${o.node}</string>
|
|
29169
|
+
<string>${o.script}</string>
|
|
29170
|
+
<string>run</string>
|
|
29171
|
+
</array>
|
|
29172
|
+
<key>RunAtLoad</key><true/>
|
|
29173
|
+
<key>KeepAlive</key><true/>
|
|
29174
|
+
<key>StandardOutPath</key><string>${log}</string>
|
|
29175
|
+
<key>StandardErrorPath</key><string>${log}</string>
|
|
29176
|
+
</dict>
|
|
29177
|
+
</plist>
|
|
29178
|
+
`,
|
|
29179
|
+
// `bootout` trước `bootstrap`: nạp đè lên một nhãn đang chạy thì launchd
|
|
29180
|
+
// từ chối, và người dùng nhận "Load failed: 5: Input/output error".
|
|
29181
|
+
install: [
|
|
29182
|
+
["launchctl", "bootout", `gui/${process.getuid?.() ?? 501}/${LABEL_MAC}`],
|
|
29183
|
+
["launchctl", "bootstrap", `gui/${process.getuid?.() ?? 501}`, `${o.home}/Library/LaunchAgents/${LABEL_MAC}.plist`]
|
|
29184
|
+
],
|
|
29185
|
+
uninstall: [["launchctl", "bootout", `gui/${process.getuid?.() ?? 501}/${LABEL_MAC}`]],
|
|
29186
|
+
log
|
|
29187
|
+
};
|
|
29188
|
+
}
|
|
29189
|
+
if (platform2 === "linux") {
|
|
29190
|
+
return {
|
|
29191
|
+
label: TASK_NAME,
|
|
29192
|
+
file: `${o.home}/.config/systemd/user/${TASK_NAME}.service`,
|
|
29193
|
+
content: `[Unit]
|
|
29194
|
+
Description=hocAI connect \u2014 n\u1ED1i Claude tr\xEAn m\xE1y n\xE0y v\xE0o hocAI
|
|
29195
|
+
|
|
29196
|
+
[Service]
|
|
29197
|
+
ExecStart=${o.node} ${o.script} run
|
|
29198
|
+
Restart=always
|
|
29199
|
+
RestartSec=5
|
|
29200
|
+
StandardOutput=append:${log}
|
|
29201
|
+
StandardError=append:${log}
|
|
29202
|
+
|
|
29203
|
+
[Install]
|
|
29204
|
+
WantedBy=default.target
|
|
29205
|
+
`,
|
|
29206
|
+
install: [
|
|
29207
|
+
["systemctl", "--user", "daemon-reload"],
|
|
29208
|
+
["systemctl", "--user", "enable", "--now", `${TASK_NAME}.service`]
|
|
29209
|
+
],
|
|
29210
|
+
uninstall: [["systemctl", "--user", "disable", "--now", `${TASK_NAME}.service`]],
|
|
29211
|
+
log
|
|
29212
|
+
};
|
|
29213
|
+
}
|
|
29214
|
+
if (platform2 === "win32") {
|
|
29215
|
+
return {
|
|
29216
|
+
label: TASK_NAME,
|
|
29217
|
+
file: null,
|
|
29218
|
+
content: null,
|
|
29219
|
+
install: [
|
|
29220
|
+
[
|
|
29221
|
+
"schtasks",
|
|
29222
|
+
"/Create",
|
|
29223
|
+
"/F",
|
|
29224
|
+
"/SC",
|
|
29225
|
+
"ONLOGON",
|
|
29226
|
+
"/TN",
|
|
29227
|
+
TASK_NAME,
|
|
29228
|
+
"/TR",
|
|
29229
|
+
`"${o.node}" "${o.script}" run`
|
|
29230
|
+
],
|
|
29231
|
+
["schtasks", "/Run", "/TN", TASK_NAME]
|
|
29232
|
+
],
|
|
29233
|
+
uninstall: [["schtasks", "/Delete", "/F", "/TN", TASK_NAME]],
|
|
29234
|
+
log
|
|
29235
|
+
};
|
|
29236
|
+
}
|
|
29237
|
+
return { label: TASK_NAME, file: null, content: null, install: [], uninstall: [], log };
|
|
29238
|
+
}
|
|
29239
|
+
|
|
29150
29240
|
// apps/mcp/src/server.ts
|
|
29151
29241
|
var import_promises = require("node:fs/promises");
|
|
29152
29242
|
var import_node_os = require("node:os");
|
|
@@ -39587,7 +39677,7 @@ var TOOLS = {
|
|
|
39587
39677
|
],
|
|
39588
39678
|
WORK: ["Read", "Write", "Edit", "Glob", "Grep"]
|
|
39589
39679
|
};
|
|
39590
|
-
var VERSION = "0.
|
|
39680
|
+
var VERSION = "0.6.0";
|
|
39591
39681
|
function claudeArgs(job, o, port) {
|
|
39592
39682
|
const mcp = {
|
|
39593
39683
|
mcpServers: {
|
|
@@ -40074,6 +40164,9 @@ async function askPortOwner(port, origin) {
|
|
|
40074
40164
|
// apps/mcp/src/cli.ts
|
|
40075
40165
|
var HOCAI_DIR = (0, import_node_path5.join)((0, import_node_os3.homedir)(), ".hocai");
|
|
40076
40166
|
var CREDS = (0, import_node_path5.join)(HOCAI_DIR, "config.json");
|
|
40167
|
+
var APP_DIR = (0, import_node_path5.join)(HOCAI_DIR, "app");
|
|
40168
|
+
var APP_CLI = (0, import_node_path5.join)(APP_DIR, "cli.js");
|
|
40169
|
+
var LOG_DIR = (0, import_node_path5.join)(HOCAI_DIR, "log");
|
|
40077
40170
|
var WEB = () => process.env.HOCAI_WEB_URL ?? "http://103.154.62.225:8090";
|
|
40078
40171
|
var API_DEFAULT = () => process.env.HOCAI_API_URL ?? `${WEB()}/api`;
|
|
40079
40172
|
var PORT = Number(process.env.MCP_HTTP_PORT ?? 4100);
|
|
@@ -40167,6 +40260,37 @@ function claudeBin() {
|
|
|
40167
40260
|
return "claude";
|
|
40168
40261
|
}
|
|
40169
40262
|
}
|
|
40263
|
+
var plan = () => daemonPlan((0, import_node_os3.platform)(), { node: process.execPath, script: APP_CLI, home: (0, import_node_os3.homedir)() });
|
|
40264
|
+
function chay(cmd, im = false) {
|
|
40265
|
+
try {
|
|
40266
|
+
(0, import_node_child_process3.execFileSync)(cmd[0], cmd.slice(1), { stdio: "ignore", shell: (0, import_node_os3.platform)() === "win32" });
|
|
40267
|
+
return true;
|
|
40268
|
+
} catch {
|
|
40269
|
+
if (!im) return false;
|
|
40270
|
+
return false;
|
|
40271
|
+
}
|
|
40272
|
+
}
|
|
40273
|
+
function caiDichVu() {
|
|
40274
|
+
const p = plan();
|
|
40275
|
+
if (p.install.length === 0) {
|
|
40276
|
+
say("\xB7 H\u1EC7 \u0111i\u1EC1u h\xE0nh n\xE0y ch\u01B0a h\u1ED7 tr\u1EE3 ch\u1EA1y \u1EA9n. D\xF9ng `npx hocai-connect run` v\xE0 \u0111\u1EC3 c\u1EEDa s\u1ED5 m\u1EDF.");
|
|
40277
|
+
return false;
|
|
40278
|
+
}
|
|
40279
|
+
(0, import_node_fs3.mkdirSync)(APP_DIR, { recursive: true });
|
|
40280
|
+
(0, import_node_fs3.mkdirSync)(LOG_DIR, { recursive: true });
|
|
40281
|
+
(0, import_node_fs3.copyFileSync)(process.argv[1], APP_CLI);
|
|
40282
|
+
if (p.file && p.content) {
|
|
40283
|
+
(0, import_node_fs3.mkdirSync)((0, import_node_path5.dirname)(p.file), { recursive: true });
|
|
40284
|
+
(0, import_node_fs3.writeFileSync)(p.file, p.content);
|
|
40285
|
+
}
|
|
40286
|
+
p.install.forEach((c, i) => chay(c, i === 0));
|
|
40287
|
+
return true;
|
|
40288
|
+
}
|
|
40289
|
+
function goDichVu() {
|
|
40290
|
+
const p = plan();
|
|
40291
|
+
for (const c of p.uninstall) chay(c, true);
|
|
40292
|
+
if (p.file) (0, import_node_fs3.rmSync)(p.file, { force: true });
|
|
40293
|
+
}
|
|
40170
40294
|
async function main() {
|
|
40171
40295
|
const cmd = process.argv[2];
|
|
40172
40296
|
if (cmd === "mcp") {
|
|
@@ -40174,8 +40298,39 @@ async function main() {
|
|
|
40174
40298
|
return;
|
|
40175
40299
|
}
|
|
40176
40300
|
if (cmd === "quen") {
|
|
40301
|
+
goDichVu();
|
|
40177
40302
|
(0, import_node_fs3.rmSync)(CREDS, { force: true });
|
|
40178
|
-
say("\u0110\xE3
|
|
40303
|
+
say("\u0110\xE3 ng\u1EAFt k\u1EBFt n\u1ED1i v\xE0 g\u1EE1 d\u1ECBch v\u1EE5 n\u1EC1n tr\xEAn m\xE1y n\xE0y.");
|
|
40304
|
+
say("Ch\u1EA1y l\u1EA1i `npx hocai-connect` \u0111\u1EC3 k\u1EBFt n\u1ED1i l\u1EA1i.");
|
|
40305
|
+
return;
|
|
40306
|
+
}
|
|
40307
|
+
if (cmd === "stop") {
|
|
40308
|
+
goDichVu();
|
|
40309
|
+
say("\u0110\xE3 t\u1EAFt v\xE0 g\u1EE1 d\u1ECBch v\u1EE5 n\u1EC1n. Ch\xECa kho\xE1 v\u1EABn gi\u1EEF \u2014 ch\u1EA1y `npx hocai-connect` l\xE0 n\u1ED1i l\u1EA1i ngay.");
|
|
40310
|
+
return;
|
|
40311
|
+
}
|
|
40312
|
+
if (cmd === "status") {
|
|
40313
|
+
const c = loadCreds();
|
|
40314
|
+
if (!c) {
|
|
40315
|
+
say("M\xE1y n\xE0y ch\u01B0a n\u1ED1i. Ch\u1EA1y `npx hocai-connect`.");
|
|
40316
|
+
process.exit(1);
|
|
40317
|
+
}
|
|
40318
|
+
const info = await askPortOwner(PORT, c.api.replace(/\/api$/, ""));
|
|
40319
|
+
if (!info) {
|
|
40320
|
+
say(`Kh\xF4ng c\xF3 g\xEC tr\u1EA3 l\u1EDDi \u1EDF c\u1ED5ng ${PORT} \u2014 d\u1ECBch v\u1EE5 n\u1EC1n ch\u01B0a ch\u1EA1y.`);
|
|
40321
|
+
process.exit(1);
|
|
40322
|
+
}
|
|
40323
|
+
say(`\u2713 \u0110ang ch\u1EA1y \xB7 ${info.user?.ten ?? "(ch\xECa \u0111\xE3 b\u1ECB thu h\u1ED3i)"} \xB7 b\u1EA3n ${info.phienBan}`);
|
|
40324
|
+
say(` Nh\u1EADt k\xFD: ${plan().log}`);
|
|
40325
|
+
return;
|
|
40326
|
+
}
|
|
40327
|
+
if (cmd === "logs") {
|
|
40328
|
+
const f = plan().log;
|
|
40329
|
+
if (!(0, import_node_fs3.existsSync)(f)) {
|
|
40330
|
+
say(`Ch\u01B0a c\xF3 nh\u1EADt k\xFD n\xE0o \u1EDF ${f}`);
|
|
40331
|
+
return;
|
|
40332
|
+
}
|
|
40333
|
+
say((0, import_node_fs3.readFileSync)(f, "utf8").split("\n").slice(-40).join("\n"));
|
|
40179
40334
|
return;
|
|
40180
40335
|
}
|
|
40181
40336
|
const creds = loadCreds() ?? await login();
|
|
@@ -40198,6 +40353,31 @@ async function main() {
|
|
|
40198
40353
|
});
|
|
40199
40354
|
writeDesktop(creds);
|
|
40200
40355
|
addClaudeCode(creds);
|
|
40356
|
+
if (cmd !== "run") {
|
|
40357
|
+
const xong = caiDichVu();
|
|
40358
|
+
say("");
|
|
40359
|
+
say("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
40360
|
+
say(` \u2713 \u0110\xE3 n\u1ED1i m\xE1y \xB7 ${me.ten}`);
|
|
40361
|
+
if (xong) {
|
|
40362
|
+
say(" M\xE1y n\xE0y s\u1EBD T\u1EF0 n\u1ED1i l\u1EA1i m\u1ED7i l\u1EA7n b\u1EA1n b\u1EADt m\xE1y.");
|
|
40363
|
+
say(" Kh\xF4ng c\u1EA7n m\u1EDF Terminal n\u1EEFa, kh\xF4ng c\u1EA7n gi\u1EEF c\u1EEDa s\u1ED5 n\xE0o.");
|
|
40364
|
+
say("");
|
|
40365
|
+
say(" Xem tr\u1EA1ng th\xE1i: npx hocai-connect status");
|
|
40366
|
+
say(" Ng\u1EAFt k\u1EBFt n\u1ED1i: npx hocai-connect stop");
|
|
40367
|
+
}
|
|
40368
|
+
say("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
40369
|
+
if (xong) {
|
|
40370
|
+
await new Promise((r) => setTimeout(r, 2500));
|
|
40371
|
+
const info = await askPortOwner(PORT, WEB());
|
|
40372
|
+
if (!info) {
|
|
40373
|
+
say("");
|
|
40374
|
+
say("\u26A0 D\u1ECBch v\u1EE5 \u0111\xE3 c\xE0i nh\u01B0ng ch\u01B0a th\u1EA5y tr\u1EA3 l\u1EDDi \u1EDF c\u1ED5ng " + PORT + ".");
|
|
40375
|
+
say(` Xem nh\u1EADt k\xFD: npx hocai-connect logs`);
|
|
40376
|
+
process.exit(1);
|
|
40377
|
+
}
|
|
40378
|
+
}
|
|
40379
|
+
return;
|
|
40380
|
+
}
|
|
40201
40381
|
const srv = buildHttpServer({
|
|
40202
40382
|
token: creds.token,
|
|
40203
40383
|
origins: (process.env.HOCAI_WEB_ORIGINS ?? `${WEB()},http://localhost:5173,http://localhost:5174`).split(","),
|
|
@@ -40216,10 +40396,9 @@ async function main() {
|
|
|
40216
40396
|
srv.listen(PORT, "127.0.0.1", () => {
|
|
40217
40397
|
say("");
|
|
40218
40398
|
say("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
40219
|
-
say(` \u2713 \
|
|
40220
|
-
say(
|
|
40221
|
-
say(
|
|
40222
|
-
say(" \u0110\xF3ng c\u1EEDa s\u1ED5 n\xE0y (Ctrl+C) l\xE0 ng\u1EAFt k\u1EBFt n\u1ED1i.");
|
|
40399
|
+
say(` \u2713 \u0110ang ch\u1EA1y \xB7 ${me.ten}`);
|
|
40400
|
+
say(` Trang hocAI g\u1ECDi Claude tr\xEAn m\xE1y b\u1EA1n qua c\u1ED5ng ${PORT}.`);
|
|
40401
|
+
say(" (\u0110\xE2y l\xE0 ch\u1EBF \u0111\u1ED9 ti\u1EC1n c\u1EA3nh \u2014 d\u1ECBch v\u1EE5 n\u1EC1n g\u1ECDi ch\xEDnh \u0111\u01B0\u1EDDng n\xE0y.)");
|
|
40223
40402
|
say("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
40224
40403
|
});
|
|
40225
40404
|
}
|