hocai-connect 0.14.0 → 0.15.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 +293 -94
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -16657,11 +16657,11 @@ var require_websocket_server = __commonJS({
|
|
|
16657
16657
|
});
|
|
16658
16658
|
|
|
16659
16659
|
// apps/mcp/src/cli.ts
|
|
16660
|
-
var
|
|
16661
|
-
var
|
|
16660
|
+
var import_node_fs6 = require("node:fs");
|
|
16661
|
+
var import_node_os5 = require("node:os");
|
|
16662
16662
|
var import_node_path6 = require("node:path");
|
|
16663
16663
|
var import_node_crypto3 = require("node:crypto");
|
|
16664
|
-
var
|
|
16664
|
+
var import_node_child_process4 = require("node:child_process");
|
|
16665
16665
|
|
|
16666
16666
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
16667
16667
|
var import_node_process = __toESM(require("node:process"), 1);
|
|
@@ -32839,9 +32839,9 @@ function cutLogIfBig(file2, maxBytes = 1e6) {
|
|
|
32839
32839
|
} catch {
|
|
32840
32840
|
}
|
|
32841
32841
|
}
|
|
32842
|
-
function daemonPlan(
|
|
32842
|
+
function daemonPlan(platform3, o) {
|
|
32843
32843
|
const log = logPathFor(o.home);
|
|
32844
|
-
if (
|
|
32844
|
+
if (platform3 === "darwin") {
|
|
32845
32845
|
return {
|
|
32846
32846
|
label: LABEL_MAC,
|
|
32847
32847
|
file: `${o.home}/Library/LaunchAgents/${LABEL_MAC}.plist`,
|
|
@@ -32875,7 +32875,7 @@ function daemonPlan(platform2, o) {
|
|
|
32875
32875
|
log
|
|
32876
32876
|
};
|
|
32877
32877
|
}
|
|
32878
|
-
if (
|
|
32878
|
+
if (platform3 === "linux") {
|
|
32879
32879
|
return {
|
|
32880
32880
|
label: TASK_NAME,
|
|
32881
32881
|
file: `${o.home}/.config/systemd/user/${TASK_NAME}.service`,
|
|
@@ -32900,7 +32900,7 @@ WantedBy=default.target
|
|
|
32900
32900
|
log
|
|
32901
32901
|
};
|
|
32902
32902
|
}
|
|
32903
|
-
if (
|
|
32903
|
+
if (platform3 === "win32") {
|
|
32904
32904
|
return {
|
|
32905
32905
|
label: TASK_NAME,
|
|
32906
32906
|
file: null,
|
|
@@ -32927,6 +32927,9 @@ WantedBy=default.target
|
|
|
32927
32927
|
}
|
|
32928
32928
|
|
|
32929
32929
|
// apps/mcp/src/agents.ts
|
|
32930
|
+
var import_node_child_process = require("node:child_process");
|
|
32931
|
+
var import_node_fs2 = require("node:fs");
|
|
32932
|
+
var import_node_os = require("node:os");
|
|
32930
32933
|
var NHAN = { claude: "Claude Code", codex: "Codex" };
|
|
32931
32934
|
function summarizeAgents(probes) {
|
|
32932
32935
|
const dong = [];
|
|
@@ -32939,6 +32942,13 @@ function summarizeAgents(probes) {
|
|
|
32939
32942
|
continue;
|
|
32940
32943
|
}
|
|
32941
32944
|
if (p.loggedIn === false) {
|
|
32945
|
+
if (p.name === "claude" && p.envAuth) {
|
|
32946
|
+
dong.push("\xB7 Claude Code: ch\u1EA1y trong Terminal b\u1EB1ng bi\u1EBFn m\xF4i tr\u01B0\u1EDDng, nh\u01B0ng CH\u01AFA \u0111\u0103ng nh\u1EADp");
|
|
32947
|
+
canhBao.push(
|
|
32948
|
+
"Claude Code tr\xEAn m\xE1y n\xE0y l\u1EA5y quy\u1EC1n t\u1EEB bi\u1EBFn m\xF4i tr\u01B0\u1EDDng c\u1EE7a shell (ANTHROPIC_AUTH_TOKEN ho\u1EB7c ANTHROPIC_API_KEY). D\u1ECBch v\u1EE5 n\u1EC1n c\u1EE7a hocAI kh\xF4ng n\u1EA1p h\u1ED3 s\u01A1 shell n\xEAn kh\xF4ng th\u1EA5y bi\u1EBFn \u0111\xF3 \u2014 ch\u1EA1y `claude auth login` \u0111\u1EC3 b\xE0i t\u1EADp ch\u1EA1y \u0111\u01B0\u1EE3c c\u1EA3 khi b\u1EA1n \u0111\xF3ng Terminal."
|
|
32949
|
+
);
|
|
32950
|
+
continue;
|
|
32951
|
+
}
|
|
32942
32952
|
dong.push(`\xB7 ${NHAN[p.name]}: \u0111\xE3 c\xE0i, CH\u01AFA \u0111\u0103ng nh\u1EADp`);
|
|
32943
32953
|
canhBao.push(
|
|
32944
32954
|
p.name === "claude" ? "Claude Code ch\u01B0a \u0111\u0103ng nh\u1EADp. Ch\u1EA1y `claude auth login` r\u1ED3i quay l\u1EA1i \u2014 ch\u01B0a \u0111\u0103ng nh\u1EADp th\xEC b\xE0i t\u1EADp kh\xF4ng ch\u1EA1y \u0111\u01B0\u1EE3c." : "Codex ch\u01B0a \u0111\u0103ng nh\u1EADp. Ch\u1EA1y `codex login` n\u1EBFu b\u1EA1n \u0111\u1ECBnh d\xF9ng n\xF3."
|
|
@@ -32961,11 +32971,23 @@ function summarizeAgents(probes) {
|
|
|
32961
32971
|
}
|
|
32962
32972
|
return { dong, canhBao, chayDuocBai: claudeSanSang };
|
|
32963
32973
|
}
|
|
32964
|
-
function
|
|
32965
|
-
const
|
|
32974
|
+
function codexLoggedIn(io) {
|
|
32975
|
+
const tep = `${io.env.CODEX_HOME || `${io.home}/.codex`}/auth.json`;
|
|
32976
|
+
if (!io.exists(tep)) return false;
|
|
32977
|
+
const raw = io.readFile(tep);
|
|
32978
|
+
if (raw === null) return null;
|
|
32979
|
+
try {
|
|
32980
|
+
const j = JSON.parse(raw);
|
|
32981
|
+
return !!(j.tokens?.access_token || j.OPENAI_API_KEY);
|
|
32982
|
+
} catch {
|
|
32983
|
+
return null;
|
|
32984
|
+
}
|
|
32985
|
+
}
|
|
32986
|
+
function probeAgents(io) {
|
|
32987
|
+
const co = (b) => io.run("command", ["-v", b]) !== null;
|
|
32966
32988
|
const probes = [];
|
|
32967
32989
|
if (co("claude")) {
|
|
32968
|
-
const raw = run("claude", ["auth", "status"]);
|
|
32990
|
+
const raw = io.run("claude", ["auth", "status"]);
|
|
32969
32991
|
let loggedIn = null;
|
|
32970
32992
|
if (raw !== null) {
|
|
32971
32993
|
try {
|
|
@@ -32974,18 +32996,102 @@ function probeAgents(run) {
|
|
|
32974
32996
|
} catch {
|
|
32975
32997
|
}
|
|
32976
32998
|
}
|
|
32977
|
-
|
|
32999
|
+
const envAuth = !!(io.env.ANTHROPIC_AUTH_TOKEN || io.env.ANTHROPIC_API_KEY);
|
|
33000
|
+
probes.push({ name: "claude", installed: true, runnable: raw !== null, loggedIn, envAuth });
|
|
32978
33001
|
}
|
|
32979
33002
|
if (co("codex")) {
|
|
32980
|
-
const ver = run("codex", ["--version"]);
|
|
32981
|
-
probes.push({ name: "codex", installed: true, runnable: ver !== null, loggedIn:
|
|
33003
|
+
const ver = io.run("codex", ["--version"]);
|
|
33004
|
+
probes.push({ name: "codex", installed: true, runnable: ver !== null, loggedIn: codexLoggedIn(io) });
|
|
32982
33005
|
}
|
|
32983
33006
|
return probes;
|
|
32984
33007
|
}
|
|
33008
|
+
function cachedProbe(io, now, ttl = { ready: 3e5, notReady: 2e4 }) {
|
|
33009
|
+
let luc = 0;
|
|
33010
|
+
let nho = null;
|
|
33011
|
+
let han = 0;
|
|
33012
|
+
return () => {
|
|
33013
|
+
const gio = now();
|
|
33014
|
+
if (nho && gio - luc <= han) return nho;
|
|
33015
|
+
nho = probeAgents(io);
|
|
33016
|
+
luc = gio;
|
|
33017
|
+
han = summarizeAgents(nho).chayDuocBai ? ttl.ready : ttl.notReady;
|
|
33018
|
+
return nho;
|
|
33019
|
+
};
|
|
33020
|
+
}
|
|
33021
|
+
function shellRun(cmd, args, opts) {
|
|
33022
|
+
try {
|
|
33023
|
+
const dong = [cmd, ...args].join(" ");
|
|
33024
|
+
const o = {
|
|
33025
|
+
encoding: "utf8",
|
|
33026
|
+
timeout: 8e3,
|
|
33027
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
33028
|
+
cwd: opts?.cwd,
|
|
33029
|
+
env: opts?.env
|
|
33030
|
+
};
|
|
33031
|
+
return (0, import_node_os.platform)() === "win32" ? (0, import_node_child_process.execSync)(dong, o) : (0, import_node_child_process.execSync)(dong, { ...o, shell: "/bin/sh" });
|
|
33032
|
+
} catch (e) {
|
|
33033
|
+
const ra = e.stdout;
|
|
33034
|
+
const chu = typeof ra === "string" ? ra : ra?.toString("utf8");
|
|
33035
|
+
return chu && chu.trim() ? chu : null;
|
|
33036
|
+
}
|
|
33037
|
+
}
|
|
33038
|
+
function realProbeIO() {
|
|
33039
|
+
return {
|
|
33040
|
+
run: shellRun,
|
|
33041
|
+
exists: import_node_fs2.existsSync,
|
|
33042
|
+
readFile: (t) => {
|
|
33043
|
+
try {
|
|
33044
|
+
return (0, import_node_fs2.readFileSync)(t, "utf8");
|
|
33045
|
+
} catch {
|
|
33046
|
+
return null;
|
|
33047
|
+
}
|
|
33048
|
+
},
|
|
33049
|
+
env: process.env,
|
|
33050
|
+
home: (0, import_node_os.homedir)()
|
|
33051
|
+
};
|
|
33052
|
+
}
|
|
33053
|
+
|
|
33054
|
+
// apps/mcp/src/permissions.ts
|
|
33055
|
+
var GUARDED_DIRS = ["Documents", "Desktop", "Downloads"];
|
|
33056
|
+
function permPlan(platform3, o) {
|
|
33057
|
+
const notice = [];
|
|
33058
|
+
const fixCache = [];
|
|
33059
|
+
const coSudo = platform3 !== "win32";
|
|
33060
|
+
if (o.alienCacheFiles > 0 && coSudo) {
|
|
33061
|
+
notice.push(
|
|
33062
|
+
`\xB7 M\u1EADt kh\u1EA9u m\xE1y \u2014 ch\u1EC9 \u0111\u1EC3 s\u1EEDa quy\u1EC1n \xEDt nh\u1EA5t ${o.alienCacheFiles} m\u1EE5c trong ${o.cacheDir}. Kh\xF4ng s\u1EEDa th\xEC l\u1EC7nh c\u1EADp nh\u1EADt sau n\xE0y s\u1EBD h\u1ECFng. B\u1ECF qua \u0111\u01B0\u1EE3c.`
|
|
33063
|
+
);
|
|
33064
|
+
fixCache.push(["sudo", "chown", "-R", o.user, o.cacheDir]);
|
|
33065
|
+
}
|
|
33066
|
+
if (platform3 === "darwin") {
|
|
33067
|
+
notice.push("\xB7 Quy\u1EC1n th\u01B0 m\u1EE5c \u2014 n\u1EBFu macOS h\u1ECFi, b\u1EA5m Cho ph\xE9p. Kh\xF4ng h\u1ECFi th\xEC kh\xF4ng c\u1EA7n l\xE0m g\xEC.");
|
|
33068
|
+
}
|
|
33069
|
+
if (o.needLogin) {
|
|
33070
|
+
notice.push("\xB7 Cho ph\xE9p trong tr\xECnh duy\u1EC7t \u2014 \u0111\u1EC3 nh\u1EADn ch\xECa kho\xE1 v\u1EC1 m\xE1y n\xE0y.");
|
|
33071
|
+
}
|
|
33072
|
+
return { notice, fixCache };
|
|
33073
|
+
}
|
|
33074
|
+
function updateNpxArgs(version2, cacheDir) {
|
|
33075
|
+
return ["--cache", cacheDir, "-y", `hocai-connect@${version2}`];
|
|
33076
|
+
}
|
|
33077
|
+
function cleanNpmEnv(env) {
|
|
33078
|
+
return Object.fromEntries(Object.entries(env).filter(([k]) => !k.startsWith("npm_config_")));
|
|
33079
|
+
}
|
|
33080
|
+
function blockedDirs(platform3, home, canRead) {
|
|
33081
|
+
if (platform3 !== "darwin") return [];
|
|
33082
|
+
return GUARDED_DIRS.filter((d) => !canRead(`${home}/${d}`));
|
|
33083
|
+
}
|
|
33084
|
+
function blockedNotice(dirs) {
|
|
33085
|
+
if (dirs.length === 0) return [];
|
|
33086
|
+
return [
|
|
33087
|
+
`D\u1ECBch v\u1EE5 n\u1EC1n kh\xF4ng \u0111\u1ECDc \u0111\u01B0\u1EE3c ${dirs.join(", ")} tr\xEAn m\xE1y n\xE0y.`,
|
|
33088
|
+
"B\xE0i t\u1EADp \u0111\u1EC3 trong nh\u1EEFng th\u01B0 m\u1EE5c \u0111\xF3 s\u1EBD kh\xF4ng ch\u1EA1y \u2014 ch\u1ECDn th\u01B0 m\u1EE5c kh\xE1c, v\xED d\u1EE5 ~/hocai-bai-tap, l\xE0 xong."
|
|
33089
|
+
];
|
|
33090
|
+
}
|
|
32985
33091
|
|
|
32986
33092
|
// apps/mcp/src/server.ts
|
|
32987
33093
|
var import_promises = require("node:fs/promises");
|
|
32988
|
-
var
|
|
33094
|
+
var import_node_os2 = require("node:os");
|
|
32989
33095
|
var import_node_path = require("node:path");
|
|
32990
33096
|
|
|
32991
33097
|
// node_modules/zod/v3/helpers/util.js
|
|
@@ -41106,7 +41212,7 @@ function buildServer(token) {
|
|
|
41106
41212
|
},
|
|
41107
41213
|
async ({ slug }) => text(await call(`/lessons/${slug}/homework`))
|
|
41108
41214
|
);
|
|
41109
|
-
const thuMucBai = (maDe) => (0, import_node_path.join)((0,
|
|
41215
|
+
const thuMucBai = (maDe) => (0, import_node_path.join)((0, import_node_os2.homedir)(), "hocai-bai-tap", maDe);
|
|
41110
41216
|
server.registerTool(
|
|
41111
41217
|
"tai_file_de",
|
|
41112
41218
|
{
|
|
@@ -41169,9 +41275,9 @@ function buildServer(token) {
|
|
|
41169
41275
|
}
|
|
41170
41276
|
|
|
41171
41277
|
// apps/mcp/src/http.ts
|
|
41172
|
-
var
|
|
41278
|
+
var import_node_fs4 = require("node:fs");
|
|
41173
41279
|
var import_node_http = __toESM(require("node:http"));
|
|
41174
|
-
var
|
|
41280
|
+
var import_node_child_process3 = require("node:child_process");
|
|
41175
41281
|
|
|
41176
41282
|
// node_modules/@hono/node-server/dist/constants-BLSFu_RU.mjs
|
|
41177
41283
|
var X_ALREADY_SENT = "x-hono-already-sent";
|
|
@@ -43221,12 +43327,12 @@ var StreamableHTTPServerTransport = class {
|
|
|
43221
43327
|
};
|
|
43222
43328
|
|
|
43223
43329
|
// apps/mcp/src/http.ts
|
|
43224
|
-
var
|
|
43330
|
+
var import_node_os3 = require("node:os");
|
|
43225
43331
|
var import_node_path3 = require("node:path");
|
|
43226
43332
|
|
|
43227
43333
|
// apps/mcp/src/job.ts
|
|
43228
43334
|
var import_node_crypto = require("node:crypto");
|
|
43229
|
-
var
|
|
43335
|
+
var import_node_fs3 = require("node:fs");
|
|
43230
43336
|
var import_node_path2 = require("node:path");
|
|
43231
43337
|
var MAX_RUNNING = 3;
|
|
43232
43338
|
var TIMEOUT_MS = 15 * 60 * 1e3;
|
|
@@ -43235,7 +43341,7 @@ var XONG = /* @__PURE__ */ new Set(["DONE", "FAILED", "STOPPED"]);
|
|
|
43235
43341
|
function createJobStore(o) {
|
|
43236
43342
|
const maxRunning = o.maxRunning ?? MAX_RUNNING;
|
|
43237
43343
|
const timeoutMs = o.timeoutMs ?? TIMEOUT_MS;
|
|
43238
|
-
(0,
|
|
43344
|
+
(0, import_node_fs3.mkdirSync)(o.dir, { recursive: true });
|
|
43239
43345
|
const jobs = /* @__PURE__ */ new Map();
|
|
43240
43346
|
const handles = /* @__PURE__ */ new Map();
|
|
43241
43347
|
const listeners = /* @__PURE__ */ new Map();
|
|
@@ -43243,7 +43349,7 @@ function createJobStore(o) {
|
|
|
43243
43349
|
const file2 = (id) => (0, import_node_path2.join)(o.dir, `${id}.jsonl`);
|
|
43244
43350
|
const push = (id, line) => {
|
|
43245
43351
|
try {
|
|
43246
|
-
(0,
|
|
43352
|
+
(0, import_node_fs3.appendFileSync)(file2(id), line + "\n");
|
|
43247
43353
|
} catch {
|
|
43248
43354
|
}
|
|
43249
43355
|
for (const fn of listeners.get(id) ?? []) fn(line);
|
|
@@ -43305,7 +43411,7 @@ function createJobStore(o) {
|
|
|
43305
43411
|
startedAt: Date.now()
|
|
43306
43412
|
};
|
|
43307
43413
|
jobs.set(job.id, job);
|
|
43308
|
-
(0,
|
|
43414
|
+
(0, import_node_fs3.writeFileSync)(file2(job.id), JSON.stringify(job) + "\n");
|
|
43309
43415
|
if (dangChay() < maxRunning) start(job);
|
|
43310
43416
|
else queue.push(job.id);
|
|
43311
43417
|
return job;
|
|
@@ -43344,9 +43450,9 @@ function createJobStore(o) {
|
|
|
43344
43450
|
}
|
|
43345
43451
|
|
|
43346
43452
|
// apps/mcp/src/folder.ts
|
|
43347
|
-
var
|
|
43453
|
+
var import_node_child_process2 = require("node:child_process");
|
|
43348
43454
|
var runExec = (cmd, args) => new Promise((resolve, reject) => {
|
|
43349
|
-
(0,
|
|
43455
|
+
(0, import_node_child_process2.execFile)(cmd, args, (err, stdout) => {
|
|
43350
43456
|
const e = err;
|
|
43351
43457
|
if (e && e.code === "ENOENT") {
|
|
43352
43458
|
reject(e);
|
|
@@ -43356,14 +43462,14 @@ var runExec = (cmd, args) => new Promise((resolve, reject) => {
|
|
|
43356
43462
|
});
|
|
43357
43463
|
});
|
|
43358
43464
|
var DIALOG_TITLE = "Ch\u1ECDn th\u01B0 m\u1EE5c cho AI l\xE0m vi\u1EC7c";
|
|
43359
|
-
function cmdFor(
|
|
43360
|
-
if (
|
|
43465
|
+
function cmdFor(platform3) {
|
|
43466
|
+
if (platform3 === "darwin") {
|
|
43361
43467
|
return {
|
|
43362
43468
|
cmd: "osascript",
|
|
43363
43469
|
args: ["-e", `POSIX path of (choose folder with prompt "${DIALOG_TITLE}")`]
|
|
43364
43470
|
};
|
|
43365
43471
|
}
|
|
43366
|
-
if (
|
|
43472
|
+
if (platform3 === "win32") {
|
|
43367
43473
|
return {
|
|
43368
43474
|
cmd: "powershell.exe",
|
|
43369
43475
|
args: [
|
|
@@ -43379,9 +43485,9 @@ function cmdFor(platform2) {
|
|
|
43379
43485
|
};
|
|
43380
43486
|
}
|
|
43381
43487
|
async function chooseFolder(o = {}) {
|
|
43382
|
-
const
|
|
43488
|
+
const platform3 = o.platform ?? process.platform;
|
|
43383
43489
|
const exec = o.exec ?? runExec;
|
|
43384
|
-
const { cmd, args } = cmdFor(
|
|
43490
|
+
const { cmd, args } = cmdFor(platform3);
|
|
43385
43491
|
let r;
|
|
43386
43492
|
try {
|
|
43387
43493
|
r = await exec(cmd, args);
|
|
@@ -43423,7 +43529,7 @@ var TOOLS = {
|
|
|
43423
43529
|
],
|
|
43424
43530
|
WORK: ["Read", "Write", "Edit", "Glob", "Grep"]
|
|
43425
43531
|
};
|
|
43426
|
-
var VERSION = "0.
|
|
43532
|
+
var VERSION = "0.15.0";
|
|
43427
43533
|
function claudeArgs(job, o, port) {
|
|
43428
43534
|
const mcp = {
|
|
43429
43535
|
mcpServers: {
|
|
@@ -43455,7 +43561,7 @@ function claudeArgs(job, o, port) {
|
|
|
43455
43561
|
];
|
|
43456
43562
|
}
|
|
43457
43563
|
function buildHttpServer(o) {
|
|
43458
|
-
const spawn2 = o.spawn ??
|
|
43564
|
+
const spawn2 = o.spawn ?? import_node_child_process3.spawn;
|
|
43459
43565
|
const dangChay = /* @__PURE__ */ new Set();
|
|
43460
43566
|
const folders = o.folders;
|
|
43461
43567
|
const json3 = (res, code, body) => {
|
|
@@ -43511,7 +43617,7 @@ function buildHttpServer(o) {
|
|
|
43511
43617
|
return typeof a === "object" && a ? a.port : 0;
|
|
43512
43618
|
};
|
|
43513
43619
|
const store = createJobStore({
|
|
43514
|
-
dir: o.jobsDir ?? (0, import_node_path3.join)((0,
|
|
43620
|
+
dir: o.jobsDir ?? (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".hocai", "jobs"),
|
|
43515
43621
|
maxRunning: o.maxRunning,
|
|
43516
43622
|
run: (job, onLine) => {
|
|
43517
43623
|
const child = spawn2(o.claudeBin, claudeArgs(job, o, port()), {
|
|
@@ -43565,7 +43671,7 @@ function buildHttpServer(o) {
|
|
|
43565
43671
|
json3(res, 400, { error: "M\xE3 \u0111\u1EC1 kh\xF4ng h\u1EE3p l\u1EC7" });
|
|
43566
43672
|
return;
|
|
43567
43673
|
}
|
|
43568
|
-
dir = (0, import_node_path3.join)((0,
|
|
43674
|
+
dir = (0, import_node_path3.join)((0, import_node_os3.homedir)(), "hocai-bai-tap", maDe);
|
|
43569
43675
|
} else {
|
|
43570
43676
|
const d = i.dir ?? "";
|
|
43571
43677
|
if (!d.startsWith("/") || d.includes("..")) {
|
|
@@ -43584,7 +43690,7 @@ function buildHttpServer(o) {
|
|
|
43584
43690
|
json3(res, 409, { error: "Ch\u1ED7 n\xE0y \u0111ang c\xF3 m\u1ED9t l\u01B0\u1EE3t ch\u1EA1y \u2014 ch\u1EDD n\xF3 xong \u0111\xE3" });
|
|
43585
43691
|
return;
|
|
43586
43692
|
}
|
|
43587
|
-
(0,
|
|
43693
|
+
(0, import_node_fs4.mkdirSync)(dir, { recursive: true });
|
|
43588
43694
|
const job = store.create({
|
|
43589
43695
|
kind: i.kind,
|
|
43590
43696
|
dir,
|
|
@@ -43628,7 +43734,11 @@ function buildHttpServer(o) {
|
|
|
43628
43734
|
json3(res, 200, {
|
|
43629
43735
|
ten: "hocai-connect",
|
|
43630
43736
|
phienBan: VERSION,
|
|
43631
|
-
user: me ? { ten: me.ten, ...hoi ? { khop: hoi === me.id } : {} } : me
|
|
43737
|
+
user: me ? { ten: me.ten, ...hoi ? { khop: hoi === me.id } : {} } : me,
|
|
43738
|
+
// Vắng mặt khoá này = helper bản cũ. Web phân biệt được `undefined` với
|
|
43739
|
+
// `[]`, nên đừng "cho lành" bằng cách trả mảng rỗng: rỗng nghĩa là máy
|
|
43740
|
+
// KHÔNG CÓ trợ lý nào, một câu hoàn toàn khác.
|
|
43741
|
+
...o.agents ? { agents: o.agents() } : {}
|
|
43632
43742
|
});
|
|
43633
43743
|
return;
|
|
43634
43744
|
}
|
|
@@ -43781,11 +43891,11 @@ function mergeClaudeDesktopConfig(existing, creds) {
|
|
|
43781
43891
|
};
|
|
43782
43892
|
return { ...base, mcpServers: { ...servers, hocai } };
|
|
43783
43893
|
}
|
|
43784
|
-
function claudeDesktopConfigPath(
|
|
43785
|
-
if (
|
|
43894
|
+
function claudeDesktopConfigPath(platform3, home, appdata) {
|
|
43895
|
+
if (platform3 === "win32") {
|
|
43786
43896
|
return import_node_path4.win32.join(appdata ?? import_node_path4.win32.join(home, "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
|
|
43787
43897
|
}
|
|
43788
|
-
if (
|
|
43898
|
+
if (platform3 === "darwin") {
|
|
43789
43899
|
return import_node_path4.posix.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
43790
43900
|
}
|
|
43791
43901
|
return import_node_path4.posix.join(home, ".config", "Claude", "claude_desktop_config.json");
|
|
@@ -43968,11 +44078,11 @@ function defaultOrigins(env) {
|
|
|
43968
44078
|
}
|
|
43969
44079
|
|
|
43970
44080
|
// apps/mcp/src/folder-registry.ts
|
|
43971
|
-
var
|
|
43972
|
-
var
|
|
44081
|
+
var import_node_fs5 = require("node:fs");
|
|
44082
|
+
var import_node_os4 = require("node:os");
|
|
43973
44083
|
var import_node_crypto2 = require("node:crypto");
|
|
43974
44084
|
var import_node_path5 = require("node:path");
|
|
43975
|
-
var MAC_DINH = (0, import_node_path5.join)((0,
|
|
44085
|
+
var MAC_DINH = (0, import_node_path5.join)((0, import_node_os4.homedir)(), ".hocai", "folders.json");
|
|
43976
44086
|
function createFolderRegistry(o = {}) {
|
|
43977
44087
|
if (!o.file && process.env.VITEST) {
|
|
43978
44088
|
throw new Error(
|
|
@@ -44011,7 +44121,7 @@ function createFolderRegistry(o = {}) {
|
|
|
44011
44121
|
function nap(file2) {
|
|
44012
44122
|
let raw;
|
|
44013
44123
|
try {
|
|
44014
|
-
raw = (0,
|
|
44124
|
+
raw = (0, import_node_fs5.readFileSync)(file2, "utf8");
|
|
44015
44125
|
} catch {
|
|
44016
44126
|
return { rows: [], daLoai: false };
|
|
44017
44127
|
}
|
|
@@ -44023,13 +44133,13 @@ function nap(file2) {
|
|
|
44023
44133
|
}
|
|
44024
44134
|
if (!Array.isArray(data)) return { rows: [], daLoai: false };
|
|
44025
44135
|
const giu = data.filter(
|
|
44026
|
-
(r) => !!r && typeof r.id === "string" && typeof r.path === "string" && typeof r.label === "string" && typeof r.createdAt === "string" && (0,
|
|
44136
|
+
(r) => !!r && typeof r.id === "string" && typeof r.path === "string" && typeof r.label === "string" && typeof r.createdAt === "string" && (0, import_node_fs5.existsSync)(r.path)
|
|
44027
44137
|
);
|
|
44028
44138
|
return { rows: giu, daLoai: giu.length !== data.length };
|
|
44029
44139
|
}
|
|
44030
44140
|
function ghi(file2, rows) {
|
|
44031
|
-
(0,
|
|
44032
|
-
(0,
|
|
44141
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(file2), { recursive: true, mode: 448 });
|
|
44142
|
+
(0, import_node_fs5.writeFileSync)(file2, JSON.stringify([...rows.values()], null, 2), { mode: 384 });
|
|
44033
44143
|
}
|
|
44034
44144
|
|
|
44035
44145
|
// node_modules/ws/wrapper.mjs
|
|
@@ -44074,6 +44184,7 @@ function createUplink(o) {
|
|
|
44074
44184
|
s.send(JSON.stringify(o.hello()));
|
|
44075
44185
|
canhIm();
|
|
44076
44186
|
});
|
|
44187
|
+
s.on("ping", canhIm);
|
|
44077
44188
|
s.on("message", (raw) => {
|
|
44078
44189
|
canhIm();
|
|
44079
44190
|
let msg;
|
|
@@ -44151,7 +44262,7 @@ function handleServerMessage(msg, deps) {
|
|
|
44151
44262
|
}
|
|
44152
44263
|
|
|
44153
44264
|
// apps/mcp/src/cli.ts
|
|
44154
|
-
var HOCAI_DIR = (0, import_node_path6.join)((0,
|
|
44265
|
+
var HOCAI_DIR = (0, import_node_path6.join)((0, import_node_os5.homedir)(), ".hocai");
|
|
44155
44266
|
var CREDS = (0, import_node_path6.join)(HOCAI_DIR, "config.json");
|
|
44156
44267
|
var APP_DIR = (0, import_node_path6.join)(HOCAI_DIR, "app");
|
|
44157
44268
|
var APP_CLI = (0, import_node_path6.join)(APP_DIR, "cli.js");
|
|
@@ -44162,25 +44273,25 @@ var PORT = Number(process.env.MCP_HTTP_PORT ?? 4100);
|
|
|
44162
44273
|
var say = (s) => process.stderr.write(s + "\n");
|
|
44163
44274
|
function loadCreds() {
|
|
44164
44275
|
try {
|
|
44165
|
-
const c = JSON.parse((0,
|
|
44276
|
+
const c = JSON.parse((0, import_node_fs6.readFileSync)(CREDS, "utf8"));
|
|
44166
44277
|
return c.token && c.api ? { token: c.token, api: c.api } : null;
|
|
44167
44278
|
} catch {
|
|
44168
44279
|
return null;
|
|
44169
44280
|
}
|
|
44170
44281
|
}
|
|
44171
44282
|
function saveCreds(c) {
|
|
44172
|
-
(0,
|
|
44173
|
-
(0,
|
|
44283
|
+
(0, import_node_fs6.mkdirSync)(HOCAI_DIR, { recursive: true, mode: 448 });
|
|
44284
|
+
(0, import_node_fs6.writeFileSync)(CREDS, JSON.stringify(c, null, 2));
|
|
44174
44285
|
try {
|
|
44175
|
-
(0,
|
|
44286
|
+
(0, import_node_fs6.chmodSync)(CREDS, 384);
|
|
44176
44287
|
} catch {
|
|
44177
44288
|
}
|
|
44178
44289
|
}
|
|
44179
44290
|
function openBrowser(url2) {
|
|
44180
|
-
const p = (0,
|
|
44291
|
+
const p = (0, import_node_os5.platform)();
|
|
44181
44292
|
const cmd = p === "darwin" ? ["open", url2] : p === "win32" ? ["cmd", "/c", "start", "", url2] : ["xdg-open", url2];
|
|
44182
44293
|
try {
|
|
44183
|
-
(0,
|
|
44294
|
+
(0, import_node_child_process4.spawn)(cmd[0], cmd.slice(1), { stdio: "ignore", detached: true }).unref();
|
|
44184
44295
|
} catch {
|
|
44185
44296
|
}
|
|
44186
44297
|
}
|
|
@@ -44201,28 +44312,28 @@ async function login() {
|
|
|
44201
44312
|
return loadCreds();
|
|
44202
44313
|
}
|
|
44203
44314
|
function writeDesktop(creds) {
|
|
44204
|
-
const path = claudeDesktopConfigPath((0,
|
|
44205
|
-
if (!(0,
|
|
44315
|
+
const path = claudeDesktopConfigPath((0, import_node_os5.platform)(), (0, import_node_os5.homedir)(), process.env.APPDATA);
|
|
44316
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(path))) {
|
|
44206
44317
|
say("\xB7 Claude Desktop: kh\xF4ng th\u1EA5y tr\xEAn m\xE1y, b\u1ECF qua");
|
|
44207
44318
|
return;
|
|
44208
44319
|
}
|
|
44209
44320
|
let prev;
|
|
44210
44321
|
try {
|
|
44211
|
-
prev = JSON.parse((0,
|
|
44322
|
+
prev = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf8"));
|
|
44212
44323
|
} catch {
|
|
44213
44324
|
prev = void 0;
|
|
44214
44325
|
}
|
|
44215
|
-
(0,
|
|
44326
|
+
(0, import_node_fs6.writeFileSync)(path, JSON.stringify(mergeClaudeDesktopConfig(prev, creds), null, 2));
|
|
44216
44327
|
say(`\u2713 Claude Desktop: \u0111\xE3 ghi ${path} (m\u1EDF l\u1EA1i Claude Desktop \u0111\u1EC3 n\xF3 nh\u1EADn)`);
|
|
44217
44328
|
}
|
|
44218
44329
|
function addClaudeCode(creds) {
|
|
44219
|
-
const win = (0,
|
|
44330
|
+
const win = (0, import_node_os5.platform)() === "win32";
|
|
44220
44331
|
try {
|
|
44221
|
-
(0,
|
|
44332
|
+
(0, import_node_child_process4.execFileSync)("claude", ["mcp", "remove", "hocai"], { stdio: "ignore", shell: win });
|
|
44222
44333
|
} catch {
|
|
44223
44334
|
}
|
|
44224
44335
|
try {
|
|
44225
|
-
(0,
|
|
44336
|
+
(0, import_node_child_process4.execFileSync)("claude", [
|
|
44226
44337
|
"mcp",
|
|
44227
44338
|
"add",
|
|
44228
44339
|
"hocai",
|
|
@@ -44244,28 +44355,13 @@ function addClaudeCode(creds) {
|
|
|
44244
44355
|
function claudeBin() {
|
|
44245
44356
|
if (process.env.CLAUDE_BIN) return process.env.CLAUDE_BIN;
|
|
44246
44357
|
try {
|
|
44247
|
-
return (0,
|
|
44358
|
+
return (0, import_node_child_process4.execSync)("command -v claude", { shell: "/bin/sh", encoding: "utf8" }).trim() || "claude";
|
|
44248
44359
|
} catch {
|
|
44249
44360
|
return "claude";
|
|
44250
44361
|
}
|
|
44251
44362
|
}
|
|
44252
|
-
function chayLay(cmd, args) {
|
|
44253
|
-
try {
|
|
44254
|
-
const dong = [cmd, ...args].join(" ");
|
|
44255
|
-
const o = {
|
|
44256
|
-
encoding: "utf8",
|
|
44257
|
-
timeout: 8e3,
|
|
44258
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
44259
|
-
};
|
|
44260
|
-
return (0, import_node_os4.platform)() === "win32" ? (0, import_node_child_process3.execSync)(dong, o) : (0, import_node_child_process3.execSync)(dong, { ...o, shell: "/bin/sh" });
|
|
44261
|
-
} catch (e) {
|
|
44262
|
-
const ra = e.stdout;
|
|
44263
|
-
const chu = typeof ra === "string" ? ra : ra?.toString("utf8");
|
|
44264
|
-
return chu && chu.trim() ? chu : null;
|
|
44265
|
-
}
|
|
44266
|
-
}
|
|
44267
44363
|
function doTroLy() {
|
|
44268
|
-
const r = summarizeAgents(probeAgents(
|
|
44364
|
+
const r = summarizeAgents(probeAgents(realProbeIO()));
|
|
44269
44365
|
if (r.dong.length) {
|
|
44270
44366
|
say("");
|
|
44271
44367
|
for (const d of r.dong) say(" " + d);
|
|
@@ -44276,13 +44372,75 @@ function doTroLy() {
|
|
|
44276
44372
|
}
|
|
44277
44373
|
return r.chayDuocBai;
|
|
44278
44374
|
}
|
|
44279
|
-
|
|
44375
|
+
function chayHien(cmd) {
|
|
44376
|
+
try {
|
|
44377
|
+
(0, import_node_child_process4.execFileSync)(cmd[0], cmd.slice(1), { stdio: "inherit", shell: (0, import_node_os5.platform)() === "win32" });
|
|
44378
|
+
return true;
|
|
44379
|
+
} catch {
|
|
44380
|
+
return false;
|
|
44381
|
+
}
|
|
44382
|
+
}
|
|
44383
|
+
var PERMS = (0, import_node_path6.join)(HOCAI_DIR, "perms.json");
|
|
44384
|
+
var NPM_CACHE = (0, import_node_path6.join)(HOCAI_DIR, "npm-cache");
|
|
44385
|
+
function npmCacheDir() {
|
|
44386
|
+
const ra = shellRun("npm", ["config", "get", "cache"], {
|
|
44387
|
+
cwd: (0, import_node_os5.homedir)(),
|
|
44388
|
+
env: cleanNpmEnv(process.env)
|
|
44389
|
+
});
|
|
44390
|
+
const chu = ra?.trim();
|
|
44391
|
+
if (chu && chu !== "undefined" && chu !== "null") return chu;
|
|
44392
|
+
return (0, import_node_os5.platform)() === "win32" ? (0, import_node_path6.join)(process.env.LOCALAPPDATA ?? (0, import_node_os5.homedir)(), "npm-cache") : (0, import_node_path6.join)((0, import_node_os5.homedir)(), ".npm");
|
|
44393
|
+
}
|
|
44394
|
+
function countAlienFiles(dir, tran = 500) {
|
|
44395
|
+
const toi = process.getuid?.();
|
|
44396
|
+
if (toi === void 0) return 0;
|
|
44397
|
+
let dem = 0;
|
|
44398
|
+
const di = (d) => {
|
|
44399
|
+
if (dem >= tran) return;
|
|
44400
|
+
let muc;
|
|
44401
|
+
try {
|
|
44402
|
+
muc = (0, import_node_fs6.readdirSync)(d);
|
|
44403
|
+
} catch {
|
|
44404
|
+
return;
|
|
44405
|
+
}
|
|
44406
|
+
for (const m of muc) {
|
|
44407
|
+
if (dem >= tran) return;
|
|
44408
|
+
const duong = (0, import_node_path6.join)(d, m);
|
|
44409
|
+
try {
|
|
44410
|
+
const st = (0, import_node_fs6.statSync)(duong);
|
|
44411
|
+
if (st.uid !== toi) {
|
|
44412
|
+
dem++;
|
|
44413
|
+
continue;
|
|
44414
|
+
}
|
|
44415
|
+
if (st.isDirectory()) di(duong);
|
|
44416
|
+
} catch {
|
|
44417
|
+
}
|
|
44418
|
+
}
|
|
44419
|
+
};
|
|
44420
|
+
di(dir);
|
|
44421
|
+
return dem;
|
|
44422
|
+
}
|
|
44423
|
+
function warnLines(lines) {
|
|
44424
|
+
if (lines.length === 0) return;
|
|
44425
|
+
say("");
|
|
44426
|
+
say("\u26A0 " + lines[0]);
|
|
44427
|
+
for (const d of lines.slice(1)) say(" " + d);
|
|
44428
|
+
}
|
|
44429
|
+
function doPerms() {
|
|
44430
|
+
try {
|
|
44431
|
+
const j = JSON.parse((0, import_node_fs6.readFileSync)(PERMS, "utf8"));
|
|
44432
|
+
return blockedNotice(Array.isArray(j.blocked) ? j.blocked : []);
|
|
44433
|
+
} catch {
|
|
44434
|
+
return [];
|
|
44435
|
+
}
|
|
44436
|
+
}
|
|
44437
|
+
var plan = () => daemonPlan((0, import_node_os5.platform)(), { node: process.execPath, script: APP_CLI, home: (0, import_node_os5.homedir)() });
|
|
44280
44438
|
function nghi(ms) {
|
|
44281
44439
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
44282
44440
|
}
|
|
44283
44441
|
function chay(cmd, im = false) {
|
|
44284
44442
|
try {
|
|
44285
|
-
(0,
|
|
44443
|
+
(0, import_node_child_process4.execFileSync)(cmd[0], cmd.slice(1), { stdio: "ignore", shell: (0, import_node_os5.platform)() === "win32" });
|
|
44286
44444
|
return true;
|
|
44287
44445
|
} catch {
|
|
44288
44446
|
if (!im) return false;
|
|
@@ -44295,17 +44453,17 @@ function caiDichVu() {
|
|
|
44295
44453
|
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.");
|
|
44296
44454
|
return false;
|
|
44297
44455
|
}
|
|
44298
|
-
(0,
|
|
44299
|
-
(0,
|
|
44300
|
-
(0,
|
|
44456
|
+
(0, import_node_fs6.mkdirSync)(APP_DIR, { recursive: true });
|
|
44457
|
+
(0, import_node_fs6.mkdirSync)(LOG_DIR, { recursive: true });
|
|
44458
|
+
(0, import_node_fs6.copyFileSync)(__filename, APP_CLI);
|
|
44301
44459
|
if (p.file && p.content) {
|
|
44302
|
-
(0,
|
|
44303
|
-
(0,
|
|
44460
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path6.dirname)(p.file), { recursive: true });
|
|
44461
|
+
(0, import_node_fs6.writeFileSync)(p.file, p.content);
|
|
44304
44462
|
}
|
|
44305
44463
|
p.install.forEach((c, i) => {
|
|
44306
44464
|
if (i === 0) {
|
|
44307
44465
|
chay(c, true);
|
|
44308
|
-
if ((0,
|
|
44466
|
+
if ((0, import_node_os5.platform)() === "darwin") {
|
|
44309
44467
|
const nhan = `gui/${process.getuid?.() ?? 501}/${p.label}`;
|
|
44310
44468
|
for (let lan = 0; lan < 20; lan++) {
|
|
44311
44469
|
if (!chay(["launchctl", "print", nhan], true)) break;
|
|
@@ -44324,7 +44482,7 @@ function caiDichVu() {
|
|
|
44324
44482
|
function goDichVu() {
|
|
44325
44483
|
const p = plan();
|
|
44326
44484
|
for (const c of p.uninstall) chay(c, true);
|
|
44327
|
-
if (p.file) (0,
|
|
44485
|
+
if (p.file) (0, import_node_fs6.rmSync)(p.file, { force: true });
|
|
44328
44486
|
}
|
|
44329
44487
|
var LENH = ["mcp", "run", "update", "status", "stop", "logs", "quen", "help", "--help", "-h", "entry"];
|
|
44330
44488
|
var TRO_GIUP = `hocai-connect \u2014 n\u1ED1i Claude tr\xEAn m\xE1y b\u1EA1n v\xE0o hocAI
|
|
@@ -44359,7 +44517,7 @@ async function main() {
|
|
|
44359
44517
|
}
|
|
44360
44518
|
if (cmd === "quen") {
|
|
44361
44519
|
goDichVu();
|
|
44362
|
-
(0,
|
|
44520
|
+
(0, import_node_fs6.rmSync)(CREDS, { force: true });
|
|
44363
44521
|
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.");
|
|
44364
44522
|
say("Ch\u1EA1y l\u1EA1i `npx hocai-connect` \u0111\u1EC3 k\u1EBFt n\u1ED1i l\u1EA1i.");
|
|
44365
44523
|
return;
|
|
@@ -44376,9 +44534,10 @@ async function main() {
|
|
|
44376
44534
|
}
|
|
44377
44535
|
say(`C\xF3 b\u1EA3n m\u1EDBi: ${VERSION} \u2192 ${moi}. \u0110ang c\u1EADp nh\u1EADt\u2026`);
|
|
44378
44536
|
say("");
|
|
44379
|
-
|
|
44537
|
+
(0, import_node_fs6.mkdirSync)(NPM_CACHE, { recursive: true });
|
|
44538
|
+
const r = (0, import_node_child_process4.spawnSync)("npx", updateNpxArgs(moi, NPM_CACHE), {
|
|
44380
44539
|
stdio: "inherit",
|
|
44381
|
-
shell: (0,
|
|
44540
|
+
shell: (0, import_node_os5.platform)() === "win32"
|
|
44382
44541
|
});
|
|
44383
44542
|
process.exit(r.status ?? 1);
|
|
44384
44543
|
}
|
|
@@ -44400,6 +44559,7 @@ async function main() {
|
|
|
44400
44559
|
}
|
|
44401
44560
|
say(`\u2713 \u0110ang ch\u1EA1y \xB7 ${info.user?.ten ?? "(ch\xECa \u0111\xE3 b\u1ECB thu h\u1ED3i)"} \xB7 b\u1EA3n ${info.phienBan}`);
|
|
44402
44561
|
say(` Nh\u1EADt k\xFD: ${plan().log}`);
|
|
44562
|
+
warnLines(doPerms());
|
|
44403
44563
|
const moi = await latestVersion();
|
|
44404
44564
|
if (moi && info.phienBan && newerVersion(moi, info.phienBan)) {
|
|
44405
44565
|
say("");
|
|
@@ -44409,13 +44569,24 @@ async function main() {
|
|
|
44409
44569
|
}
|
|
44410
44570
|
if (cmd === "logs") {
|
|
44411
44571
|
const f = plan().log;
|
|
44412
|
-
if (!(0,
|
|
44572
|
+
if (!(0, import_node_fs6.existsSync)(f)) {
|
|
44413
44573
|
say(`Ch\u01B0a c\xF3 nh\u1EADt k\xFD n\xE0o \u1EDF ${f}`);
|
|
44414
44574
|
return;
|
|
44415
44575
|
}
|
|
44416
|
-
say((0,
|
|
44576
|
+
say((0, import_node_fs6.readFileSync)(f, "utf8").split("\n").slice(-40).join("\n"));
|
|
44417
44577
|
return;
|
|
44418
44578
|
}
|
|
44579
|
+
const quyen = cmd === "run" ? null : permPlan((0, import_node_os5.platform)(), {
|
|
44580
|
+
alienCacheFiles: countAlienFiles(npmCacheDir()),
|
|
44581
|
+
cacheDir: npmCacheDir(),
|
|
44582
|
+
user: (0, import_node_os5.userInfo)().username,
|
|
44583
|
+
needLogin: !loadCreds()
|
|
44584
|
+
});
|
|
44585
|
+
if (quyen && quyen.notice.length) {
|
|
44586
|
+
say("");
|
|
44587
|
+
say("hocAI s\u1EAFp xin nh\u1EEFng th\u1EE9 sau \u2014 kh\xF4ng c\xF3 g\xEC ch\u1EA1y ng\u1EA7m sau l\u01B0ng b\u1EA1n:");
|
|
44588
|
+
for (const d of quyen.notice) say(" " + d);
|
|
44589
|
+
}
|
|
44419
44590
|
const creds = loadCreds() ?? await login();
|
|
44420
44591
|
process.env.HOCAI_API_URL = creds.api;
|
|
44421
44592
|
const me = await fetchIdentity(creds.api, creds.token).catch(() => {
|
|
@@ -44460,10 +44631,34 @@ async function main() {
|
|
|
44460
44631
|
say(` Xem nh\u1EADt k\xFD: npx hocai-connect logs`);
|
|
44461
44632
|
process.exit(1);
|
|
44462
44633
|
}
|
|
44634
|
+
warnLines(doPerms());
|
|
44635
|
+
}
|
|
44636
|
+
if (quyen && quyen.fixCache.length) {
|
|
44637
|
+
say("");
|
|
44638
|
+
say("C\xF2n m\u1ED9t vi\u1EC7c: cache npm tr\xEAn m\xE1y n\xE0y c\xF3 t\u1EC7p thu\u1ED9c ng\u01B0\u1EDDi d\xF9ng kh\xE1c,");
|
|
44639
|
+
say("n\xEAn l\u1EC7nh `npx hocai-connect update` sau n\xE0y s\u1EBD h\u1ECFng. S\u1EEDa c\u1EA7n m\u1EADt kh\u1EA9u m\xE1y.");
|
|
44640
|
+
say("Kh\xF4ng mu\u1ED1n th\xEC b\u1EA5m Ctrl-C \u2014 m\u1ECDi th\u1EE9 kh\xE1c \u0111\xE3 xong v\xE0 v\u1EABn ch\u1EA1y.");
|
|
44641
|
+
for (const lenh of quyen.fixCache) {
|
|
44642
|
+
const ok = chayHien(lenh);
|
|
44643
|
+
say(ok ? "\u2713 \u0110\xE3 s\u1EEDa quy\u1EC1n cache npm." : "\xB7 Ch\u01B0a s\u1EEDa \u0111\u01B0\u1EE3c. C\u1EADp nh\u1EADt sau n\xE0y v\u1EABn ch\u1EA1y \u0111\u01B0\u1EE3c v\xEC hocAI d\xF9ng cache ri\xEAng.");
|
|
44644
|
+
}
|
|
44463
44645
|
}
|
|
44464
44646
|
return;
|
|
44465
44647
|
}
|
|
44466
|
-
cutLogIfBig(logPathFor((0,
|
|
44648
|
+
cutLogIfBig(logPathFor((0, import_node_os5.homedir)()));
|
|
44649
|
+
try {
|
|
44650
|
+
const chan = blockedDirs((0, import_node_os5.platform)(), (0, import_node_os5.homedir)(), (duong) => {
|
|
44651
|
+
try {
|
|
44652
|
+
(0, import_node_fs6.readdirSync)(duong);
|
|
44653
|
+
return true;
|
|
44654
|
+
} catch {
|
|
44655
|
+
return false;
|
|
44656
|
+
}
|
|
44657
|
+
});
|
|
44658
|
+
(0, import_node_fs6.mkdirSync)(HOCAI_DIR, { recursive: true });
|
|
44659
|
+
(0, import_node_fs6.writeFileSync)(PERMS, JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), blocked: chan }) + "\n");
|
|
44660
|
+
} catch {
|
|
44661
|
+
}
|
|
44467
44662
|
const folders = createFolderRegistry();
|
|
44468
44663
|
const srv = buildHttpServer({
|
|
44469
44664
|
// MỘT sổ dùng chung cho cả đường trình duyệt lẫn đường lên socket. Hai sổ
|
|
@@ -44476,7 +44671,11 @@ async function main() {
|
|
|
44476
44671
|
// chối trang mới trong im lặng. Xem `defaultOrigins`.
|
|
44477
44672
|
origins: defaultOrigins(process.env.HOCAI_WEB_ORIGINS),
|
|
44478
44673
|
claudeBin: claudeBin(),
|
|
44479
|
-
me: identity.current
|
|
44674
|
+
me: identity.current,
|
|
44675
|
+
// Nhớ 5 phút. Đủ lâu để tuyến nóng không đốt máy học viên, đủ ngắn để
|
|
44676
|
+
// người vừa `claude auth login` không phải khởi động lại dịch vụ mới thấy
|
|
44677
|
+
// màn hình đổi.
|
|
44678
|
+
agents: cachedProbe(realProbeIO(), Date.now)
|
|
44480
44679
|
});
|
|
44481
44680
|
srv.on("error", (e) => {
|
|
44482
44681
|
if (e.code !== "EADDRINUSE") throw e;
|
|
@@ -44494,8 +44693,8 @@ async function main() {
|
|
|
44494
44693
|
// hai lượt nối là chuyện thường, và máy chủ phải nhận danh sách MỚI NHẤT.
|
|
44495
44694
|
hello: () => ({
|
|
44496
44695
|
t: "hello",
|
|
44497
|
-
name: (0,
|
|
44498
|
-
os: (0,
|
|
44696
|
+
name: (0, import_node_os5.hostname)(),
|
|
44697
|
+
os: (0, import_node_os5.platform)(),
|
|
44499
44698
|
folders: folders.list()
|
|
44500
44699
|
}),
|
|
44501
44700
|
onMessage: (msg) => handleServerMessage(msg, { folders, store: srv.store, send: uplink.send })
|