hocai-connect 0.18.0 → 0.18.1

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.
Files changed (2) hide show
  1. package/dist/cli.js +214 -65
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -45788,7 +45788,7 @@ var TOOLS = {
45788
45788
  // không phải là lời mời đọc ổ đĩa của học viên.
45789
45789
  CHAT: []
45790
45790
  };
45791
- var VERSION = "0.18.0";
45791
+ var VERSION = "0.18.1";
45792
45792
  function claudeArgs(job, o, port) {
45793
45793
  const mcp = {
45794
45794
  mcpServers: {
@@ -47823,6 +47823,83 @@ async function setupMcp(options) {
47823
47823
  return { script, protocolVerified: true, tools, clients };
47824
47824
  }
47825
47825
 
47826
+ // apps/mcp/src/terminal-progress.ts
47827
+ var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
47828
+ var CLEAR_LINE = "\r\x1B[2K";
47829
+ function createTerminalProgress(options = {}) {
47830
+ const stream = options.stream ?? process.stderr;
47831
+ const intervalMs = options.intervalMs ?? 80;
47832
+ const interactive = options.interactive ?? (stream.isTTY === true && process.env.TERM !== "dumb");
47833
+ let timer = null;
47834
+ let frame = 0;
47835
+ let label = "";
47836
+ let active = false;
47837
+ let lastPlain = "";
47838
+ const clearTimer = () => {
47839
+ if (!timer) return;
47840
+ clearInterval(timer);
47841
+ timer = null;
47842
+ };
47843
+ const draw = () => {
47844
+ if (!active || !interactive) return;
47845
+ stream.write(`${CLEAR_LINE}${FRAMES[frame % FRAMES.length]} ${label}`);
47846
+ frame++;
47847
+ };
47848
+ const plain = (icon, text) => {
47849
+ stream.write(`${icon} ${text}
47850
+ `);
47851
+ lastPlain = text;
47852
+ };
47853
+ const stop = () => {
47854
+ if (!active) return;
47855
+ clearTimer();
47856
+ if (interactive) stream.write(CLEAR_LINE);
47857
+ active = false;
47858
+ };
47859
+ const settle = (icon, text) => {
47860
+ const finalLabel = text ?? label;
47861
+ clearTimer();
47862
+ if (interactive) stream.write(`${CLEAR_LINE}${icon} ${finalLabel}
47863
+ `);
47864
+ else plain(icon, finalLabel);
47865
+ active = false;
47866
+ };
47867
+ return {
47868
+ get interactive() {
47869
+ return interactive;
47870
+ },
47871
+ start(text) {
47872
+ stop();
47873
+ label = text;
47874
+ frame = 0;
47875
+ active = true;
47876
+ lastPlain = "";
47877
+ if (interactive) {
47878
+ draw();
47879
+ timer = setInterval(draw, intervalMs);
47880
+ timer.unref?.();
47881
+ } else {
47882
+ plain("\xB7", text);
47883
+ }
47884
+ },
47885
+ update(text) {
47886
+ if (!active) return;
47887
+ label = text;
47888
+ if (interactive) draw();
47889
+ else if (text !== lastPlain) plain("\xB7", text);
47890
+ },
47891
+ succeed(text) {
47892
+ if (!active && !text) return;
47893
+ settle("\u2713", text);
47894
+ },
47895
+ fail(text) {
47896
+ if (!active && !text) return;
47897
+ settle("\u2715", text);
47898
+ },
47899
+ stop
47900
+ };
47901
+ }
47902
+
47826
47903
  // apps/mcp/src/cli.ts
47827
47904
  var HOCAI_DIR = (0, import_node_path17.join)((0, import_node_os11.homedir)(), ".hocai");
47828
47905
  var CREDS = (0, import_node_path17.join)(HOCAI_DIR, "config.json");
@@ -47867,18 +47944,35 @@ async function login() {
47867
47944
  say2(`N\u1EBFu kh\xF4ng th\u1EA5y g\xEC m\u1EDF ra, d\xE1n \u0111\u1ECBa ch\u1EC9 n\xE0y v\xE0o tr\xECnh duy\u1EC7t:
47868
47945
  ${url2}`);
47869
47946
  openBrowser(url2);
47870
- const creds = await l.token;
47871
- await l.close();
47872
- saveCreds({ token: creds.token, api: absoluteApiUrl(creds.api, WEB(), API_DEFAULT()) });
47873
- say2("\u2713 \u0110\xE3 nh\u1EADn token v\xE0 l\u01B0u v\xE0o ~/.hocai/config.json");
47874
- return loadCreds();
47947
+ const progress = createTerminalProgress();
47948
+ progress.start("\u0110ang ch\u1EDD b\u1EA1n cho ph\xE9p trong tr\xECnh duy\u1EC7t\u2026");
47949
+ try {
47950
+ const creds = await l.token;
47951
+ await l.close();
47952
+ saveCreds({ token: creds.token, api: absoluteApiUrl(creds.api, WEB(), API_DEFAULT()) });
47953
+ progress.succeed("\u0110\xE3 \u0111\u0103ng nh\u1EADp v\xE0 l\u01B0u k\u1EBFt n\u1ED1i hocAI.");
47954
+ return loadCreds();
47955
+ } catch (error51) {
47956
+ progress.fail("Ch\u01B0a nh\u1EADn \u0111\u01B0\u1EE3c \u0111\u0103ng nh\u1EADp t\u1EEB tr\xECnh duy\u1EC7t.");
47957
+ await l.close().catch(() => {
47958
+ });
47959
+ throw error51;
47960
+ }
47875
47961
  }
47876
47962
  async function configureMcp(json3 = false) {
47877
47963
  const creds = workCredentials(loadCreds());
47878
- const result = await setupMcp({ root: HOCAI_DIR, source: __filename, authenticated: !!creds });
47964
+ const progress = json3 ? null : createTerminalProgress();
47965
+ progress?.start("\u0110ang c\u1EA5u h\xECnh MCP cho c\xE1c tr\u1EE3 l\xFD AI tr\xEAn m\xE1y\u2026");
47966
+ let result;
47967
+ try {
47968
+ result = await setupMcp({ root: HOCAI_DIR, source: __filename, authenticated: !!creds });
47969
+ } catch (error51) {
47970
+ progress?.fail("C\u1EA5u h\xECnh MCP ch\u01B0a ho\xE0n t\u1EA5t.");
47971
+ throw error51;
47972
+ }
47879
47973
  if (json3) process.stdout.write(JSON.stringify(result) + "\n");
47880
47974
  else {
47881
- say2("\u2713 MCP \u0111\xE3 b\u1EAFt tay v\xE0 kh\xE1m ph\xE1 c\xF4ng c\u1EE5 th\xE0nh c\xF4ng.");
47975
+ progress?.succeed("MCP \u0111\xE3 b\u1EAFt tay v\xE0 kh\xE1m ph\xE1 c\xF4ng c\u1EE5 th\xE0nh c\xF4ng.");
47882
47976
  for (const client of result.clients) {
47883
47977
  const status = { configured: "\u0111\xE3 c\u1EA5u h\xECnh", unchanged: "\u0111\xE3 c\xF3 c\u1EA5u h\xECnh \u0111\xFAng", skipped: "ch\u01B0a th\u1EA5y \u1EE9ng d\u1EE5ng", failed: "ch\u01B0a c\u1EA5u h\xECnh \u0111\u01B0\u1EE3c" }[client.status];
47884
47978
  say2(` ${client.client}: ${status}${client.message ? ` \u2014 ${client.message}` : ""}`);
@@ -47989,31 +48083,41 @@ function caiDichVu() {
47989
48083
  say2("\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.");
47990
48084
  return false;
47991
48085
  }
47992
- (0, import_node_fs10.mkdirSync)(APP_DIR, { recursive: true });
47993
- (0, import_node_fs10.mkdirSync)(LOG_DIR, { recursive: true });
47994
- (0, import_node_fs10.copyFileSync)(__filename, APP_CLI);
47995
- if (p.file && p.content) {
47996
- (0, import_node_fs10.mkdirSync)((0, import_node_path17.dirname)(p.file), { recursive: true });
47997
- (0, import_node_fs10.writeFileSync)(p.file, p.content);
47998
- }
47999
- p.install.forEach((c, i) => {
48000
- if (i === 0) {
48001
- chay(c, true);
48002
- if ((0, import_node_os11.platform)() === "darwin") {
48003
- const nhan = `gui/${process.getuid?.() ?? 501}/${p.label}`;
48004
- for (let lan = 0; lan < 20; lan++) {
48005
- if (!chay(["launchctl", "print", nhan], true)) break;
48006
- nghi(250);
48086
+ const progress = createTerminalProgress();
48087
+ progress.start("\u0110ang chu\u1EA9n b\u1ECB d\u1ECBch v\u1EE5 n\u1EC1n\u2026");
48088
+ try {
48089
+ (0, import_node_fs10.mkdirSync)(APP_DIR, { recursive: true });
48090
+ (0, import_node_fs10.mkdirSync)(LOG_DIR, { recursive: true });
48091
+ (0, import_node_fs10.copyFileSync)(__filename, APP_CLI);
48092
+ progress.update("\u0110ang ghi c\u1EA5u h\xECnh d\u1ECBch v\u1EE5 n\u1EC1n\u2026");
48093
+ if (p.file && p.content) {
48094
+ (0, import_node_fs10.mkdirSync)((0, import_node_path17.dirname)(p.file), { recursive: true });
48095
+ (0, import_node_fs10.writeFileSync)(p.file, p.content);
48096
+ }
48097
+ progress.update("\u0110ang \u0111\u0103ng k\xFD d\u1ECBch v\u1EE5 v\u1EDBi h\u1EC7 \u0111i\u1EC1u h\xE0nh\u2026");
48098
+ p.install.forEach((c, i) => {
48099
+ if (i === 0) {
48100
+ chay(c, true);
48101
+ if ((0, import_node_os11.platform)() === "darwin") {
48102
+ const nhan = `gui/${process.getuid?.() ?? 501}/${p.label}`;
48103
+ for (let lan = 0; lan < 20; lan++) {
48104
+ if (!chay(["launchctl", "print", nhan], true)) break;
48105
+ nghi(250);
48106
+ }
48007
48107
  }
48108
+ return;
48008
48109
  }
48009
- return;
48010
- }
48011
- for (let lan = 0; lan < 5; lan++) {
48012
- if (chay(c, true)) return;
48013
- nghi(700);
48014
- }
48015
- });
48016
- return true;
48110
+ for (let lan = 0; lan < 5; lan++) {
48111
+ if (chay(c, true)) return;
48112
+ nghi(700);
48113
+ }
48114
+ });
48115
+ progress.succeed("D\u1ECBch v\u1EE5 n\u1EC1n \u0111\xE3 \u0111\u01B0\u1EE3c c\xE0i v\xE0 b\u1EADt.");
48116
+ return true;
48117
+ } catch (error51) {
48118
+ progress.fail("Kh\xF4ng c\xE0i \u0111\u01B0\u1EE3c d\u1ECBch v\u1EE5 n\u1EC1n.");
48119
+ throw error51;
48120
+ }
48017
48121
  }
48018
48122
  function goDichVu() {
48019
48123
  const p = plan();
@@ -48058,19 +48162,41 @@ async function main() {
48058
48162
  if (cmd === "sync-reports") {
48059
48163
  const flags = process.argv.slice(3);
48060
48164
  if (flags.some((flag) => flag !== "--json")) throw new Error("sync-reports ch\u1EC9 nh\u1EADn --json.");
48165
+ const json3 = flags.includes("--json");
48061
48166
  const creds2 = workCredentials(loadCreds());
48062
48167
  if (!creds2) throw new Error("Ch\u01B0a n\u1ED1i hocAI. Ch\u1EA1y hocai-connect tr\u01B0\u1EDBc.");
48063
- const result = await createWorkOutbox({ ...creds2, root: (0, import_node_path17.join)(HOCAI_DIR, "work-outbox") }).flush();
48064
- if (flags.includes("--json")) process.stdout.write(JSON.stringify(result) + "\n");
48065
- else say2(`\u0110\xE3 x\xE1c nh\u1EADn ${result.sent} b\xE1o c\xE1o; c\xF2n ch\u1EDD ${result.pending}.${result.lastError ? ` ${result.lastError}` : ""}`);
48168
+ const progress = json3 ? null : createTerminalProgress();
48169
+ progress?.start("\u0110ang \u0111\u1ED3ng b\u1ED9 c\xE1c b\xE1o c\xE1o c\xF2n ch\u1EDD\u2026");
48170
+ let result;
48171
+ try {
48172
+ result = await createWorkOutbox({ ...creds2, root: (0, import_node_path17.join)(HOCAI_DIR, "work-outbox") }).flush();
48173
+ } catch (error51) {
48174
+ progress?.fail("\u0110\u1ED3ng b\u1ED9 b\xE1o c\xE1o ch\u01B0a ho\xE0n t\u1EA5t.");
48175
+ throw error51;
48176
+ }
48177
+ if (json3) process.stdout.write(JSON.stringify(result) + "\n");
48178
+ else {
48179
+ progress?.succeed(`\u0110\xE3 \u0111\u1ED3ng b\u1ED9 b\xE1o c\xE1o \xB7 g\u1EEDi ${result.sent} \xB7 c\xF2n ${result.pending}`);
48180
+ if (result.lastError) say2(` ${result.lastError}`);
48181
+ }
48066
48182
  process.exitCode = result.pending ? 2 : 0;
48067
48183
  return;
48068
48184
  }
48069
48185
  if (cmd === "report" || cmd === "doctor") {
48070
48186
  const flags = process.argv.slice(3);
48071
48187
  if (flags.some((flag) => flag !== "--json")) throw new Error("L\u1EC7nh report ch\u1EC9 nh\u1EADn tu\u1EF3 ch\u1ECDn --json.");
48072
- const report = await collectMachineReport({ helperVersion: VERSION });
48073
- process.stdout.write((flags.includes("--json") ? JSON.stringify(report, null, 2) : formatMachineReport(report)) + "\n");
48188
+ const json3 = flags.includes("--json");
48189
+ const progress = json3 ? null : createTerminalProgress();
48190
+ progress?.start("\u0110ang d\xF2 Claude, Codex v\xE0 tr\u1EA1ng th\xE1i m\xE1y\u2026");
48191
+ let report;
48192
+ try {
48193
+ report = await collectMachineReport({ helperVersion: VERSION });
48194
+ progress?.succeed("\u0110\xE3 d\xF2 xong tr\u1EA1ng th\xE1i m\xE1y v\xE0 c\xE1c tr\u1EE3 l\xFD AI.");
48195
+ } catch (error51) {
48196
+ progress?.fail("Kh\xF4ng d\xF2 xong tr\u1EA1ng th\xE1i m\xE1y.");
48197
+ throw error51;
48198
+ }
48199
+ process.stdout.write((json3 ? JSON.stringify(report, null, 2) : formatMachineReport(report)) + "\n");
48074
48200
  return;
48075
48201
  }
48076
48202
  if (cmd === "enable-usage") {
@@ -48111,25 +48237,37 @@ async function main() {
48111
48237
  return;
48112
48238
  }
48113
48239
  if (cmd === "quen") {
48240
+ const progress = createTerminalProgress();
48241
+ progress.start("\u0110ang ng\u1EAFt m\xE1y n\xE0y kh\u1ECFi hocAI\u2026");
48114
48242
  goDichVu();
48115
48243
  (0, import_node_fs10.rmSync)(CREDS, { force: true });
48116
- say2("\u0110\xE3 ng\u1EAFt k\u1EBFt n\u1ED1i v\xE0 g\u1EE1 d\u1ECBch v\u1EE5 n\u1EC1n tr\xEAn m\xE1y n\xE0y.");
48244
+ progress.succeed("\u0110\xE3 ng\u1EAFt k\u1EBFt n\u1ED1i v\xE0 g\u1EE1 d\u1ECBch v\u1EE5 n\u1EC1n tr\xEAn m\xE1y n\xE0y.");
48117
48245
  say2("Ch\u1EA1y l\u1EA1i `npx hocai-connect` \u0111\u1EC3 k\u1EBFt n\u1ED1i l\u1EA1i.");
48118
48246
  return;
48119
48247
  }
48120
48248
  if (cmd === "update") {
48121
48249
  const stored = loadCreds();
48122
- const [moi, running] = await Promise.all([
48123
- latestVersion(),
48124
- stored ? askPortOwner(PORT, stored.api.replace(/\/api$/, "")) : Promise.resolve(null)
48125
- ]);
48250
+ const progress = createTerminalProgress();
48251
+ progress.start("\u0110ang ki\u1EC3m tra phi\xEAn b\u1EA3n m\u1EDBi v\xE0 d\u1ECBch v\u1EE5 \u0111ang ch\u1EA1y\u2026");
48252
+ let moi;
48253
+ let running;
48254
+ try {
48255
+ ;
48256
+ [moi, running] = await Promise.all([
48257
+ latestVersion(),
48258
+ stored ? askPortOwner(PORT, stored.api.replace(/\/api$/, "")) : Promise.resolve(null)
48259
+ ]);
48260
+ } catch (error51) {
48261
+ progress.fail("Kh\xF4ng ki\u1EC3m tra \u0111\u01B0\u1EE3c phi\xEAn b\u1EA3n hi\u1EC7n t\u1EA1i.");
48262
+ throw error51;
48263
+ }
48126
48264
  const action = planHelperUpdate(VERSION, moi, running?.phienBan ?? null);
48127
48265
  if (action === "current") {
48128
- say2(`\u2713 D\u1ECBch v\u1EE5 \u0111ang ch\u1EA1y b\u1EA3n ${running?.phienBan}; kh\xF4ng c\u1EA7n c\xE0i l\u1EA1i.`);
48266
+ progress.succeed(`D\u1ECBch v\u1EE5 \u0111ang ch\u1EA1y b\u1EA3n ${running?.phienBan}; kh\xF4ng c\u1EA7n c\xE0i l\u1EA1i.`);
48129
48267
  return;
48130
48268
  }
48131
48269
  if (action === "download" && moi) {
48132
- say2(`C\xF3 b\u1EA3n m\u1EDBi: ${VERSION} \u2192 ${moi}. \u0110ang c\u1EADp nh\u1EADt\u2026`);
48270
+ progress.succeed(`C\xF3 b\u1EA3n m\u1EDBi ${VERSION} \u2192 ${moi}. B\u1EAFt \u0111\u1EA7u c\u1EADp nh\u1EADt.`);
48133
48271
  say2("");
48134
48272
  (0, import_node_fs10.mkdirSync)(NPM_CACHE, { recursive: true });
48135
48273
  const r = (0, import_node_child_process9.spawnSync)("npx", updateNpxArgs(moi, NPM_CACHE), {
@@ -48138,12 +48276,15 @@ async function main() {
48138
48276
  });
48139
48277
  process.exit(r.status ?? 1);
48140
48278
  }
48141
- say2(`\u0110ang c\xE0i bundle ${VERSION} v\xE0o d\u1ECBch v\u1EE5 (b\u1EA3n \u0111ang ch\u1EA1y: ${running?.phienBan ?? "ch\u01B0a c\xF3"}).`);
48279
+ progress.succeed(`\u0110\xE3 ch\u1ECDn bundle ${VERSION}; \u0111ang c\xE0i v\xE0o d\u1ECBch v\u1EE5 n\u1EC1n.`);
48142
48280
  cmd = void 0;
48143
48281
  }
48144
48282
  if (cmd === "stop") {
48283
+ const progress = createTerminalProgress();
48284
+ progress.start("\u0110ang t\u1EAFt v\xE0 g\u1EE1 d\u1ECBch v\u1EE5 n\u1EC1n\u2026");
48145
48285
  goDichVu();
48146
- say2("\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.");
48286
+ progress.succeed("\u0110\xE3 t\u1EAFt v\xE0 g\u1EE1 d\u1ECBch v\u1EE5 n\u1EC1n.");
48287
+ say2("Ch\xECa kho\xE1 v\u1EABn gi\u1EEF \u2014 ch\u1EA1y `npx hocai-connect` l\xE0 n\u1ED1i l\u1EA1i ngay.");
48147
48288
  return;
48148
48289
  }
48149
48290
  if (cmd === "status") {
@@ -48152,15 +48293,19 @@ async function main() {
48152
48293
  say2("M\xE1y n\xE0y ch\u01B0a n\u1ED1i. Ch\u1EA1y `npx hocai-connect`.");
48153
48294
  process.exit(1);
48154
48295
  }
48155
- const info = await askPortOwner(PORT, c.api.replace(/\/api$/, ""));
48296
+ const progress = createTerminalProgress();
48297
+ progress.start("\u0110ang ki\u1EC3m tra d\u1ECBch v\u1EE5 v\xE0 phi\xEAn b\u1EA3n hocai-connect\u2026");
48298
+ const [info, moi] = await Promise.all([
48299
+ askPortOwner(PORT, c.api.replace(/\/api$/, "")),
48300
+ latestVersion()
48301
+ ]);
48156
48302
  if (!info) {
48157
- say2(`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.`);
48303
+ progress.fail(`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.`);
48158
48304
  process.exit(1);
48159
48305
  }
48160
- say2(`\u2713 \u0110ang ch\u1EA1y \xB7 ${info.user?.ten ?? "(ch\xECa \u0111\xE3 b\u1ECB thu h\u1ED3i)"} \xB7 b\u1EA3n ${info.phienBan}`);
48306
+ progress.succeed(`\u0110ang ch\u1EA1y \xB7 ${info.user?.ten ?? "(ch\xECa \u0111\xE3 b\u1ECB thu h\u1ED3i)"} \xB7 b\u1EA3n ${info.phienBan}`);
48161
48307
  say2(` Nh\u1EADt k\xFD: ${plan().log}`);
48162
48308
  warnLines(doPerms());
48163
- const moi = await latestVersion();
48164
48309
  if (moi && info.phienBan && newerVersion(moi, info.phienBan)) {
48165
48310
  say2("");
48166
48311
  say2(` C\xF3 b\u1EA3n m\u1EDBi ${moi}. C\u1EADp nh\u1EADt: npx hocai-connect@latest update`);
@@ -48189,18 +48334,20 @@ async function main() {
48189
48334
  }
48190
48335
  const creds = loadCreds() ?? await login();
48191
48336
  process.env.HOCAI_API_URL = creds.api;
48337
+ const identityProgress = cmd === "run" ? null : createTerminalProgress();
48338
+ identityProgress?.start("\u0110ang x\xE1c minh t\xE0i kho\u1EA3n hocAI\u2026");
48192
48339
  const me = await fetchIdentity(creds.api, creds.token).catch(() => {
48193
- say2("");
48194
- say2("Kh\xF4ng n\u1ED1i \u0111\u01B0\u1EE3c t\u1EDBi hocAI \u0111\u1EC3 ki\u1EC3m tra t\xE0i kho\u1EA3n. Ki\u1EC3m tra m\u1EA1ng r\u1ED3i ch\u1EA1y l\u1EA1i \u2014");
48195
- say2("kh\xF4ng c\xF3 m\u1EA1ng th\xEC trang hocAI c\u0169ng kh\xF4ng m\u1EDF \u0111\u01B0\u1EE3c, n\xEAn ch\u1EA1y ti\u1EBFp c\u0169ng kh\xF4ng l\xE0m g\xEC \u0111\u01B0\u1EE3c.");
48340
+ identityProgress?.fail("Kh\xF4ng k\u1EBFt n\u1ED1i \u0111\u01B0\u1EE3c t\u1EDBi hocAI \u0111\u1EC3 ki\u1EC3m tra t\xE0i kho\u1EA3n.");
48341
+ say2("Ki\u1EC3m tra m\u1EA1ng r\u1ED3i ch\u1EA1y l\u1EA1i \u2014 kh\xF4ng c\xF3 m\u1EA1ng th\xEC trang hocAI c\u0169ng kh\xF4ng m\u1EDF \u0111\u01B0\u1EE3c.");
48196
48342
  process.exit(1);
48197
48343
  });
48198
48344
  if (!me) {
48199
- say2("");
48200
- say2("Token tr\xEAn m\xE1y n\xE0y kh\xF4ng d\xF9ng \u0111\u01B0\u1EE3c n\u1EEFa \u2014 \u0111\xE3 b\u1ECB thu h\u1ED3i, ho\u1EB7c t\xE0i kho\u1EA3n \u0111\xE3 b\u1ECB kho\xE1.");
48345
+ identityProgress?.fail("Token tr\xEAn m\xE1y n\xE0y kh\xF4ng d\xF9ng \u0111\u01B0\u1EE3c n\u1EEFa.");
48346
+ say2("Token c\xF3 th\u1EC3 \u0111\xE3 b\u1ECB thu h\u1ED3i, ho\u1EB7c t\xE0i kho\u1EA3n \u0111\xE3 b\u1ECB kho\xE1.");
48201
48347
  say2("Ch\u1EA1y `npx hocai-connect quen` r\u1ED3i ch\u1EA1y l\u1EA1i `npx hocai-connect` \u0111\u1EC3 k\u1EBFt n\u1ED1i l\u1EA1i.");
48202
48348
  process.exit(1);
48203
48349
  }
48350
+ identityProgress?.succeed(`\u0110\xE3 x\xE1c minh t\xE0i kho\u1EA3n \xB7 ${me.ten}`);
48204
48351
  const identity = createIdentityCache({
48205
48352
  fetchIdentity: () => fetchIdentity(creds.api, creds.token),
48206
48353
  seed: me,
@@ -48210,6 +48357,19 @@ async function main() {
48210
48357
  if (cmd !== "run") {
48211
48358
  const xong = caiDichVu();
48212
48359
  const sanSang = doTroLy();
48360
+ if (xong) {
48361
+ const startupProgress = createTerminalProgress();
48362
+ startupProgress.start("\u0110ang ch\u1EDD d\u1ECBch v\u1EE5 n\u1EC1n kh\u1EDFi \u0111\u1ED9ng v\xE0 ph\u1EA3n h\u1ED3i\u2026");
48363
+ await new Promise((r) => setTimeout(r, 2500));
48364
+ const info = await askPortOwner(PORT, WEB());
48365
+ if (!info) {
48366
+ startupProgress.fail("D\u1ECBch v\u1EE5 \u0111\xE3 c\xE0i nh\u01B0ng ch\u01B0a ph\u1EA3n h\u1ED3i \u1EDF c\u1ED5ng " + PORT + ".");
48367
+ say2(` Xem nh\u1EADt k\xFD: npx hocai-connect logs`);
48368
+ process.exit(1);
48369
+ }
48370
+ startupProgress.succeed(`D\u1ECBch v\u1EE5 n\u1EC1n \u0111\xE3 s\u1EB5n s\xE0ng \xB7 b\u1EA3n ${info.phienBan}`);
48371
+ warnLines(doPerms());
48372
+ }
48213
48373
  say2("");
48214
48374
  say2("\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");
48215
48375
  say2(sanSang ? ` \u2713 \u0110\xE3 n\u1ED1i m\xE1y \xB7 ${me.ten}` : ` \u2713 \u0110\xE3 n\u1ED1i m\xE1y \xB7 ${me.ten} \u2014 nh\u01B0ng xem c\u1EA3nh b\xE1o \u1EDF tr\xEAn`);
@@ -48221,17 +48381,6 @@ async function main() {
48221
48381
  say2(" Ng\u1EAFt k\u1EBFt n\u1ED1i: npx hocai-connect stop");
48222
48382
  }
48223
48383
  say2("\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");
48224
- if (xong) {
48225
- await new Promise((r) => setTimeout(r, 2500));
48226
- const info = await askPortOwner(PORT, WEB());
48227
- if (!info) {
48228
- say2("");
48229
- say2("\u26A0 D\u1ECBch v\u1EE5 \u0111\xE3 c\xE0i nh\u01B0ng ch\u01B0a th\u1EA5y tr\u1EA3 l\u1EDDi \u1EDF c\u1ED5ng " + PORT + ".");
48230
- say2(` Xem nh\u1EADt k\xFD: npx hocai-connect logs`);
48231
- process.exit(1);
48232
- }
48233
- warnLines(doPerms());
48234
- }
48235
48384
  if (quyen && quyen.fixCache.length) {
48236
48385
  say2("");
48237
48386
  say2("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,");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hocai-connect",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "Nối AI trên máy vào hocAI, chat, làm việc và gửi báo cáo qua MCP",
5
5
  "bin": {
6
6
  "hocai-connect": "bin.js"