chatlab-cli 0.21.1 → 0.22.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.
Files changed (60) hide show
  1. package/README.md +5 -5
  2. package/dist/{chunk-OQVKZTVD.mjs → chunk-3UBWLWXB.mjs} +2 -2
  3. package/dist/{chunk-AIR7EAF4.mjs → chunk-4U45E7TO.mjs} +2 -2
  4. package/dist/{chunk-OZWXLRJL.mjs → chunk-6GLMVWGA.mjs} +24 -15
  5. package/dist/chunk-6GLMVWGA.mjs.map +1 -0
  6. package/dist/{chunk-2AIOU3PW.mjs → chunk-6NB475AA.mjs} +12 -3
  7. package/dist/chunk-6NB475AA.mjs.map +1 -0
  8. package/dist/{chunk-LI4X52E7.mjs → chunk-AMMSVJG4.mjs} +325 -94
  9. package/dist/chunk-AMMSVJG4.mjs.map +1 -0
  10. package/dist/{chunk-4GI2UPCS.mjs → chunk-D2XJ4Z7G.mjs} +2 -2
  11. package/dist/{chunk-7HQWGLX6.mjs → chunk-QJQJIUUS.mjs} +102 -96
  12. package/dist/chunk-QJQJIUUS.mjs.map +1 -0
  13. package/dist/chunk-VSOWNKPA.mjs +49 -0
  14. package/dist/cli.mjs +4 -3
  15. package/dist/{http-DHQI4G5J.mjs → http-R5UECMPJ.mjs} +8 -7
  16. package/dist/{import-CQWGIMZQ.mjs → import-3LOWRXWA.mjs} +5 -4
  17. package/dist/index.mjs +8 -7
  18. package/dist/{mcp-7Q3FEI3Z.mjs → mcp-WBHNLED2.mjs} +8 -7
  19. package/dist/mcp-WBHNLED2.mjs.map +1 -0
  20. package/dist/{src-QBT5SYW5.mjs → src-UHM2UDRD.mjs} +3 -2
  21. package/dist/{stream-import-VG7RP6KJ.mjs → stream-import-V6Z7DXSW.mjs} +4 -3
  22. package/dist/stream-import-V6Z7DXSW.mjs.map +1 -0
  23. package/dist/update-checker-MQMQ6A4B.mjs +191 -0
  24. package/dist/update-checker-MQMQ6A4B.mjs.map +1 -0
  25. package/dist-web/assets/{DebugToolsPanel-CoBtqb--.css → DebugToolsPanel-DkbsB6lr.css} +1 -1
  26. package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-CpFGhsl5.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-CxYyne-Q.js} +5 -5
  27. package/dist-web/assets/{EChartWordcloud-BYLFxPAX.js → EChartWordcloud-Ubal_aYg.js} +1 -1
  28. package/dist-web/assets/{MessageExportModal-DTgxz1eQ.js → MessageExportModal-De5_tX6a.js} +1 -1
  29. package/dist-web/assets/{electron-CTK4NJag.js → electron-CRSL7qPM.js} +1 -1
  30. package/dist-web/assets/{fetch-C2vUkdnA.js → fetch-Q-PqsiMb.js} +1 -1
  31. package/dist-web/assets/{fetch-CTZXLLcn.js → fetch-cFjLAPG2.js} +1 -1
  32. package/dist-web/assets/{index-DeG0EHOT.js → index-BJUGnYn5.js} +1 -1
  33. package/dist-web/assets/{index-DuhN8jAf.js → index-B_31fXeB.js} +2 -2
  34. package/dist-web/assets/index-CbOwHYzO.css +1 -0
  35. package/dist-web/assets/index-DKMUn8F5.js +173 -0
  36. package/dist-web/assets/{index-C4B0hv6C.js → index-D_ksezTw.js} +4 -4
  37. package/dist-web/assets/index-Dhg3SDb6.js +7 -0
  38. package/dist-web/assets/logo-DXIuG_WE.svg +17 -0
  39. package/dist-web/assets/{vendor-echarts-C13vDgZW.js → vendor-echarts-C5u62NnM.js} +1 -1
  40. package/dist-web/assets/{vendor-echarts-wordcloud-uVdwYsYa.js → vendor-echarts-wordcloud-CZ9gsX8l.js} +1 -1
  41. package/dist-web/assets/{vendor-nuxt-ui-CYMNNdeD.js → vendor-nuxt-ui-7OAuiz_i.js} +1 -1
  42. package/dist-web/assets/{vendor-zrender-5DcYjSZk.js → vendor-zrender-DFl4U2Oe.js} +1 -1
  43. package/dist-web/assets/{web-DImo6Kjz.js → web-CZe0Ismu.js} +1 -1
  44. package/dist-web/index.html +3 -3
  45. package/package.json +4 -3
  46. package/dist/chunk-2AIOU3PW.mjs.map +0 -1
  47. package/dist/chunk-7HQWGLX6.mjs.map +0 -1
  48. package/dist/chunk-LI4X52E7.mjs.map +0 -1
  49. package/dist/chunk-OZWXLRJL.mjs.map +0 -1
  50. package/dist/mcp-7Q3FEI3Z.mjs.map +0 -1
  51. package/dist-web/assets/index-B8867dX7.css +0 -1
  52. package/dist-web/assets/index-DUXf21MT.js +0 -173
  53. package/dist-web/assets/index-DZiH2cC1.js +0 -7
  54. /package/dist/{chunk-OQVKZTVD.mjs.map → chunk-3UBWLWXB.mjs.map} +0 -0
  55. /package/dist/{chunk-AIR7EAF4.mjs.map → chunk-4U45E7TO.mjs.map} +0 -0
  56. /package/dist/{chunk-4GI2UPCS.mjs.map → chunk-D2XJ4Z7G.mjs.map} +0 -0
  57. /package/dist/{http-DHQI4G5J.mjs.map → chunk-VSOWNKPA.mjs.map} +0 -0
  58. /package/dist/{import-CQWGIMZQ.mjs.map → http-R5UECMPJ.mjs.map} +0 -0
  59. /package/dist/{src-QBT5SYW5.mjs.map → import-3LOWRXWA.mjs.map} +0 -0
  60. /package/dist/{stream-import-VG7RP6KJ.mjs.map → src-UHM2UDRD.mjs.map} +0 -0
@@ -7,20 +7,21 @@ const __dirname = __pathDirname(__filename);
7
7
  import {
8
8
  importData,
9
9
  parseFile
10
- } from "./chunk-OQVKZTVD.mjs";
10
+ } from "./chunk-3UBWLWXB.mjs";
11
11
  import {
12
12
  analyzeIncrementalImport,
13
13
  analyzeNewImport,
14
14
  incrementalImport,
15
15
  streamImport
16
- } from "./chunk-AIR7EAF4.mjs";
16
+ } from "./chunk-4U45E7TO.mjs";
17
17
  import {
18
18
  AGENT_TOOL_REGISTRY,
19
19
  CoreDataProvider
20
- } from "./chunk-4GI2UPCS.mjs";
20
+ } from "./chunk-D2XJ4Z7G.mjs";
21
21
  import {
22
- getVersion
23
- } from "./chunk-2AIOU3PW.mjs";
22
+ getVersion,
23
+ resolveCliPath
24
+ } from "./chunk-6NB475AA.mjs";
24
25
  import {
25
26
  AIConversationManager,
26
27
  ALL_MIGRATIONS,
@@ -114,11 +115,10 @@ import {
114
115
  verifyCliDataPath,
115
116
  writeAuthProfile,
116
117
  writeConfigField
117
- } from "./chunk-7HQWGLX6.mjs";
118
+ } from "./chunk-QJQJIUUS.mjs";
118
119
 
119
120
  // src/http/index.ts
120
121
  import * as fs14 from "fs";
121
- import * as path15 from "path";
122
122
  import * as crypto5 from "crypto";
123
123
 
124
124
  // src/http/server.ts
@@ -207,6 +207,10 @@ async function authHook(request, reply) {
207
207
  if (!cachedToken) return;
208
208
  if (request.url.startsWith("/_web/")) return;
209
209
  if (webModeEnabled && !request.url.startsWith("/api/")) return;
210
+ return requireBearerToken(request, reply);
211
+ }
212
+ function requireBearerToken(request, reply) {
213
+ if (!cachedToken) return;
210
214
  const authHeader = request.headers.authorization;
211
215
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
212
216
  const err = unauthorized();
@@ -492,7 +496,7 @@ function registerSessionRoutes(server2, dbManager2) {
492
496
 
493
497
  // src/http/routes/web/index.ts
494
498
  import * as os3 from "os";
495
- import * as path7 from "path";
499
+ import * as path6 from "path";
496
500
 
497
501
  // src/merger/merge-cache.ts
498
502
  import * as fs from "fs";
@@ -653,7 +657,6 @@ function registerMemberRoutes(server2, adapter) {
653
657
 
654
658
  // src/http/routes/web/helpers.ts
655
659
  import * as fs2 from "fs";
656
- import * as path2 from "path";
657
660
  function parseTimeFilter(query) {
658
661
  const { startTs, endTs, memberId } = query;
659
662
  if (!startTs && !endTs && !memberId) return void 0;
@@ -665,7 +668,7 @@ function parseTimeFilter(query) {
665
668
  }
666
669
  function resolveNativeBinding() {
667
670
  if (process.versions.electron) return void 0;
668
- const nativePath = path2.resolve(__dirname, "../../../../native/better_sqlite3.node");
671
+ const nativePath = resolveCliPath("native/better_sqlite3.node");
669
672
  if (fs2.existsSync(nativePath)) return nativePath;
670
673
  return void 0;
671
674
  }
@@ -879,10 +882,10 @@ function registerSessionIndexRoutes(server2, adapter) {
879
882
 
880
883
  // src/ai/llm-config.ts
881
884
  import * as fs3 from "fs";
882
- import * as path3 from "path";
885
+ import * as path2 from "path";
883
886
  import { randomUUID as randomUUID2 } from "crypto";
884
887
  function loadLlmConfig(aiDataDir) {
885
- const configPath = path3.join(aiDataDir, "llm-config.json");
888
+ const configPath = path2.join(aiDataDir, "llm-config.json");
886
889
  if (!fs3.existsSync(configPath)) {
887
890
  return { configs: [], defaultAssistant: null, fastModel: null };
888
891
  }
@@ -924,7 +927,7 @@ function getDefaultAssistantConfig(aiDataDir) {
924
927
  }
925
928
  var MAX_CONFIG_COUNT = 99;
926
929
  function saveLlmConfig(aiDataDir, store) {
927
- const configPath = path3.join(aiDataDir, "llm-config.json");
930
+ const configPath = path2.join(aiDataDir, "llm-config.json");
928
931
  const toSave = {
929
932
  ...store,
930
933
  configs: store.configs.map((c) => {
@@ -1028,7 +1031,7 @@ function setFastModelSlot(aiDataDir, slot) {
1028
1031
  return { success: true };
1029
1032
  }
1030
1033
  function loadRawConfigStore(aiDataDir) {
1031
- const configPath = path3.join(aiDataDir, "llm-config.json");
1034
+ const configPath = path2.join(aiDataDir, "llm-config.json");
1032
1035
  if (!fs3.existsSync(configPath)) {
1033
1036
  return { configs: [], defaultAssistant: null, fastModel: null };
1034
1037
  }
@@ -1088,13 +1091,13 @@ function registerSummaryRoutes(server2, dbManager2, adapter) {
1088
1091
  // src/http/routes/web/import.ts
1089
1092
  import * as fs4 from "fs";
1090
1093
  import * as os from "os";
1091
- import * as path4 from "path";
1094
+ import * as path3 from "path";
1092
1095
  var DEMO_BASE_URL = "https://chatlab.fun/assets/demo";
1093
1096
  function cleanupTemp(...paths) {
1094
1097
  for (const p of paths) {
1095
1098
  try {
1096
- const stat = fs4.statSync(p);
1097
- if (stat.isDirectory()) {
1099
+ const stat2 = fs4.statSync(p);
1100
+ if (stat2.isDirectory()) {
1098
1101
  fs4.rmSync(p, { recursive: true, force: true });
1099
1102
  } else {
1100
1103
  fs4.unlinkSync(p);
@@ -1110,8 +1113,8 @@ function registerImportRoutes(server2, dbManager2) {
1110
1113
  server2.post("/_web/detect-format", async (request, reply) => {
1111
1114
  const data = await request.file();
1112
1115
  if (!data) return reply.code(400).send({ error: "No file uploaded" });
1113
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-detect-"));
1114
- const tmpPath = path4.join(tmpDir, data.filename || "upload");
1116
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-detect-"));
1117
+ const tmpPath = path3.join(tmpDir, data.filename || "upload");
1115
1118
  try {
1116
1119
  const chunks = [];
1117
1120
  for await (const chunk of data.file) {
@@ -1128,8 +1131,8 @@ function registerImportRoutes(server2, dbManager2) {
1128
1131
  server2.post("/_web/scan-multi-chat", async (request, reply) => {
1129
1132
  const data = await request.file();
1130
1133
  if (!data) return reply.code(400).send({ error: "No file uploaded" });
1131
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-scan-"));
1132
- const tmpPath = path4.join(tmpDir, data.filename || "upload");
1134
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-scan-"));
1135
+ const tmpPath = path3.join(tmpDir, data.filename || "upload");
1133
1136
  try {
1134
1137
  const chunks = [];
1135
1138
  for await (const chunk of data.file) {
@@ -1145,8 +1148,8 @@ function registerImportRoutes(server2, dbManager2) {
1145
1148
  server2.post("/_web/import", async (request, reply) => {
1146
1149
  const data = await request.file();
1147
1150
  if (!data) return reply.code(400).send({ error: "No file uploaded" });
1148
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-import-"));
1149
- const tmpPath = path4.join(tmpDir, data.filename || "upload");
1151
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-import-"));
1152
+ const tmpPath = path3.join(tmpDir, data.filename || "upload");
1150
1153
  const chunks = [];
1151
1154
  for await (const chunk of data.file) {
1152
1155
  chunks.push(chunk);
@@ -1194,7 +1197,7 @@ data: ${JSON.stringify(eventData)}
1194
1197
  server2.post("/_web/import-directory", async (request, reply) => {
1195
1198
  const parts = request.parts();
1196
1199
  if (!parts) return reply.code(400).send({ error: "No files uploaded" });
1197
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-dir-import-"));
1200
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-dir-import-"));
1198
1201
  const relativePaths = [];
1199
1202
  const fileBuffers = [];
1200
1203
  try {
@@ -1222,9 +1225,9 @@ data: ${JSON.stringify(eventData)}
1222
1225
  if (segments.length > 1) {
1223
1226
  relPath = segments.slice(1).join("/");
1224
1227
  }
1225
- const targetPath = path4.resolve(tmpDir, relPath);
1226
- if (!targetPath.startsWith(tmpDir + path4.sep)) continue;
1227
- fs4.mkdirSync(path4.dirname(targetPath), { recursive: true });
1228
+ const targetPath = path3.resolve(tmpDir, relPath);
1229
+ if (!targetPath.startsWith(tmpDir + path3.sep)) continue;
1230
+ fs4.mkdirSync(path3.dirname(targetPath), { recursive: true });
1228
1231
  fs4.writeFileSync(targetPath, fileBuffers[i].data);
1229
1232
  }
1230
1233
  const entryPath = findEntryFileInDirectory(tmpDir);
@@ -1270,8 +1273,8 @@ data: ${JSON.stringify({ success: false, error: err instanceof Error ? err.messa
1270
1273
  const sessionId = request.params.id;
1271
1274
  const data = await request.file();
1272
1275
  if (!data) return reply.code(400).send({ error: "No file uploaded" });
1273
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-inc-"));
1274
- const tmpPath = path4.join(tmpDir, data.filename || "upload");
1276
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-inc-"));
1277
+ const tmpPath = path3.join(tmpDir, data.filename || "upload");
1275
1278
  const chunks = [];
1276
1279
  for await (const chunk of data.file) {
1277
1280
  chunks.push(chunk);
@@ -1308,8 +1311,8 @@ data: ${JSON.stringify(eventData)}
1308
1311
  const sessionId = request.params.id;
1309
1312
  const data = await request.file();
1310
1313
  if (!data) return reply.code(400).send({ error: "No file uploaded" });
1311
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-analyze-"));
1312
- const tmpPath = path4.join(tmpDir, data.filename || "upload");
1314
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-analyze-"));
1315
+ const tmpPath = path3.join(tmpDir, data.filename || "upload");
1313
1316
  const chunks = [];
1314
1317
  for await (const chunk of data.file) {
1315
1318
  chunks.push(chunk);
@@ -1326,8 +1329,8 @@ data: ${JSON.stringify(eventData)}
1326
1329
  server2.post("/_web/import/analyze", async (request, reply) => {
1327
1330
  const data = await request.file();
1328
1331
  if (!data) return reply.code(400).send({ error: "No file uploaded" });
1329
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-analyze-"));
1330
- const tmpPath = path4.join(tmpDir, data.filename || "upload");
1332
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-analyze-"));
1333
+ const tmpPath = path3.join(tmpDir, data.filename || "upload");
1331
1334
  const chunks = [];
1332
1335
  for await (const chunk of data.file) {
1333
1336
  chunks.push(chunk);
@@ -1355,9 +1358,9 @@ data: ${JSON.stringify(eventData)}
1355
1358
 
1356
1359
  `);
1357
1360
  }
1358
- const tmpDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "chatlab-demo-"));
1359
- const groupPath = path4.join(tmpDir, "demo-group.json");
1360
- const privatePath = path4.join(tmpDir, "demo-private.json");
1361
+ const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-demo-"));
1362
+ const groupPath = path3.join(tmpDir, "demo-group.json");
1363
+ const privatePath = path3.join(tmpDir, "demo-private.json");
1361
1364
  try {
1362
1365
  sendEvent("progress", { stage: "downloading", current: 1, total: 2 });
1363
1366
  const groupResp = await fetch(`${DEMO_BASE_URL}/${locale}/demo-group.json`, {
@@ -1397,13 +1400,13 @@ data: ${JSON.stringify(eventData)}
1397
1400
  // src/http/routes/web/merge.ts
1398
1401
  import * as fs5 from "fs";
1399
1402
  import * as os2 from "os";
1400
- import * as path5 from "path";
1403
+ import * as path4 from "path";
1401
1404
  function registerMergeRoutes(server2, dbManager2, mergeCache) {
1402
1405
  server2.post("/_web/merge/parse", async (request, reply) => {
1403
1406
  const data = await request.file();
1404
1407
  if (!data) return reply.code(400).send({ error: "No file uploaded" });
1405
- const tmpDir = fs5.mkdtempSync(path5.join(os2.tmpdir(), "chatlab-merge-"));
1406
- const tmpPath = path5.join(tmpDir, data.filename || "upload");
1408
+ const tmpDir = fs5.mkdtempSync(path4.join(os2.tmpdir(), "chatlab-merge-"));
1409
+ const tmpPath = path4.join(tmpDir, data.filename || "upload");
1407
1410
  const chunks = [];
1408
1411
  for await (const chunk of data.file) {
1409
1412
  chunks.push(chunk);
@@ -1412,7 +1415,7 @@ function registerMergeRoutes(server2, dbManager2, mergeCache) {
1412
1415
  try {
1413
1416
  const result = await streamParseFileInfo(tmpPath, {
1414
1417
  createTempDatabase(sourceFilePath) {
1415
- return mergeCache.createTempDatabase(path5.basename(sourceFilePath));
1418
+ return mergeCache.createTempDatabase(path4.basename(sourceFilePath));
1416
1419
  },
1417
1420
  onProgress() {
1418
1421
  }
@@ -1477,10 +1480,10 @@ function registerMergeRoutes(server2, dbManager2, mergeCache) {
1477
1480
  const merged = buildMergedOutput(dataSources, outputName);
1478
1481
  let sessionId;
1479
1482
  if (andImport) {
1480
- const { streamImport: serverStreamImport } = await import("./stream-import-VG7RP6KJ.mjs");
1483
+ const { streamImport: serverStreamImport } = await import("./stream-import-V6Z7DXSW.mjs");
1481
1484
  const jsonData = JSON.stringify(merged.chatLabData);
1482
- const tmpDir = fs5.mkdtempSync(path5.join(os2.tmpdir(), "chatlab-merged-"));
1483
- const tmpPath = path5.join(tmpDir, `${outputName}.json`);
1485
+ const tmpDir = fs5.mkdtempSync(path4.join(os2.tmpdir(), "chatlab-merged-"));
1486
+ const tmpPath = path4.join(tmpDir, `${outputName}.json`);
1484
1487
  fs5.writeFileSync(tmpPath, jsonData, "utf-8");
1485
1488
  try {
1486
1489
  const importResult = await serverStreamImport(dbManager2, tmpPath);
@@ -1530,7 +1533,7 @@ function registerMergeRoutes(server2, dbManager2, mergeCache) {
1530
1533
  const db = ensureDb2(dbManager2, sid);
1531
1534
  const exported = exportSessionToJson(db);
1532
1535
  const { db: tempDb, tempDbPath } = mergeCache.createTempDatabase(exported.meta.name);
1533
- const { TempDbWriter } = await import("./src-QBT5SYW5.mjs");
1536
+ const { TempDbWriter } = await import("./src-UHM2UDRD.mjs");
1534
1537
  const writer = new TempDbWriter(tempDb);
1535
1538
  writer.writeMeta({
1536
1539
  name: exported.meta.name,
@@ -1592,8 +1595,192 @@ function registerExportRoutes(server2, adapter) {
1592
1595
 
1593
1596
  // src/http/routes/web/cache.ts
1594
1597
  import * as fs6 from "fs";
1595
- import * as path6 from "path";
1596
- function registerCacheRoutes(server2, downloadsDir) {
1598
+ import * as fsp from "fs/promises";
1599
+ import * as path5 from "path";
1600
+ import { execFile } from "child_process";
1601
+ function runExecFile(file, args, runner = execFile) {
1602
+ return new Promise((resolve2, reject) => {
1603
+ runner(file, args, (error) => {
1604
+ if (error) {
1605
+ reject(error);
1606
+ return;
1607
+ }
1608
+ resolve2();
1609
+ });
1610
+ });
1611
+ }
1612
+ async function openDirectoryPath(dirPath, platform = process.platform, runner) {
1613
+ if (platform === "darwin") {
1614
+ await runExecFile("open", [dirPath], runner);
1615
+ } else if (platform === "win32") {
1616
+ await runExecFile("explorer.exe", [dirPath], runner);
1617
+ } else {
1618
+ await runExecFile("xdg-open", [dirPath], runner);
1619
+ }
1620
+ }
1621
+ async function showPathInFolder(filePath, platform = process.platform, runner) {
1622
+ if (platform === "darwin") {
1623
+ await runExecFile("open", ["-R", filePath], runner);
1624
+ } else if (platform === "win32") {
1625
+ await runExecFile("explorer.exe", [`/select,${filePath}`], runner);
1626
+ } else {
1627
+ await runExecFile("xdg-open", [path5.dirname(filePath)], runner);
1628
+ }
1629
+ }
1630
+ async function getDirSize(dirPath) {
1631
+ let totalSize = 0;
1632
+ try {
1633
+ if (!fs6.existsSync(dirPath)) return 0;
1634
+ const files = await fsp.readdir(dirPath, { withFileTypes: true });
1635
+ for (const file of files) {
1636
+ const filePath = path5.join(dirPath, file.name);
1637
+ if (file.isDirectory()) {
1638
+ totalSize += await getDirSize(filePath);
1639
+ } else {
1640
+ const stat2 = await fsp.stat(filePath);
1641
+ totalSize += stat2.size;
1642
+ }
1643
+ }
1644
+ } catch {
1645
+ }
1646
+ return totalSize;
1647
+ }
1648
+ async function getFileCount(dirPath) {
1649
+ let count = 0;
1650
+ try {
1651
+ if (!fs6.existsSync(dirPath)) return 0;
1652
+ const files = await fsp.readdir(dirPath, { withFileTypes: true });
1653
+ for (const file of files) {
1654
+ const filePath = path5.join(dirPath, file.name);
1655
+ if (file.isDirectory()) {
1656
+ count += await getFileCount(filePath);
1657
+ } else {
1658
+ count++;
1659
+ }
1660
+ }
1661
+ } catch {
1662
+ }
1663
+ return count;
1664
+ }
1665
+ function registerCacheRoutes(server2, pathProvider) {
1666
+ const downloadsDir = pathProvider.getDownloadsDir();
1667
+ server2.get("/_web/cache/info", async () => {
1668
+ const directories = [
1669
+ {
1670
+ id: "databases",
1671
+ name: "settings.storage.cache.databases.name",
1672
+ description: "settings.storage.cache.databases.description",
1673
+ path: pathProvider.getDatabaseDir(),
1674
+ icon: "i-heroicons-circle-stack",
1675
+ canClear: false
1676
+ },
1677
+ {
1678
+ id: "ai",
1679
+ name: "settings.storage.cache.ai.name",
1680
+ description: "settings.storage.cache.ai.description",
1681
+ path: pathProvider.getAiDataDir(),
1682
+ icon: "i-heroicons-sparkles",
1683
+ canClear: false
1684
+ },
1685
+ {
1686
+ id: "cache",
1687
+ name: "settings.storage.cache.statsCache.name",
1688
+ description: "settings.storage.cache.statsCache.description",
1689
+ path: pathProvider.getCacheDir(),
1690
+ icon: "i-heroicons-bolt",
1691
+ canClear: true
1692
+ },
1693
+ {
1694
+ id: "logs",
1695
+ name: "settings.storage.cache.logs.name",
1696
+ description: "settings.storage.cache.logs.description",
1697
+ path: pathProvider.getLogsDir(),
1698
+ icon: "i-heroicons-document-text",
1699
+ canClear: true
1700
+ }
1701
+ ];
1702
+ const results = await Promise.all(
1703
+ directories.map(async (dir) => {
1704
+ const [size, fileCount] = await Promise.all([getDirSize(dir.path), getFileCount(dir.path)]);
1705
+ return { ...dir, size, fileCount, exists: fs6.existsSync(dir.path) };
1706
+ })
1707
+ );
1708
+ return {
1709
+ baseDir: pathProvider.getUserDataDir(),
1710
+ systemDir: pathProvider.getSystemDir(),
1711
+ directories: results,
1712
+ totalSize: results.reduce((sum, d) => sum + d.size, 0)
1713
+ };
1714
+ });
1715
+ server2.post("/_web/cache/clear", async (request) => {
1716
+ const { cacheId } = request.body;
1717
+ const allowedDirs = {
1718
+ cache: pathProvider.getCacheDir(),
1719
+ logs: pathProvider.getLogsDir()
1720
+ };
1721
+ const dirPath = allowedDirs[cacheId];
1722
+ if (!dirPath) return { success: false, error: "Not allowed to clear this directory" };
1723
+ if (!fs6.existsSync(dirPath)) return { success: true };
1724
+ const files = await fsp.readdir(dirPath);
1725
+ for (const file of files) {
1726
+ const filePath = path5.join(dirPath, file);
1727
+ const stat2 = await fsp.stat(filePath);
1728
+ if (stat2.isDirectory()) {
1729
+ await fsp.rm(filePath, { recursive: true });
1730
+ } else {
1731
+ await fsp.unlink(filePath);
1732
+ }
1733
+ }
1734
+ return { success: true };
1735
+ });
1736
+ server2.post("/_web/cache/open-dir", async (request) => {
1737
+ const { cacheId } = request.body;
1738
+ const dirPaths = {
1739
+ base: pathProvider.getUserDataDir(),
1740
+ system: pathProvider.getSystemDir(),
1741
+ databases: pathProvider.getDatabaseDir(),
1742
+ cache: pathProvider.getCacheDir(),
1743
+ ai: pathProvider.getAiDataDir(),
1744
+ logs: pathProvider.getLogsDir(),
1745
+ downloads: downloadsDir
1746
+ };
1747
+ const dirPath = dirPaths[cacheId];
1748
+ if (!dirPath) return { success: false, error: "Unknown directory" };
1749
+ if (!fs6.existsSync(dirPath)) {
1750
+ await fsp.mkdir(dirPath, { recursive: true });
1751
+ }
1752
+ try {
1753
+ await openDirectoryPath(dirPath);
1754
+ } catch (error) {
1755
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1756
+ }
1757
+ return { success: true };
1758
+ });
1759
+ server2.get("/_web/cache/data-dir", async () => {
1760
+ const config = loadConfig();
1761
+ const isCustom = Boolean(config.data.user_data_dir || process.env.CHATLAB_DATA_DIR);
1762
+ return { path: pathProvider.getUserDataDir(), isCustom };
1763
+ });
1764
+ server2.get("/_web/cache/latest-import-log", async () => {
1765
+ const importLogDir = path5.join(pathProvider.getLogsDir(), "import");
1766
+ if (!fs6.existsSync(importLogDir)) {
1767
+ return { success: false, error: "Log directory not found" };
1768
+ }
1769
+ const files = await fsp.readdir(importLogDir);
1770
+ const logFiles = files.filter((f) => f.startsWith("import_") && f.endsWith(".log"));
1771
+ if (logFiles.length === 0) {
1772
+ return { success: false, error: "No import logs found" };
1773
+ }
1774
+ const fileStats = await Promise.all(
1775
+ logFiles.map(async (f) => {
1776
+ const filePath = path5.join(importLogDir, f);
1777
+ const stat2 = await fsp.stat(filePath);
1778
+ return { name: f, path: filePath, mtime: stat2.mtime.getTime() };
1779
+ })
1780
+ );
1781
+ fileStats.sort((a, b) => b.mtime - a.mtime);
1782
+ return { success: true, path: fileStats[0].path, name: fileStats[0].name };
1783
+ });
1597
1784
  server2.post("/_web/cache/save-to-downloads", async (request) => {
1598
1785
  const { filename, dataUrl } = request.body;
1599
1786
  if (!filename || !dataUrl) {
@@ -1605,7 +1792,7 @@ function registerCacheRoutes(server2, downloadsDir) {
1605
1792
  if (!fs6.existsSync(downloadsDir)) {
1606
1793
  fs6.mkdirSync(downloadsDir, { recursive: true });
1607
1794
  }
1608
- const filePath = path6.join(downloadsDir, filename);
1795
+ const filePath = path5.join(downloadsDir, filename);
1609
1796
  fs6.writeFileSync(filePath, buffer);
1610
1797
  return { success: true, filePath };
1611
1798
  });
@@ -1614,26 +1801,46 @@ function registerCacheRoutes(server2, downloadsDir) {
1614
1801
  if (!filePath) {
1615
1802
  return { success: false, error: "filePath is required" };
1616
1803
  }
1617
- const { exec } = await import("child_process");
1618
- const platform = process.platform;
1619
- const dir = path6.dirname(filePath);
1620
- if (platform === "darwin") {
1621
- exec(`open -R "${filePath}"`);
1622
- } else if (platform === "win32") {
1623
- exec(`explorer /select,"${filePath}"`);
1624
- } else {
1625
- exec(`xdg-open "${dir}"`);
1804
+ try {
1805
+ await showPathInFolder(filePath);
1806
+ } catch (error) {
1807
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1626
1808
  }
1627
1809
  return { success: true };
1628
1810
  });
1629
1811
  }
1630
1812
 
1631
1813
  // src/http/routes/web/index.ts
1814
+ function isNewerVersion(latest, current) {
1815
+ const parse = (v) => {
1816
+ const [core, pre] = v.split("-", 2);
1817
+ const parts = core.split(".").map(Number);
1818
+ return { major: parts[0] || 0, minor: parts[1] || 0, patch: parts[2] || 0, pre };
1819
+ };
1820
+ const l = parse(latest);
1821
+ const c = parse(current);
1822
+ if (l.major !== c.major) return l.major > c.major;
1823
+ if (l.minor !== c.minor) return l.minor > c.minor;
1824
+ if (l.patch !== c.patch) return l.patch > c.patch;
1825
+ if (c.pre && !l.pre) return true;
1826
+ return false;
1827
+ }
1632
1828
  function registerWebRoutes(server2, dbManager2, options) {
1633
1829
  const adapter = createDatabaseManagerAdapter(dbManager2);
1634
1830
  const mergeCache = options?.pathProvider ? new MergeSessionCache(options.pathProvider, { nativeBinding: options.nativeBinding }) : null;
1635
1831
  mergeCache?.cleanupOrphans();
1636
- const downloadsDir = options?.pathProvider?.getDownloadsDir() || path7.join(os3.homedir(), "Downloads");
1832
+ const fallbackPathProvider = {
1833
+ getSystemDir: () => path6.join(os3.homedir(), ".chatlab"),
1834
+ getUserDataDir: () => path6.join(os3.homedir(), ".chatlab", "data"),
1835
+ getDatabaseDir: () => path6.join(os3.homedir(), ".chatlab", "data", "databases"),
1836
+ getAiDataDir: () => path6.join(os3.homedir(), ".chatlab", "ai"),
1837
+ getSettingsDir: () => path6.join(os3.homedir(), ".chatlab", "settings"),
1838
+ getCacheDir: () => path6.join(os3.homedir(), ".chatlab", "cache"),
1839
+ getTempDir: () => path6.join(os3.homedir(), ".chatlab", "temp"),
1840
+ getLogsDir: () => path6.join(os3.homedir(), ".chatlab", "logs"),
1841
+ getDownloadsDir: () => path6.join(os3.homedir(), "Downloads")
1842
+ };
1843
+ const resolvedPathProvider = options?.pathProvider ?? fallbackPathProvider;
1637
1844
  registerSessionRoutes2(server2, adapter);
1638
1845
  registerMemberRoutes(server2, adapter);
1639
1846
  registerAnalyticsRoutes(server2, dbManager2, adapter);
@@ -1645,11 +1852,34 @@ function registerWebRoutes(server2, dbManager2, options) {
1645
1852
  registerMergeRoutes(server2, dbManager2, mergeCache);
1646
1853
  }
1647
1854
  registerExportRoutes(server2, adapter);
1648
- registerCacheRoutes(server2, downloadsDir);
1855
+ registerCacheRoutes(server2, resolvedPathProvider);
1856
+ server2.get("/_web/system/check-update", async () => {
1857
+ const currentVersion = getVersion();
1858
+ const packageName = "chatlab-cli";
1859
+ try {
1860
+ const resp = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
1861
+ headers: { Accept: "application/json" },
1862
+ signal: AbortSignal.timeout(1e4)
1863
+ });
1864
+ if (!resp.ok) {
1865
+ return { hasUpdate: false, currentVersion, error: `npm registry HTTP ${resp.status}` };
1866
+ }
1867
+ const data = await resp.json();
1868
+ const latestVersion = data.version || currentVersion;
1869
+ const hasUpdate = isNewerVersion(latestVersion, currentVersion);
1870
+ return { hasUpdate, currentVersion, latestVersion };
1871
+ } catch (err) {
1872
+ return {
1873
+ hasUpdate: false,
1874
+ currentVersion,
1875
+ error: err instanceof Error ? err.message : String(err)
1876
+ };
1877
+ }
1878
+ });
1649
1879
  }
1650
1880
 
1651
1881
  // src/http/routes/nlp.ts
1652
- import * as path8 from "path";
1882
+ import * as path7 from "path";
1653
1883
  function ensureDb3(dbManager2, sessionId) {
1654
1884
  const db = dbManager2.open(sessionId);
1655
1885
  if (!db) {
@@ -1660,7 +1890,7 @@ function ensureDb3(dbManager2, sessionId) {
1660
1890
  function registerNlpRoutes(server2, dbManager2) {
1661
1891
  const pathProvider = dbManager2["pathProvider"];
1662
1892
  if (pathProvider) {
1663
- const nlpDir = path8.join(pathProvider.getUserDataDir(), "nlp");
1893
+ const nlpDir = path7.join(pathProvider.getSystemDir(), "nlp");
1664
1894
  initNlpDir(nlpDir);
1665
1895
  ensureDefaultDict(nlpDir).catch((err) => console.warn("[NLP] Auto-download zh-CN dict failed:", err));
1666
1896
  }
@@ -1698,12 +1928,12 @@ function registerNlpRoutes(server2, dbManager2) {
1698
1928
  }
1699
1929
  function resolveNlpDir(dbManager2) {
1700
1930
  const pathProvider = dbManager2["pathProvider"];
1701
- return path8.join(pathProvider.getUserDataDir(), "nlp");
1931
+ return path7.join(pathProvider.getSystemDir(), "nlp");
1702
1932
  }
1703
1933
 
1704
1934
  // src/http/routes/ai.ts
1705
1935
  import * as fs10 from "fs";
1706
- import * as path12 from "path";
1936
+ import * as path11 from "path";
1707
1937
 
1708
1938
  // src/ai/logger.ts
1709
1939
  var logger = null;
@@ -1752,6 +1982,7 @@ function adaptToolsForAgent(tools, getContext, options) {
1752
1982
  description: tool.description,
1753
1983
  parameters: convertJsonSchemaToParameters(tool.inputSchema),
1754
1984
  async execute(_toolCallId, params) {
1985
+ const toolParams = params && typeof params === "object" ? params : {};
1755
1986
  const ctx = getContext();
1756
1987
  const execCtx = {
1757
1988
  db: ctx.db,
@@ -1761,7 +1992,7 @@ function adaptToolsForAgent(tools, getContext, options) {
1761
1992
  segmentText: (texts, locale, options2) => batchSegmentWithFrequency(texts, locale, options2)
1762
1993
  };
1763
1994
  try {
1764
- const result = await tool.handler(params, execCtx);
1995
+ const result = await tool.handler(toolParams, execCtx);
1765
1996
  if (result.rawMessages && result.rawMessages.length > 0) {
1766
1997
  const pipelineResult = applyPreprocessingPipeline({
1767
1998
  rawMessages: result.rawMessages,
@@ -1784,9 +2015,9 @@ function adaptToolsForAgent(tools, getContext, options) {
1784
2015
 
1785
2016
  // src/ai/assistant-loader.ts
1786
2017
  import * as fs7 from "fs";
1787
- import * as path9 from "path";
2018
+ import * as path8 from "path";
1788
2019
  function loadAssistantConfig(aiDataDir, assistantId) {
1789
- const filePath = path9.join(aiDataDir, "assistants", `${assistantId}.md`);
2020
+ const filePath = path8.join(aiDataDir, "assistants", `${assistantId}.md`);
1790
2021
  if (!fs7.existsSync(filePath)) return null;
1791
2022
  try {
1792
2023
  const content = fs7.readFileSync(filePath, "utf-8");
@@ -1798,7 +2029,7 @@ function loadAssistantConfig(aiDataDir, assistantId) {
1798
2029
 
1799
2030
  // src/ai/manager-factory.ts
1800
2031
  import * as fs8 from "fs";
1801
- import * as path10 from "path";
2032
+ import * as path9 from "path";
1802
2033
  import { createHash, randomUUID as randomUUID3 } from "crypto";
1803
2034
  var nodeFs = {
1804
2035
  ensureDir(dir) {
@@ -1821,7 +2052,7 @@ var nodeFs = {
1821
2052
  return fs8.existsSync(filePath);
1822
2053
  },
1823
2054
  joinPath(...parts) {
1824
- return path10.join(...parts);
2055
+ return path9.join(...parts);
1825
2056
  }
1826
2057
  };
1827
2058
  var managerCache = /* @__PURE__ */ new Map();
@@ -1831,13 +2062,13 @@ function getAssistantManager(aiDataDir) {
1831
2062
  cached = {
1832
2063
  assistant: new AssistantManager({
1833
2064
  fs: nodeFs,
1834
- assistantsDir: path10.join(aiDataDir, "assistants"),
2065
+ assistantsDir: path9.join(aiDataDir, "assistants"),
1835
2066
  builtinRawConfigs: [],
1836
2067
  generateId: () => `custom_${randomUUID3().replace(/-/g, "").slice(0, 12)}`
1837
2068
  }),
1838
2069
  skill: new SkillManagerCore({
1839
2070
  fs: nodeFs,
1840
- skillsDir: path10.join(aiDataDir, "skills"),
2071
+ skillsDir: path9.join(aiDataDir, "skills"),
1841
2072
  builtinRawSkills: [],
1842
2073
  contentHash: (content) => createHash("md5").update(content).digest("hex")
1843
2074
  })
@@ -1980,10 +2211,10 @@ async function runServerAgent(options) {
1980
2211
 
1981
2212
  // src/ai/custom-store.ts
1982
2213
  import * as fs9 from "fs";
1983
- import * as path11 from "path";
2214
+ import * as path10 from "path";
1984
2215
  import { randomUUID as randomUUID4 } from "crypto";
1985
2216
  function readProviders(aiDataDir) {
1986
- const storePath = path11.join(aiDataDir, "custom-providers.json");
2217
+ const storePath = path10.join(aiDataDir, "custom-providers.json");
1987
2218
  if (!fs9.existsSync(storePath)) return [];
1988
2219
  try {
1989
2220
  const content = fs9.readFileSync(storePath, "utf-8");
@@ -1993,8 +2224,8 @@ function readProviders(aiDataDir) {
1993
2224
  }
1994
2225
  }
1995
2226
  function writeProviders(aiDataDir, providers) {
1996
- const storePath = path11.join(aiDataDir, "custom-providers.json");
1997
- const dir = path11.dirname(storePath);
2227
+ const storePath = path10.join(aiDataDir, "custom-providers.json");
2228
+ const dir = path10.dirname(storePath);
1998
2229
  if (!fs9.existsSync(dir)) fs9.mkdirSync(dir, { recursive: true });
1999
2230
  fs9.writeFileSync(storePath, JSON.stringify(providers, null, 2), "utf-8");
2000
2231
  }
@@ -2027,7 +2258,7 @@ function deleteCustomProvider(aiDataDir, id) {
2027
2258
  return { success: true };
2028
2259
  }
2029
2260
  function readModels(aiDataDir) {
2030
- const storePath = path11.join(aiDataDir, "custom-models.json");
2261
+ const storePath = path10.join(aiDataDir, "custom-models.json");
2031
2262
  if (!fs9.existsSync(storePath)) return [];
2032
2263
  try {
2033
2264
  const content = fs9.readFileSync(storePath, "utf-8");
@@ -2037,8 +2268,8 @@ function readModels(aiDataDir) {
2037
2268
  }
2038
2269
  }
2039
2270
  function writeModels(aiDataDir, models) {
2040
- const storePath = path11.join(aiDataDir, "custom-models.json");
2041
- const dir = path11.dirname(storePath);
2271
+ const storePath = path10.join(aiDataDir, "custom-models.json");
2272
+ const dir = path10.dirname(storePath);
2042
2273
  if (!fs9.existsSync(dir)) fs9.mkdirSync(dir, { recursive: true });
2043
2274
  fs9.writeFileSync(storePath, JSON.stringify(models, null, 2), "utf-8");
2044
2275
  }
@@ -2154,7 +2385,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
2154
2385
  return mgr.getBuiltinCatalog();
2155
2386
  });
2156
2387
  server2.get("/_web/ai/llm/has-config", async () => {
2157
- const configPath = path12.join(getAiDir(dbManager2), "llm-config.json");
2388
+ const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
2158
2389
  if (!fs10.existsSync(configPath)) return false;
2159
2390
  try {
2160
2391
  const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
@@ -2165,7 +2396,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
2165
2396
  }
2166
2397
  });
2167
2398
  server2.get("/_web/ai/llm/configs", async () => {
2168
- const configPath = path12.join(getAiDir(dbManager2), "llm-config.json");
2399
+ const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
2169
2400
  if (!fs10.existsSync(configPath)) return { configs: [], defaultAssistant: null, fastModel: null };
2170
2401
  try {
2171
2402
  const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
@@ -2194,7 +2425,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
2194
2425
  });
2195
2426
  });
2196
2427
  server2.get("/_web/ai/llm/provider-registry", async () => {
2197
- const customPath = path12.join(getAiDir(dbManager2), "custom-providers.json");
2428
+ const customPath = path11.join(getAiDir(dbManager2), "custom-providers.json");
2198
2429
  let custom = [];
2199
2430
  if (fs10.existsSync(customPath)) {
2200
2431
  try {
@@ -2207,7 +2438,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
2207
2438
  return [...BUILTIN_PROVIDERS, ...custom];
2208
2439
  });
2209
2440
  server2.get("/_web/ai/llm/model-catalog", async () => {
2210
- const customPath = path12.join(getAiDir(dbManager2), "custom-models.json");
2441
+ const customPath = path11.join(getAiDir(dbManager2), "custom-models.json");
2211
2442
  let custom = [];
2212
2443
  if (fs10.existsSync(customPath)) {
2213
2444
  try {
@@ -2220,7 +2451,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
2220
2451
  return [...BUILTIN_MODELS, ...custom];
2221
2452
  });
2222
2453
  server2.get("/_web/ai/llm/default-assistant-slot", async () => {
2223
- const configPath = path12.join(getAiDir(dbManager2), "llm-config.json");
2454
+ const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
2224
2455
  if (!fs10.existsSync(configPath)) return null;
2225
2456
  try {
2226
2457
  const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
@@ -2230,7 +2461,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
2230
2461
  }
2231
2462
  });
2232
2463
  server2.get("/_web/ai/llm/fast-model-slot", async () => {
2233
- const configPath = path12.join(getAiDir(dbManager2), "llm-config.json");
2464
+ const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
2234
2465
  if (!fs10.existsSync(configPath)) return null;
2235
2466
  try {
2236
2467
  const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
@@ -2587,7 +2818,7 @@ var NOOP_LOGGER = { info: noop, warn: noop, error: noop };
2587
2818
 
2588
2819
  // ../../packages/sync/src/data-source-manager.ts
2589
2820
  import * as fs11 from "fs";
2590
- import * as path13 from "path";
2821
+ import * as path12 from "path";
2591
2822
  import * as crypto2 from "crypto";
2592
2823
  var CONFIG_FILE = "data-sources.json";
2593
2824
  function generateId(prefix = "ds") {
@@ -2615,7 +2846,7 @@ var DataSourceManager = class {
2615
2846
  this.logger = logger2 ?? NOOP_LOGGER;
2616
2847
  }
2617
2848
  getConfigPath() {
2618
- return path13.join(this.configDir, CONFIG_FILE);
2849
+ return path12.join(this.configDir, CONFIG_FILE);
2619
2850
  }
2620
2851
  ensureDir() {
2621
2852
  fs11.mkdirSync(this.configDir, { recursive: true });
@@ -2904,10 +3135,10 @@ var PullEngine = class {
2904
3135
  limit: ds.pullLimit
2905
3136
  });
2906
3137
  try {
2907
- const stat = fs12.statSync(tempFile);
2908
- this.logger.info(`[Pull] "${sess.name}" page ${pageCount}: fetched ${stat.size} bytes`);
3138
+ const stat2 = fs12.statSync(tempFile);
3139
+ this.logger.info(`[Pull] "${sess.name}" page ${pageCount}: fetched ${stat2.size} bytes`);
2909
3140
  const sync0 = parseSyncFromFile(tempFile);
2910
- if (stat.size < 1024) {
3141
+ if (stat2.size < 1024) {
2911
3142
  if (!fileContainsMessages(tempFile) && sync0?.hasMore === false) {
2912
3143
  cleanupTempFile(tempFile);
2913
3144
  const retryDelays = [2e3, 3e3, 5e3];
@@ -2990,7 +3221,7 @@ var PullEngine = class {
2990
3221
  continue;
2991
3222
  }
2992
3223
  }
2993
- if (stat.size === 0) {
3224
+ if (stat2.size === 0) {
2994
3225
  cleanupTempFile(tempFile);
2995
3226
  break;
2996
3227
  }
@@ -3198,11 +3429,11 @@ function reloadTimer(dsId, skipInitialPull = false) {
3198
3429
  // src/sync/adapters.ts
3199
3430
  import * as fs13 from "fs";
3200
3431
  import * as os4 from "os";
3201
- import * as path14 from "path";
3432
+ import * as path13 from "path";
3202
3433
  import * as crypto4 from "crypto";
3203
3434
  function getTempFilePath(ext) {
3204
3435
  const id = crypto4.randomBytes(8).toString("hex");
3205
- return path14.join(os4.tmpdir(), `chatlab-pull-${id}${ext}`);
3436
+ return path13.join(os4.tmpdir(), `chatlab-pull-${id}${ext}`);
3206
3437
  }
3207
3438
  var NodeFetcher = class {
3208
3439
  async fetchToTempFile(baseUrl, remoteSessionId, token, params) {
@@ -3225,7 +3456,7 @@ var NodeFetcher = class {
3225
3456
  };
3226
3457
  function resolveNativeBinding2() {
3227
3458
  if (process.versions.electron) return void 0;
3228
- const nativePath = path14.resolve(__dirname, "../../native/better_sqlite3.node");
3459
+ const nativePath = resolveCliPath("native/better_sqlite3.node");
3229
3460
  if (fs13.existsSync(nativePath)) return nativePath;
3230
3461
  return void 0;
3231
3462
  }
@@ -3456,7 +3687,7 @@ var dbManager = null;
3456
3687
  var convManager = null;
3457
3688
  function resolveNativeBinding3() {
3458
3689
  if (process.versions.electron) return void 0;
3459
- const nativePath = path15.resolve(__dirname, "../../native/better_sqlite3.node");
3690
+ const nativePath = resolveCliPath("native/better_sqlite3.node");
3460
3691
  if (fs14.existsSync(nativePath)) return nativePath;
3461
3692
  return void 0;
3462
3693
  }
@@ -3481,7 +3712,7 @@ async function startHttpServer(options) {
3481
3712
  const pathProvider = new NodePathProvider(userDataDir);
3482
3713
  pathProvider.ensureAllDirs();
3483
3714
  if (hasPendingElectronDataWarning() || !verifyCliDataPath(pathProvider.getDatabaseDir())) {
3484
- throw new Error(
3715
+ console.error(
3485
3716
  "\n" + "=".repeat(68) + "\n ChatLab: Electron desktop data not found\n" + "=".repeat(68) + '\n\n Detected that ChatLab desktop app was installed on this machine,\n but could not locate your chat databases.\n\n This usually means you changed the data directory in desktop settings.\n\n To fix this, choose one of:\n\n 1. Open ChatLab desktop app \u2014 it will auto-migrate your data\n 2. Set the data directory manually:\n export CHATLAB_DATA_DIR="/path/to/your/data"\n 3. Edit ~/.chatlab/config.toml:\n [data]\n user_data_dir = "/path/to/your/data"\n\n' + "=".repeat(68) + "\n"
3486
3717
  );
3487
3718
  }
@@ -3558,4 +3789,4 @@ export {
3558
3789
  startHttpServer,
3559
3790
  stopHttpServer
3560
3791
  };
3561
- //# sourceMappingURL=chunk-LI4X52E7.mjs.map
3792
+ //# sourceMappingURL=chunk-AMMSVJG4.mjs.map