chatlab-cli 0.24.1 → 0.25.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 (73) hide show
  1. package/dist/chat-command-5XMRLXZM.mjs +166 -0
  2. package/dist/chat-command-5XMRLXZM.mjs.map +1 -0
  3. package/dist/{chunk-N5DGZQB4.mjs → chunk-7VG6QGQ2.mjs} +1543 -664
  4. package/dist/chunk-7VG6QGQ2.mjs.map +1 -0
  5. package/dist/{chunk-QJI6AOAT.mjs → chunk-CUCDRAY6.mjs} +17 -25
  6. package/dist/chunk-CUCDRAY6.mjs.map +1 -0
  7. package/dist/chunk-FDK6SPCG.mjs +40 -0
  8. package/dist/chunk-FDK6SPCG.mjs.map +1 -0
  9. package/dist/{chunk-ZL322NVL.mjs → chunk-GTCTDD2Z.mjs} +116 -504
  10. package/dist/chunk-GTCTDD2Z.mjs.map +1 -0
  11. package/dist/{chunk-43XWYC3M.mjs → chunk-JE3FOFF7.mjs} +219 -123
  12. package/dist/chunk-JE3FOFF7.mjs.map +1 -0
  13. package/dist/{chunk-QY6P2YS7.mjs → chunk-PDQFSQO6.mjs} +59 -33
  14. package/dist/chunk-PDQFSQO6.mjs.map +1 -0
  15. package/dist/chunk-WYHGWTA4.mjs +485 -0
  16. package/dist/chunk-WYHGWTA4.mjs.map +1 -0
  17. package/dist/{chunk-CIIQ3S2X.mjs → chunk-YZYP5ST6.mjs} +37 -8
  18. package/dist/chunk-YZYP5ST6.mjs.map +1 -0
  19. package/dist/cli.mjs +3 -2
  20. package/dist/{http-TPX74BLK.mjs → http-C3CGXUBU.mjs} +8 -6
  21. package/dist/{import-B745DRHD.mjs → import-VS7L5JDX.mjs} +4 -4
  22. package/dist/index.mjs +10 -8
  23. package/dist/{mcp-YWAVG5XW.mjs → mcp-6VXDPUQK.mjs} +11 -6
  24. package/dist/mcp-6VXDPUQK.mjs.map +1 -0
  25. package/dist/{stream-import-OPALPVWF.mjs → stream-import-TFDBNVIW.mjs} +3 -3
  26. package/dist-web/assets/{DebugToolsPanel-DaSNc1o-.css → DebugToolsPanel-vn-bnUxn.css} +1 -1
  27. package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-B1xZmp9r.js +161 -0
  28. package/dist-web/assets/{EChartWordcloud-VpNJDurs.js → EChartWordcloud-CzhfrEF_.js} +1 -1
  29. package/dist-web/assets/{MessageExportModal-CSfaY25B.js → MessageExportModal-B79pPBL9.js} +1 -1
  30. package/dist-web/assets/{electron-BUeXfvxT.js → electron-DRkrjeIl.js} +1 -1
  31. package/dist-web/assets/electron-Dv8jdn_2.js +1 -0
  32. package/dist-web/assets/{fetch-RDFt3hmp.js → fetch-BmZIm6mS.js} +1 -1
  33. package/dist-web/assets/fetch-BqLy63aj.js +1 -0
  34. package/dist-web/assets/fetch-BstX-wd4.js +1 -0
  35. package/dist-web/assets/{fetch-BohUj3CQ.js → fetch-Bvcxe5PI.js} +1 -1
  36. package/dist-web/assets/{fetch-BneHn5qk.js → fetch-CDamdvtb.js} +1 -1
  37. package/dist-web/assets/{fetch-DypPduyQ.js → fetch-DWg-2kOp.js} +1 -1
  38. package/dist-web/assets/{fetch-CARsBVl0.js → fetch-DfgdagMN.js} +1 -1
  39. package/dist-web/assets/{fetch-Ck3tjoLa.js → fetch-Drk9dLaF.js} +1 -1
  40. package/dist-web/assets/{fetch-B2q6973s.js → fetch-Y-_WsCuk.js} +1 -1
  41. package/dist-web/assets/{fetch-BGMRmQx0.js → fetch-ph2_d79v.js} +1 -1
  42. package/dist-web/assets/{index-Bvlj3dMn.js → index-9urfJP1r.js} +1 -1
  43. package/dist-web/assets/index-CfKjh0Jr.js +9 -0
  44. package/dist-web/assets/index-CprJOAB1.css +1 -0
  45. package/dist-web/assets/{index-BvaWRM6_.js → index-DMWf5On7.js} +1 -1
  46. package/dist-web/assets/{index-DCWvD-4L.js → index-D_hHm7bQ.js} +2 -2
  47. package/dist-web/assets/index-MCdpiX_O.js +173 -0
  48. package/dist-web/assets/{index-C5LrQG3N.js → index-deYDOVUa.js} +4 -4
  49. package/dist-web/assets/vendor-echarts-CITQeskI.js +11 -0
  50. package/dist-web/assets/{vendor-echarts-wordcloud-CZ9gsX8l.js → vendor-echarts-wordcloud-B1kQMklB.js} +1 -1
  51. package/dist-web/assets/{vendor-nuxt-ui-BYU7dz8t.js → vendor-nuxt-ui-C_8CsH6e.js} +1 -1
  52. package/dist-web/assets/{vendor-reka-ui-CnB0mMNX.js → vendor-reka-ui-CIMXwvEp.js} +1 -1
  53. package/dist-web/assets/{web-CXPkmhis.js → web-XJV6Vj5t.js} +1 -1
  54. package/dist-web/index.html +4 -4
  55. package/package.json +1 -1
  56. package/dist/chunk-43XWYC3M.mjs.map +0 -1
  57. package/dist/chunk-CIIQ3S2X.mjs.map +0 -1
  58. package/dist/chunk-N5DGZQB4.mjs.map +0 -1
  59. package/dist/chunk-QJI6AOAT.mjs.map +0 -1
  60. package/dist/chunk-QY6P2YS7.mjs.map +0 -1
  61. package/dist/chunk-ZL322NVL.mjs.map +0 -1
  62. package/dist/mcp-YWAVG5XW.mjs.map +0 -1
  63. package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-BBDrsJfe.js +0 -161
  64. package/dist-web/assets/electron-BynNUuEA.js +0 -1
  65. package/dist-web/assets/fetch-BtHwWs8A.js +0 -1
  66. package/dist-web/assets/fetch-DzNuFdFM.js +0 -1
  67. package/dist-web/assets/index-BRwEubUe.js +0 -173
  68. package/dist-web/assets/index-DB-iqXzV.css +0 -1
  69. package/dist-web/assets/index-DS1rzk1I.js +0 -8
  70. package/dist-web/assets/vendor-echarts-C5u62NnM.js +0 -11
  71. /package/dist/{http-TPX74BLK.mjs.map → http-C3CGXUBU.mjs.map} +0 -0
  72. /package/dist/{import-B745DRHD.mjs.map → import-VS7L5JDX.mjs.map} +0 -0
  73. /package/dist/{stream-import-OPALPVWF.mjs.map → stream-import-TFDBNVIW.mjs.map} +0 -0
@@ -7,31 +7,38 @@ const __dirname = __pathDirname(__filename);
7
7
  import {
8
8
  importData,
9
9
  parseFile
10
- } from "./chunk-QJI6AOAT.mjs";
10
+ } from "./chunk-CUCDRAY6.mjs";
11
11
  import {
12
12
  analyzeIncrementalImport,
13
13
  analyzeNewImport,
14
14
  incrementalImport,
15
15
  streamImport
16
- } from "./chunk-QY6P2YS7.mjs";
16
+ } from "./chunk-PDQFSQO6.mjs";
17
17
  import {
18
- AGENT_TOOL_REGISTRY,
19
- CoreDataProvider
20
- } from "./chunk-43XWYC3M.mjs";
18
+ assertCliDataDirCompatible
19
+ } from "./chunk-FDK6SPCG.mjs";
21
20
  import {
22
21
  getVersion
23
22
  } from "./chunk-5ADKYYNA.mjs";
24
23
  import {
25
- AIConversationManager,
24
+ closeServerAiLogger,
25
+ createCliRunAgentStream,
26
+ initServerAiLogger
27
+ } from "./chunk-WYHGWTA4.mjs";
28
+ import {
29
+ AGENT_TOOL_REGISTRY,
30
+ CoreDataProvider
31
+ } from "./chunk-JE3FOFF7.mjs";
32
+ import {
33
+ AIChatManager,
26
34
  ALL_MIGRATIONS,
27
- AgentEventHandler,
28
- AiLogger,
29
35
  AssistantManager,
30
36
  BUILTIN_MODELS,
31
37
  BUILTIN_PROVIDERS,
32
38
  BUILTIN_TOOL_CATALOG,
33
39
  CustomModelStore,
34
40
  CustomProviderStore,
41
+ DataDirCompatibilityError,
35
42
  DatabaseManager,
36
43
  LLMConfigStore,
37
44
  MergeSessionCache,
@@ -39,22 +46,14 @@ import {
39
46
  NodePathProvider,
40
47
  POS_TAG_DEFINITIONS,
41
48
  PreferencesManager,
42
- SkillManager,
43
49
  SkillManagerCore,
44
50
  TempDbWriter,
45
51
  applyPendingNodeDataDirMigrationIfNeeded,
46
- applyPreprocessingPipeline,
47
- batchSegmentWithFrequency,
48
52
  buildMergedOutput,
49
53
  buildPiModel,
50
- buildSystemPrompt,
51
- checkAndCompress,
52
54
  checkConflictsFromSources,
53
55
  computeWordFrequency,
54
56
  countMessagesTokens,
55
- createActivateSkillTool,
56
- createAiTranslate,
57
- createCompressionLlmAdapter,
58
57
  createDatabaseManagerAdapter,
59
58
  createJiebaNlpProvider,
60
59
  createNodeDataDirSwitch,
@@ -70,11 +69,9 @@ import {
70
69
  fetchRemoteModels,
71
70
  filterMessagesWithContext,
72
71
  findEntryFileInDirectory,
73
- formatAIError,
74
72
  getAvailableYears,
75
73
  getBuiltinModelsByProvider,
76
74
  getCatchphraseAnalysis,
77
- getChatOverview,
78
75
  getClusterGraph,
79
76
  getDailyActivity,
80
77
  getDefaultNodeUserDataDir,
@@ -104,17 +101,13 @@ import {
104
101
  getYearlyActivity,
105
102
  hasPendingElectronDataWarning,
106
103
  initNlpDir,
107
- initTokenizer,
108
104
  isDictDownloaded,
109
105
  isNewerStableVersion,
110
106
  loadConfig,
111
107
  member_service_exports,
112
108
  mergeRulesForLocale,
113
- openBetterSqliteDatabase,
114
- parseAssistantFile,
115
109
  queryMessages,
116
110
  resolveApiKey,
117
- runAgentCore,
118
111
  runSimpleLlmStream,
119
112
  scanMultiChatFile,
120
113
  segmentText,
@@ -128,13 +121,13 @@ import {
128
121
  verifyCliDataPath,
129
122
  writeAuthProfile,
130
123
  writeConfigField
131
- } from "./chunk-N5DGZQB4.mjs";
124
+ } from "./chunk-7VG6QGQ2.mjs";
132
125
  import {
133
126
  resolveCliPath
134
127
  } from "./chunk-FJ35V3TE.mjs";
135
128
 
136
129
  // src/http/index.ts
137
- import * as fs11 from "fs";
130
+ import * as fs9 from "fs";
138
131
  import * as crypto4 from "crypto";
139
132
 
140
133
  // src/http/server.ts
@@ -150,6 +143,7 @@ var HTTP_STATUS = {
150
143
  ["SQL_EXECUTION_ERROR" /* SQL_EXECUTION_ERROR */]: 400,
151
144
  ["EXPORT_TOO_LARGE" /* EXPORT_TOO_LARGE */]: 400,
152
145
  ["BODY_TOO_LARGE" /* BODY_TOO_LARGE */]: 413,
146
+ ["DATA_DIR_INCOMPATIBLE" /* DATA_DIR_INCOMPATIBLE */]: 409,
153
147
  ["SERVER_ERROR" /* SERVER_ERROR */]: 500
154
148
  };
155
149
  var ApiError = class extends Error {
@@ -180,6 +174,14 @@ function exportTooLarge(count, limit) {
180
174
  function serverError(message = "Internal server error") {
181
175
  return new ApiError("SERVER_ERROR" /* SERVER_ERROR */, message);
182
176
  }
177
+ function dataDirIncompatible(message) {
178
+ return new ApiError("DATA_DIR_INCOMPATIBLE" /* DATA_DIR_INCOMPATIBLE */, message);
179
+ }
180
+ function apiErrorFromUnknown(error) {
181
+ if (error instanceof ApiError) return error;
182
+ if (error instanceof DataDirCompatibilityError) return dataDirIncompatible(error.message);
183
+ return null;
184
+ }
183
185
  function successResponse(data, meta) {
184
186
  return {
185
187
  success: true,
@@ -790,7 +792,7 @@ function registerExportRoutes(server2, ctx) {
790
792
  timeFilter: body.timeFilter,
791
793
  senderIds: body.senderIds,
792
794
  contextSize: body.contextSize,
793
- chatSessionIds: body.chatSessionIds
795
+ segmentIds: body.segmentIds
794
796
  });
795
797
  if (!result.success) {
796
798
  return reply.code(500).send({ error: result.error });
@@ -1172,10 +1174,10 @@ function registerAiFilterRoutes(server2, ctx) {
1172
1174
  return filterMessagesWithContext(db, { keywords, timeFilter, senderIds, contextSize, page, pageSize });
1173
1175
  });
1174
1176
  server2.post("/_web/ai/multiple-sessions-messages", async (request, reply) => {
1175
- const { sessionId, chatSessionIds, page, pageSize } = request.body;
1177
+ const { sessionId, segmentIds, page, pageSize } = request.body;
1176
1178
  const db = ctx.dbManager.open(sessionId);
1177
1179
  if (!db) return reply.code(404).send({ error: `Session not found: ${sessionId}` });
1178
- return getMultipleSessionsMessages(db, chatSessionIds, page, pageSize);
1180
+ return getMultipleSessionsMessages(db, segmentIds, page, pageSize);
1179
1181
  });
1180
1182
  }
1181
1183
 
@@ -1254,31 +1256,31 @@ function registerAiToolRoutes(server2, ctx) {
1254
1256
  });
1255
1257
  }
1256
1258
 
1257
- // ../../packages/http-routes/src/routes/web/ai-conversations.ts
1258
- function registerAiConversationRoutes(server2, ctx) {
1259
- const cm = ctx.conversationManager;
1259
+ // ../../packages/http-routes/src/routes/web/ai-chats.ts
1260
+ function registerAiChatRoutes(server2, ctx) {
1261
+ const cm = ctx.aiChatManager;
1260
1262
  if (!cm) return;
1261
- server2.post("/_web/ai/conversations", async (request) => {
1263
+ server2.post("/_web/ai/chats", async (request) => {
1262
1264
  const { sessionId, title, assistantId } = request.body;
1263
- return cm.createConversation(sessionId, title, assistantId);
1265
+ return cm.createAIChat(sessionId, title, assistantId);
1264
1266
  });
1265
- server2.get("/_web/ai/conversations", async (request) => {
1267
+ server2.get("/_web/ai/chats", async (request) => {
1266
1268
  const { sessionId } = request.query;
1267
1269
  if (!sessionId) return [];
1268
- return cm.getConversations(sessionId);
1270
+ return cm.getAIChats(sessionId);
1269
1271
  });
1270
- server2.get("/_web/ai/conversations/:id", async (request, reply) => {
1271
- const conv = cm.getConversation(request.params.id);
1272
- if (!conv) return reply.code(404).send({ error: "Conversation not found" });
1272
+ server2.get("/_web/ai/chats/:id", async (request, reply) => {
1273
+ const conv = cm.getAIChat(request.params.id);
1274
+ if (!conv) return reply.code(404).send({ error: "AI chat not found" });
1273
1275
  return conv;
1274
1276
  });
1275
- server2.put("/_web/ai/conversations/:id/title", async (request) => {
1276
- return cm.updateConversationTitle(request.params.id, request.body.title);
1277
+ server2.put("/_web/ai/chats/:id/title", async (request) => {
1278
+ return cm.updateAIChatTitle(request.params.id, request.body.title);
1277
1279
  });
1278
- server2.delete("/_web/ai/conversations/:id", async (request) => {
1279
- return cm.deleteConversation(request.params.id);
1280
+ server2.delete("/_web/ai/chats/:id", async (request) => {
1281
+ return cm.deleteAIChat(request.params.id);
1280
1282
  });
1281
- server2.post("/_web/ai/conversations/:id/messages", async (request) => {
1283
+ server2.post("/_web/ai/chats/:id/messages", async (request) => {
1282
1284
  const { role, content, dataKeywords, dataMessageCount, contentBlocks, tokenUsage } = request.body;
1283
1285
  return cm.addMessage(
1284
1286
  request.params.id,
@@ -1290,23 +1292,23 @@ function registerAiConversationRoutes(server2, ctx) {
1290
1292
  tokenUsage
1291
1293
  );
1292
1294
  });
1293
- server2.get("/_web/ai/conversations/:id/messages", async (request) => {
1295
+ server2.get("/_web/ai/chats/:id/messages", async (request) => {
1294
1296
  return cm.getMessages(request.params.id);
1295
1297
  });
1296
- server2.post("/_web/ai/conversations/:id/messages/:messageId/delete-from", async (request, reply) => {
1298
+ server2.post("/_web/ai/chats/:id/messages/:messageId/delete-from", async (request, reply) => {
1297
1299
  const { id, messageId } = request.params;
1298
1300
  if (!id || typeof id !== "string" || !messageId || typeof messageId !== "string") {
1299
- return reply.code(400).send({ error: "conversation id and messageId are required" });
1301
+ return reply.code(400).send({ error: "aiChatId and messageId are required" });
1300
1302
  }
1301
1303
  cm.deleteMessagesFrom(id, messageId);
1302
1304
  return { success: true };
1303
1305
  });
1304
- server2.post("/_web/ai/conversations/:id/fork", async (request, reply) => {
1306
+ server2.post("/_web/ai/chats/:id/fork", async (request, reply) => {
1305
1307
  const { upToMessageId, title } = request.body;
1306
1308
  if (!upToMessageId || typeof upToMessageId !== "string") {
1307
1309
  return reply.code(400).send({ error: "upToMessageId is required" });
1308
1310
  }
1309
- return cm.forkConversation(request.params.id, upToMessageId, title);
1311
+ return cm.forkAIChat(request.params.id, upToMessageId, title);
1310
1312
  });
1311
1313
  server2.put("/_web/ai/messages/:messageId/content", async (request, reply) => {
1312
1314
  const { content } = request.body;
@@ -1316,23 +1318,23 @@ function registerAiConversationRoutes(server2, ctx) {
1316
1318
  cm.updateMessageContent(request.params.messageId, content);
1317
1319
  return { success: true };
1318
1320
  });
1319
- server2.post("/_web/ai/conversations/:id/messages/:messageId/delete-relink", async (request, reply) => {
1321
+ server2.post("/_web/ai/chats/:id/messages/:messageId/delete-relink", async (request, reply) => {
1320
1322
  const { id, messageId } = request.params;
1321
1323
  if (!id || !messageId) {
1322
- return reply.code(400).send({ error: "conversation id and messageId are required" });
1324
+ return reply.code(400).send({ error: "aiChatId and messageId are required" });
1323
1325
  }
1324
1326
  cm.deleteAndRelinkMessage(id, messageId);
1325
1327
  return { success: true };
1326
1328
  });
1327
- server2.post("/_web/ai/conversations/:id/messages/insert-after", async (request, reply) => {
1329
+ server2.post("/_web/ai/chats/:id/messages/insert-after", async (request, reply) => {
1328
1330
  const { afterMessageId, role, content, contentBlocks, tokenUsage } = request.body;
1329
1331
  if (!afterMessageId || typeof afterMessageId !== "string") {
1330
1332
  return reply.code(400).send({ error: "afterMessageId is required" });
1331
1333
  }
1332
1334
  return cm.insertMessageAfter(request.params.id, afterMessageId, role, content, contentBlocks, tokenUsage);
1333
1335
  });
1334
- server2.get("/_web/ai/conversations/:id/token-usage", async (request) => {
1335
- return cm.getConversationTokenUsage(request.params.id);
1336
+ server2.get("/_web/ai/chats/:id/token-usage", async (request) => {
1337
+ return cm.getAIChatTokenUsage(request.params.id);
1336
1338
  });
1337
1339
  server2.get("/_web/ai/debug/schema", async () => {
1338
1340
  return cm.getAiSchema();
@@ -1353,7 +1355,7 @@ function registerAiConversationRoutes(server2, ctx) {
1353
1355
  const cleared = cm.clearAllDebugContext();
1354
1356
  return { success: true, cleared };
1355
1357
  });
1356
- server2.get("/_web/ai/conversations/:id/estimate-tokens", async (request) => {
1358
+ server2.get("/_web/ai/chats/:id/estimate-tokens", async (request) => {
1357
1359
  const history = cm.getHistoryForAgent(request.params.id);
1358
1360
  const tokens = countMessagesTokens(history.map((m) => ({ role: m.role, content: m.content })));
1359
1361
  return { success: true, tokens, messageCount: history.length };
@@ -1380,8 +1382,8 @@ function registerAiSummaryRoutes(server2, ctx) {
1380
1382
  if (!deps) return;
1381
1383
  const { sessionAdapter: adapter } = ctx;
1382
1384
  server2.post("/_web/sessions/:id/summaries/generate", async (request, reply) => {
1383
- const { chatSessionId, locale, forceRegenerate, strategy } = request.body;
1384
- const result = await summary_service_exports.generateSummary(adapter, request.params.id, chatSessionId, deps, {
1385
+ const { segmentId, locale, forceRegenerate, strategy } = request.body;
1386
+ const result = await summary_service_exports.generateSummary(adapter, request.params.id, segmentId, deps, {
1385
1387
  locale,
1386
1388
  forceRegenerate,
1387
1389
  strategy
@@ -1403,8 +1405,8 @@ function registerAiSummaryRoutes(server2, ctx) {
1403
1405
  return result;
1404
1406
  });
1405
1407
  server2.post("/_web/sessions/:id/summaries/check-can-generate", async (request) => {
1406
- const { chatSessionIds } = request.body;
1407
- return summary_service_exports.checkCanGenerate(adapter, request.params.id, chatSessionIds);
1408
+ const { segmentIds } = request.body;
1409
+ return summary_service_exports.checkCanGenerate(adapter, request.params.id, segmentIds);
1408
1410
  });
1409
1411
  }
1410
1412
 
@@ -1844,7 +1846,7 @@ function registerSharedRoutes(server2, ctx, options) {
1844
1846
  if (options?.requireAi) {
1845
1847
  const missing = [];
1846
1848
  if (!ctx.aiDataDir) missing.push("aiDataDir");
1847
- if (!ctx.conversationManager) missing.push("conversationManager");
1849
+ if (!ctx.aiChatManager) missing.push("aiChatManager");
1848
1850
  if (!ctx.assistantManager) missing.push("assistantManager");
1849
1851
  if (!ctx.skillManagerCore) missing.push("skillManagerCore");
1850
1852
  if (!ctx.llmConfigStore) missing.push("llmConfigStore");
@@ -1862,7 +1864,7 @@ function registerSharedRoutes(server2, ctx, options) {
1862
1864
  registerAiAgentStreamRoutes(server2, ctx);
1863
1865
  registerAiFilterRoutes(server2, ctx);
1864
1866
  registerAiToolRoutes(server2, ctx);
1865
- registerAiConversationRoutes(server2, ctx);
1867
+ registerAiChatRoutes(server2, ctx);
1866
1868
  registerAiSummaryRoutes(server2, ctx);
1867
1869
  registerMergeRoutes(server2, ctx);
1868
1870
  registerCacheRoutes(server2, ctx);
@@ -1920,8 +1922,9 @@ function createServer() {
1920
1922
  });
1921
1923
  server2.addHook("onRequest", authHook);
1922
1924
  server2.setErrorHandler((error, _request, reply) => {
1923
- if (error instanceof ApiError) {
1924
- reply.code(error.statusCode).send(errorResponse(error));
1925
+ const apiError = apiErrorFromUnknown(error);
1926
+ if (apiError) {
1927
+ reply.code(apiError.statusCode).send(errorResponse(apiError));
1925
1928
  return;
1926
1929
  }
1927
1930
  if (error.statusCode === 413) {
@@ -2337,7 +2340,7 @@ function registerWebRoutes(server2, dbManager2, options) {
2337
2340
  const resolvedPathProvider = options?.pathProvider ?? fallbackPathProvider;
2338
2341
  const ai = options?.aiContext;
2339
2342
  const cliStreamImport = async (dm, filePath) => {
2340
- const { streamImport: streamImport2 } = await import("./stream-import-OPALPVWF.mjs");
2343
+ const { streamImport: streamImport2 } = await import("./stream-import-TFDBNVIW.mjs");
2341
2344
  const result = await streamImport2(dm, filePath);
2342
2345
  if (!result.sessionId) throw new Error("Import succeeded but no sessionId returned");
2343
2346
  return { sessionId: result.sessionId };
@@ -2373,7 +2376,7 @@ function registerWebRoutes(server2, dbManager2, options) {
2373
2376
  },
2374
2377
  ...ai && {
2375
2378
  aiDataDir: ai.aiDataDir,
2376
- conversationManager: ai.convManager,
2379
+ aiChatManager: ai.aiChatManager,
2377
2380
  assistantManager: ai.assistantManager,
2378
2381
  skillManagerCore: ai.skillManagerCore,
2379
2382
  llmConfigStore: ai.llmConfigStore,
@@ -2433,24 +2436,6 @@ function registerProxyRoutes(server2) {
2433
2436
  });
2434
2437
  }
2435
2438
 
2436
- // src/ai/logger.ts
2437
- var logger = null;
2438
- function initServerAiLogger(logsDir) {
2439
- if (!logger) {
2440
- logger = new AiLogger(logsDir);
2441
- }
2442
- return logger;
2443
- }
2444
- function getServerAiLogger() {
2445
- return logger;
2446
- }
2447
- function closeServerAiLogger() {
2448
- if (logger) {
2449
- logger.close();
2450
- logger = null;
2451
- }
2452
- }
2453
-
2454
2439
  // src/ai/manager-factory.ts
2455
2440
  import * as fs5 from "fs";
2456
2441
  import * as path7 from "path";
@@ -2510,379 +2495,14 @@ function getSkillManagerCore(aiDataDir) {
2510
2495
  return cached.skill;
2511
2496
  }
2512
2497
 
2513
- // src/ai/tool-adapter.ts
2514
- var DEFAULT_MAX_TOOL_RESULT_TOKENS = 8e3;
2515
- var TOOL_TRUNCATION_STRATEGY = {
2516
- search_messages: "keep_first",
2517
- deep_search_messages: "keep_first",
2518
- get_recent_messages: "keep_last",
2519
- get_message_context: "keep_last",
2520
- get_session_messages: "keep_last",
2521
- get_conversation_between: "keep_last"
2522
- };
2523
- function convertJsonSchemaToParameters(schema) {
2524
- const properties = {};
2525
- for (const [key, prop] of Object.entries(schema.properties)) {
2526
- properties[key] = { ...prop };
2527
- }
2528
- return {
2529
- type: "object",
2530
- properties,
2531
- required: schema.required || []
2532
- };
2533
- }
2534
- function adaptToolsForAgent(tools, getContext, options) {
2535
- const tokenBudget = options?.maxToolResultTokens ?? DEFAULT_MAX_TOOL_RESULT_TOKENS;
2536
- return tools.map((tool) => ({
2537
- name: tool.name,
2538
- label: tool.name,
2539
- description: tool.description,
2540
- parameters: convertJsonSchemaToParameters(tool.inputSchema),
2541
- async execute(_toolCallId, params) {
2542
- const toolParams = params && typeof params === "object" ? params : {};
2543
- const ctx = getContext();
2544
- const execCtx = {
2545
- db: ctx.db,
2546
- dataProvider: new CoreDataProvider(ctx.db),
2547
- sessionId: ctx.sessionId,
2548
- locale: ctx.locale,
2549
- segmentText: (texts, locale, options2) => batchSegmentWithFrequency(texts, locale, options2)
2550
- };
2551
- try {
2552
- const result = await tool.handler(toolParams, execCtx);
2553
- if (result.rawMessages && result.rawMessages.length > 0) {
2554
- const pipelineResult = applyPreprocessingPipeline({
2555
- rawMessages: result.rawMessages,
2556
- locale: ctx.locale,
2557
- maxToolResultTokens: tokenBudget,
2558
- truncationStrategy: TOOL_TRUNCATION_STRATEGY[tool.name] ?? "keep_last",
2559
- extraDetails: result.data ?? {},
2560
- logger: getServerAiLogger() ?? void 0
2561
- });
2562
- return { content: [{ type: "text", text: pipelineResult.text }], details: null };
2563
- }
2564
- return { content: [{ type: "text", text: result.content }], details: null };
2565
- } catch (error) {
2566
- const msg = error instanceof Error ? error.message : String(error);
2567
- return { content: [{ type: "text", text: `Error: ${msg}` }], details: null };
2568
- }
2569
- }
2570
- }));
2571
- }
2572
-
2573
- // src/ai/llm-config.ts
2574
- import * as fs6 from "fs";
2575
- import * as path8 from "path";
2576
- function loadLlmConfig(aiDataDir) {
2577
- const configPath = path8.join(aiDataDir, "llm-config.json");
2578
- if (!fs6.existsSync(configPath)) {
2579
- return { configs: [], defaultAssistant: null, fastModel: null };
2580
- }
2581
- try {
2582
- const data = JSON.parse(fs6.readFileSync(configPath, "utf-8"));
2583
- const configs = (data.configs || []).map((c) => {
2584
- const provider = c.provider || "";
2585
- const authProfile = c.authProfile;
2586
- const profileKey = resolveApiKey(provider, authProfile);
2587
- const rawKey = c.apiKey || "";
2588
- const fallbackKey = rawKey.startsWith("enc:") ? "" : rawKey;
2589
- return {
2590
- ...c,
2591
- apiKey: profileKey || fallbackKey
2592
- };
2593
- });
2594
- return {
2595
- configs,
2596
- defaultAssistant: data.defaultAssistant ?? null,
2597
- fastModel: data.fastModel ?? null
2598
- };
2599
- } catch {
2600
- return { configs: [], defaultAssistant: null, fastModel: null };
2601
- }
2602
- }
2603
- function resolveSlot(slot, configs) {
2604
- if (slot && configs.some((c) => c.id === slot.configId)) return slot;
2605
- const fallback = configs[0];
2606
- if (!fallback) return null;
2607
- return { configId: fallback.id, modelId: fallback.model };
2608
- }
2609
- function getDefaultAssistantConfig(aiDataDir) {
2610
- const store = loadLlmConfig(aiDataDir);
2611
- const slot = resolveSlot(store.defaultAssistant, store.configs);
2612
- if (!slot) return null;
2613
- const config = store.configs.find((c) => c.id === slot.configId);
2614
- if (!config) return null;
2615
- return { ...config, model: slot.modelId || config.model };
2616
- }
2617
- function buildPiModel2(config) {
2618
- return buildPiModel(config);
2619
- }
2620
-
2621
- // src/ai/assistant-loader.ts
2622
- import * as fs7 from "fs";
2623
- import * as path9 from "path";
2624
- function loadAssistantConfig(aiDataDir, assistantId) {
2625
- const filePath = path9.join(aiDataDir, "assistants", `${assistantId}.md`);
2626
- if (!fs7.existsSync(filePath)) return null;
2627
- try {
2628
- const content = fs7.readFileSync(filePath, "utf-8");
2629
- return parseAssistantFile(content, filePath);
2630
- } catch {
2631
- return null;
2632
- }
2633
- }
2634
-
2635
- // src/ai/agent.ts
2636
- async function runServerAgent(options) {
2637
- const {
2638
- userMessage,
2639
- conversationId,
2640
- historyLeafMessageId,
2641
- chatType = "group",
2642
- locale = "zh-CN",
2643
- assistantSystemPrompt,
2644
- skillMenu,
2645
- skillDef,
2646
- compressionConfig,
2647
- tools = [],
2648
- aiDataDir,
2649
- convManager: convManager2,
2650
- onEvent,
2651
- abortSignal,
2652
- ownerInfo,
2653
- mentionedMembers,
2654
- dataSnapshot,
2655
- thinkingLevel
2656
- } = options;
2657
- const aiLogger = getServerAiLogger();
2658
- await initTokenizer();
2659
- const llmConfig = getDefaultAssistantConfig(aiDataDir);
2660
- if (!llmConfig) {
2661
- onEvent({ type: "error", error: { name: "ConfigError", message: "LLM service not configured" } });
2662
- onEvent({ type: "done", isFinished: true });
2663
- return;
2664
- }
2665
- const piModel = buildPiModel2(llmConfig);
2666
- const t = createAiTranslate(locale);
2667
- let skillCtx;
2668
- if (skillDef) {
2669
- skillCtx = { skillDef };
2670
- } else if (skillMenu) {
2671
- skillCtx = { skillMenu };
2672
- }
2673
- const systemPrompt = buildSystemPrompt({
2674
- t,
2675
- chatType,
2676
- assistantSystemPrompt,
2677
- ownerInfo,
2678
- locale,
2679
- skillCtx,
2680
- mentionedMembers,
2681
- dataSnapshot
2682
- });
2683
- const handler = new AgentEventHandler({
2684
- onChunk: onEvent,
2685
- context: {},
2686
- systemPrompt
2687
- });
2688
- if (compressionConfig?.enabled && historyLeafMessageId === void 0) {
2689
- const llmAdapter = createCompressionLlmAdapter({
2690
- piModel,
2691
- apiKey: llmConfig.apiKey,
2692
- onCompressing: () => handler.emitStatus("compressing", [])
2693
- });
2694
- const compressionResult = await checkAndCompress(
2695
- conversationId,
2696
- compressionConfig,
2697
- systemPrompt,
2698
- llmAdapter,
2699
- convManager2,
2700
- aiLogger ?? void 0
2701
- );
2702
- if (compressionResult.compressed) {
2703
- onEvent({
2704
- type: "compression_done",
2705
- compressionResult: {
2706
- summaryContent: compressionResult.summaryContent ?? "",
2707
- tokensBefore: compressionResult.tokensBefore ?? 0,
2708
- tokensAfter: compressionResult.tokensAfter ?? 0,
2709
- timestamp: Date.now()
2710
- }
2711
- });
2712
- }
2713
- } else if (compressionConfig?.enabled && historyLeafMessageId !== void 0) {
2714
- aiLogger?.info?.("Compression", "Skipping compression for edited branch request", {
2715
- conversationId,
2716
- historyLeafMessageId
2717
- });
2718
- }
2719
- if (abortSignal?.aborted) {
2720
- handler.emitStatus("aborted", [], { force: true });
2721
- onEvent({ type: "done", isFinished: true, usage: handler.cloneUsage() });
2722
- return;
2723
- }
2724
- let history = [];
2725
- try {
2726
- history = convManager2.getHistoryForAgent(conversationId, void 0, historyLeafMessageId);
2727
- } catch {
2728
- }
2729
- handler.emitStatus("preparing", [], { pendingUserMessage: userMessage, force: true });
2730
- const steerMessage = t("ai.agent.answerWithoutTools");
2731
- let cachedMessages = [];
2732
- try {
2733
- const result = await runAgentCore({
2734
- piModel,
2735
- apiKey: llmConfig.apiKey,
2736
- systemPrompt,
2737
- tools,
2738
- history,
2739
- userMessage,
2740
- maxToolRounds: 5,
2741
- abortSignal,
2742
- steerMessage,
2743
- thinkingLevel,
2744
- onConvertToLlm: (filteredMessages) => {
2745
- cachedMessages = filteredMessages;
2746
- },
2747
- onEvent: (coreEvent) => handler.handleCoreEvent(coreEvent, cachedMessages),
2748
- onDebugContext: (messages) => {
2749
- try {
2750
- convManager2.setPendingDebugContext(conversationId, JSON.stringify(messages, null, 2));
2751
- } catch {
2752
- }
2753
- }
2754
- });
2755
- if (result.error) {
2756
- const friendlyMessage = formatAIError(result.error);
2757
- onEvent({ type: "error", error: { name: "AgentError", message: friendlyMessage } });
2758
- }
2759
- handler.emitStatus("completed", cachedMessages, { force: true });
2760
- onEvent({ type: "done", isFinished: true, usage: result.usage });
2761
- } catch (error) {
2762
- const friendlyMessage = formatAIError(error);
2763
- aiLogger?.error("ServerAgent", "Agent execution error", { error: String(error) });
2764
- handler.emitStatus("error", cachedMessages, { force: true });
2765
- onEvent({ type: "error", error: { name: "AgentError", message: friendlyMessage } });
2766
- onEvent({ type: "done", isFinished: true, usage: handler.cloneUsage() });
2767
- }
2768
- }
2769
-
2770
- // src/ai/agent-stream-runner.ts
2771
- function getAiDir(dbManager2) {
2772
- const pathProvider = dbManager2["pathProvider"];
2773
- if (!pathProvider) {
2774
- throw Object.assign(new Error("PathProvider not available"), { statusCode: 500 });
2775
- }
2776
- return pathProvider.getAiDataDir();
2777
- }
2778
- function createCliRunAgentStream(dbManager2, convManager2) {
2779
- return async (params, onEvent, abortSignal) => {
2780
- const {
2781
- userMessage,
2782
- conversationId,
2783
- historyLeafMessageId,
2784
- sessionId,
2785
- chatType,
2786
- locale,
2787
- assistantId,
2788
- skillId,
2789
- enableAutoSkill,
2790
- compressionConfig,
2791
- ownerInfo,
2792
- mentionedMembers,
2793
- thinkingLevel
2794
- } = params;
2795
- const aiDataDir = getAiDir(dbManager2);
2796
- let assistantSystemPrompt;
2797
- if (assistantId) {
2798
- const assistantConfig = loadAssistantConfig(aiDataDir, assistantId);
2799
- if (assistantConfig?.systemPrompt) {
2800
- assistantSystemPrompt = assistantConfig.systemPrompt;
2801
- }
2802
- }
2803
- const llmConfig = getDefaultAssistantConfig(aiDataDir);
2804
- const maxToolResultPercent = compressionConfig?.maxToolResultPercent ?? 50;
2805
- const contextWindow = llmConfig ? buildPiModel2(llmConfig).contextWindow ?? 128e3 : 128e3;
2806
- const maxToolResultTokens = Math.floor(contextWindow * (maxToolResultPercent / 100));
2807
- const db = dbManager2.open?.(sessionId);
2808
- const agentTools = db ? adaptToolsForAgent(AGENT_TOOL_REGISTRY, () => ({ db, sessionId, locale }), { maxToolResultTokens }) : [];
2809
- const skillMgr = new SkillManager(aiDataDir);
2810
- skillMgr.init();
2811
- const toolNames = agentTools.map((t) => t.name);
2812
- let resolvedSkillDef;
2813
- let resolvedSkillMenu;
2814
- if (skillId) {
2815
- const def = skillMgr.getSkillConfig(skillId);
2816
- if (def) resolvedSkillDef = { name: def.name, prompt: def.prompt };
2817
- } else if (enableAutoSkill) {
2818
- const menu = skillMgr.getSkillMenu(chatType ?? "group", toolNames);
2819
- if (menu) resolvedSkillMenu = menu;
2820
- }
2821
- if (resolvedSkillMenu) {
2822
- const activateSkillTool = createActivateSkillTool({
2823
- chatType: chatType ?? "group",
2824
- allowedTools: toolNames,
2825
- locale,
2826
- getSkillConfig: (id) => skillMgr.getSkillConfig(id)
2827
- });
2828
- agentTools.push(activateSkillTool);
2829
- }
2830
- const resolvedCompression = compressionConfig?.enabled ? {
2831
- enabled: true,
2832
- tokenThresholdPercent: compressionConfig.tokenThresholdPercent ?? 75,
2833
- bufferSizePercent: compressionConfig.bufferSizePercent ?? 20,
2834
- maxToolResultPercent: compressionConfig.maxToolResultPercent
2835
- } : void 0;
2836
- let dataSnapshot;
2837
- if (db) {
2838
- try {
2839
- const overview = getChatOverview(db, 5);
2840
- if (overview) {
2841
- dataSnapshot = {
2842
- name: overview.name,
2843
- platform: overview.platform,
2844
- type: overview.type,
2845
- totalMessages: overview.totalMessages,
2846
- totalMembers: overview.totalMembers,
2847
- firstMessageTs: overview.firstMessageTs,
2848
- lastMessageTs: overview.lastMessageTs,
2849
- capturedAt: Math.floor(Date.now() / 1e3)
2850
- };
2851
- }
2852
- } catch {
2853
- }
2854
- }
2855
- await runServerAgent({
2856
- userMessage,
2857
- conversationId,
2858
- historyLeafMessageId,
2859
- chatType,
2860
- locale,
2861
- assistantSystemPrompt,
2862
- skillMenu: resolvedSkillMenu,
2863
- skillDef: resolvedSkillDef,
2864
- compressionConfig: resolvedCompression,
2865
- tools: agentTools,
2866
- aiDataDir,
2867
- convManager: convManager2,
2868
- onEvent,
2869
- abortSignal,
2870
- ownerInfo,
2871
- mentionedMembers,
2872
- dataSnapshot,
2873
- thinkingLevel
2874
- });
2875
- };
2876
- }
2877
-
2878
2498
  // ../../packages/sync/src/types.ts
2879
2499
  var noop = () => {
2880
2500
  };
2881
2501
  var NOOP_LOGGER = { info: noop, warn: noop, error: noop };
2882
2502
 
2883
2503
  // ../../packages/sync/src/data-source-manager.ts
2884
- import * as fs8 from "fs";
2885
- import * as path10 from "path";
2504
+ import * as fs6 from "fs";
2505
+ import * as path8 from "path";
2886
2506
  import * as crypto from "crypto";
2887
2507
  var CONFIG_FILE = "data-sources.json";
2888
2508
  function generateId(prefix = "ds") {
@@ -2905,22 +2525,22 @@ function isValidDataSourceArray(data) {
2905
2525
  var DataSourceManager = class {
2906
2526
  configDir;
2907
2527
  logger;
2908
- constructor(configDir, logger2) {
2528
+ constructor(configDir, logger) {
2909
2529
  this.configDir = configDir;
2910
- this.logger = logger2 ?? NOOP_LOGGER;
2530
+ this.logger = logger ?? NOOP_LOGGER;
2911
2531
  }
2912
2532
  getConfigPath() {
2913
- return path10.join(this.configDir, CONFIG_FILE);
2533
+ return path8.join(this.configDir, CONFIG_FILE);
2914
2534
  }
2915
2535
  ensureDir() {
2916
- fs8.mkdirSync(this.configDir, { recursive: true });
2536
+ fs6.mkdirSync(this.configDir, { recursive: true });
2917
2537
  }
2918
2538
  // ==================== Load / Save ====================
2919
2539
  loadAll() {
2920
2540
  try {
2921
2541
  const filePath = this.getConfigPath();
2922
- if (fs8.existsSync(filePath)) {
2923
- const raw = fs8.readFileSync(filePath, "utf-8");
2542
+ if (fs6.existsSync(filePath)) {
2543
+ const raw = fs6.readFileSync(filePath, "utf-8");
2924
2544
  const parsed = JSON.parse(raw);
2925
2545
  if (!isValidDataSourceArray(parsed)) {
2926
2546
  this.logger.warn("[DataSource] Incompatible config format detected, returning empty.");
@@ -2939,7 +2559,7 @@ var DataSourceManager = class {
2939
2559
  saveAll(sources) {
2940
2560
  try {
2941
2561
  this.ensureDir();
2942
- fs8.writeFileSync(this.getConfigPath(), JSON.stringify(sources, null, 2), "utf-8");
2562
+ fs6.writeFileSync(this.getConfigPath(), JSON.stringify(sources, null, 2), "utf-8");
2943
2563
  } catch (err) {
2944
2564
  this.logger.error("[DataSource] Failed to save config", err);
2945
2565
  }
@@ -3064,7 +2684,7 @@ function parseRemoteSessionsResponse(body) {
3064
2684
  }
3065
2685
 
3066
2686
  // ../../packages/sync/src/pull-engine.ts
3067
- import * as fs9 from "fs";
2687
+ import * as fs7 from "fs";
3068
2688
  import * as crypto2 from "crypto";
3069
2689
  var MAX_PAGES_PER_PULL = 5e3;
3070
2690
  var PULL_OVERLAP_SECONDS = 60;
@@ -3084,7 +2704,7 @@ function parseSyncFromFile(filePath) {
3084
2704
  try {
3085
2705
  const isJsonl = filePath.endsWith(".jsonl");
3086
2706
  if (isJsonl) {
3087
- const content = fs9.readFileSync(filePath, "utf-8");
2707
+ const content = fs7.readFileSync(filePath, "utf-8");
3088
2708
  const lines = content.trimEnd().split("\n");
3089
2709
  for (let i = lines.length - 1; i >= Math.max(0, lines.length - 5); i--) {
3090
2710
  try {
@@ -3103,7 +2723,7 @@ function parseSyncFromFile(filePath) {
3103
2723
  }
3104
2724
  return null;
3105
2725
  }
3106
- const raw = fs9.readFileSync(filePath, "utf-8");
2726
+ const raw = fs7.readFileSync(filePath, "utf-8");
3107
2727
  const parsed = JSON.parse(raw);
3108
2728
  if (parsed.sync && typeof parsed.sync === "object") {
3109
2729
  const s = parsed.sync;
@@ -3117,7 +2737,7 @@ function parseSyncFromFile(filePath) {
3117
2737
  function fileContainsMessages(filePath) {
3118
2738
  try {
3119
2739
  if (filePath.endsWith(".jsonl")) {
3120
- const content = fs9.readFileSync(filePath, "utf-8");
2740
+ const content = fs7.readFileSync(filePath, "utf-8");
3121
2741
  for (const line of content.split("\n")) {
3122
2742
  const trimmed = line.trim();
3123
2743
  if (!trimmed) continue;
@@ -3130,7 +2750,7 @@ function fileContainsMessages(filePath) {
3130
2750
  }
3131
2751
  return false;
3132
2752
  }
3133
- const raw = fs9.readFileSync(filePath, "utf-8");
2753
+ const raw = fs7.readFileSync(filePath, "utf-8");
3134
2754
  const parsed = JSON.parse(raw);
3135
2755
  return Array.isArray(parsed.messages) && parsed.messages.length > 0;
3136
2756
  } catch {
@@ -3139,7 +2759,7 @@ function fileContainsMessages(filePath) {
3139
2759
  }
3140
2760
  function cleanupTempFile(filePath) {
3141
2761
  try {
3142
- if (fs9.existsSync(filePath)) fs9.unlinkSync(filePath);
2762
+ if (fs7.existsSync(filePath)) fs7.unlinkSync(filePath);
3143
2763
  } catch {
3144
2764
  }
3145
2765
  }
@@ -3199,7 +2819,7 @@ var PullEngine = class {
3199
2819
  limit: ds.pullLimit
3200
2820
  });
3201
2821
  try {
3202
- const stat2 = fs9.statSync(tempFile);
2822
+ const stat2 = fs7.statSync(tempFile);
3203
2823
  this.logger.info(`[Pull] "${sess.name}" page ${pageCount}: fetched ${stat2.size} bytes`);
3204
2824
  const sync0 = parseSyncFromFile(tempFile);
3205
2825
  if (stat2.size < 1024) {
@@ -3217,7 +2837,7 @@ var PullEngine = class {
3217
2837
  since,
3218
2838
  limit: ds.pullLimit
3219
2839
  });
3220
- const retryStat = fs9.statSync(retryFile);
2840
+ const retryStat = fs7.statSync(retryFile);
3221
2841
  this.logger.info(`[Pull] "${sess.name}" retry ${ri + 1}: fetched ${retryStat.size} bytes`);
3222
2842
  const retrySync = parseSyncFromFile(retryFile);
3223
2843
  if (retryStat.size < 1024 && !fileContainsMessages(retryFile) && retrySync?.hasMore === false) {
@@ -3491,13 +3111,13 @@ function reloadTimer(dsId, skipInitialPull = false) {
3491
3111
  }
3492
3112
 
3493
3113
  // src/sync/adapters.ts
3494
- import * as fs10 from "fs";
3114
+ import * as fs8 from "fs";
3495
3115
  import * as os4 from "os";
3496
- import * as path11 from "path";
3116
+ import * as path9 from "path";
3497
3117
  import * as crypto3 from "crypto";
3498
3118
  function getTempFilePath(ext) {
3499
3119
  const id = crypto3.randomBytes(8).toString("hex");
3500
- return path11.join(os4.tmpdir(), `chatlab-pull-${id}${ext}`);
3120
+ return path9.join(os4.tmpdir(), `chatlab-pull-${id}${ext}`);
3501
3121
  }
3502
3122
  var NodeFetcher = class {
3503
3123
  async fetchToTempFile(baseUrl, remoteSessionId, token, params) {
@@ -3514,45 +3134,38 @@ var NodeFetcher = class {
3514
3134
  const isJsonl = contentType.includes("ndjson") || contentType.includes("jsonl");
3515
3135
  const tempFile = getTempFilePath(isJsonl ? ".jsonl" : ".json");
3516
3136
  const buffer = Buffer.from(await response.arrayBuffer());
3517
- fs10.writeFileSync(tempFile, buffer);
3137
+ fs8.writeFileSync(tempFile, buffer);
3518
3138
  return tempFile;
3519
3139
  }
3520
3140
  };
3521
- function resolveNativeBinding2() {
3522
- if (process.versions.electron) return void 0;
3523
- const nativePath = resolveCliPath("native/better_sqlite3.node");
3524
- if (fs10.existsSync(nativePath)) return nativePath;
3525
- return void 0;
3526
- }
3527
3141
  var DirectImporter = class {
3528
3142
  dbManager;
3529
- nativeBinding;
3530
3143
  logger;
3531
- constructor(dbManager2, logger2) {
3144
+ constructor(dbManager2, logger) {
3532
3145
  this.dbManager = dbManager2;
3533
- this.nativeBinding = resolveNativeBinding2();
3534
- this.logger = logger2 ?? NOOP_LOGGER;
3146
+ this.logger = logger ?? NOOP_LOGGER;
3535
3147
  }
3536
3148
  sessionExists(sessionId) {
3537
3149
  const dbPath = this.dbManager.getDbPath(sessionId);
3538
- if (!fs10.existsSync(dbPath)) return false;
3150
+ if (!fs8.existsSync(dbPath)) return false;
3539
3151
  try {
3540
- const db = openBetterSqliteDatabase(dbPath, { readonly: true, nativeBinding: this.nativeBinding });
3152
+ const db = this.dbManager.openRawSessionDatabase(sessionId, { readonly: true });
3541
3153
  const row = db.prepare("SELECT COUNT(*) as cnt FROM sqlite_master WHERE type='table' AND name='message'").get();
3542
3154
  db.close();
3543
3155
  if (row.cnt === 0) {
3544
3156
  this.logger.warn(`[DirectImporter] DB file exists but has no message table: ${sessionId}, removing`);
3545
3157
  try {
3546
- fs10.unlinkSync(dbPath);
3158
+ fs8.unlinkSync(dbPath);
3547
3159
  } catch {
3548
3160
  }
3549
3161
  return false;
3550
3162
  }
3551
3163
  return true;
3552
- } catch {
3164
+ } catch (error) {
3165
+ if (error instanceof DataDirCompatibilityError) throw error;
3553
3166
  this.logger.warn(`[DirectImporter] Cannot validate DB file: ${sessionId}, removing`);
3554
3167
  try {
3555
- fs10.unlinkSync(dbPath);
3168
+ fs8.unlinkSync(dbPath);
3556
3169
  } catch {
3557
3170
  }
3558
3171
  return false;
@@ -3573,8 +3186,7 @@ var DirectImporter = class {
3573
3186
  const data = await parseFile(tempFile);
3574
3187
  this.dbManager.close(sessionId);
3575
3188
  const result = await importData(this.dbManager, data, {
3576
- sessionId,
3577
- nativeBinding: this.nativeBinding
3189
+ sessionId
3578
3190
  });
3579
3191
  if (result.success) {
3580
3192
  this.logger.info(
@@ -3599,8 +3211,7 @@ var DirectImporter = class {
3599
3211
  try {
3600
3212
  const data = await parseFile(tempFile);
3601
3213
  const result = await importData(this.dbManager, data, {
3602
- sessionId: externalId,
3603
- nativeBinding: this.nativeBinding
3214
+ sessionId: externalId
3604
3215
  });
3605
3216
  if (result.success) {
3606
3217
  this.logger.info(
@@ -3672,8 +3283,8 @@ function registerAutomationRoutes(server2, ctx) {
3672
3283
  if (request.query.deleteData === "true" && removed.targetSessionId) {
3673
3284
  dbManager2.close(removed.targetSessionId);
3674
3285
  const dbPath = dbManager2.getDbPath(removed.targetSessionId);
3675
- const fs12 = await import("fs");
3676
- if (fs12.existsSync(dbPath)) fs12.unlinkSync(dbPath);
3286
+ const fs10 = await import("fs");
3287
+ if (fs10.existsSync(dbPath)) fs10.unlinkSync(dbPath);
3677
3288
  }
3678
3289
  return { success: true };
3679
3290
  });
@@ -3748,26 +3359,26 @@ function cleanupSync() {
3748
3359
  // src/http/index.ts
3749
3360
  var server = null;
3750
3361
  var dbManager = null;
3751
- var convManager = null;
3362
+ var aiChatManager = null;
3752
3363
  function createFileConfigStorage(aiDataDir) {
3753
3364
  return {
3754
3365
  readJson(key) {
3755
3366
  try {
3756
- return JSON.parse(fs11.readFileSync(`${aiDataDir}/${key}.json`, "utf-8"));
3367
+ return JSON.parse(fs9.readFileSync(`${aiDataDir}/${key}.json`, "utf-8"));
3757
3368
  } catch {
3758
3369
  return null;
3759
3370
  }
3760
3371
  },
3761
3372
  writeJson(key, data) {
3762
- if (!fs11.existsSync(aiDataDir)) fs11.mkdirSync(aiDataDir, { recursive: true });
3763
- fs11.writeFileSync(`${aiDataDir}/${key}.json`, JSON.stringify(data, null, 2), "utf-8");
3373
+ if (!fs9.existsSync(aiDataDir)) fs9.mkdirSync(aiDataDir, { recursive: true });
3374
+ fs9.writeFileSync(`${aiDataDir}/${key}.json`, JSON.stringify(data, null, 2), "utf-8");
3764
3375
  }
3765
3376
  };
3766
3377
  }
3767
- function resolveNativeBinding3() {
3378
+ function resolveNativeBinding2() {
3768
3379
  if (process.versions.electron) return void 0;
3769
3380
  const nativePath = resolveCliPath("native/better_sqlite3.node");
3770
- if (fs11.existsSync(nativePath)) return nativePath;
3381
+ if (fs9.existsSync(nativePath)) return nativePath;
3771
3382
  return void 0;
3772
3383
  }
3773
3384
  function ensureToken(config) {
@@ -3799,6 +3410,7 @@ async function startHttpServer(options) {
3799
3410
  const userDataDir = config.data.user_data_dir || void 0;
3800
3411
  const pathProvider = new NodePathProvider(userDataDir);
3801
3412
  pathProvider.ensureAllDirs();
3413
+ const runtime = assertCliDataDirCompatible(pathProvider, "cli");
3802
3414
  if (hasPendingElectronDataWarning() || !verifyCliDataPath(pathProvider.getDatabaseDir())) {
3803
3415
  console.error(
3804
3416
  "\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"
@@ -3814,10 +3426,10 @@ async function startHttpServer(options) {
3814
3426
  }
3815
3427
  });
3816
3428
  await migrationRunner.run();
3817
- const nativeBinding = resolveNativeBinding3();
3818
- dbManager = new DatabaseManager(pathProvider, { nativeBinding });
3429
+ const nativeBinding = resolveNativeBinding2();
3430
+ dbManager = new DatabaseManager(pathProvider, { nativeBinding, runtime });
3819
3431
  const aiDataDir = pathProvider.getAiDataDir();
3820
- convManager = new AIConversationManager(aiDataDir, { nativeBinding });
3432
+ aiChatManager = new AIChatManager(aiDataDir, { nativeBinding });
3821
3433
  const assistantManager = getAssistantManager(aiDataDir);
3822
3434
  const skillManagerCore = getSkillManagerCore(aiDataDir);
3823
3435
  const llmConfigStore = new LLMConfigStore(createFileConfigStorage(aiDataDir), {
@@ -3842,17 +3454,17 @@ async function startHttpServer(options) {
3842
3454
  nativeBinding,
3843
3455
  aiContext: {
3844
3456
  aiDataDir,
3845
- convManager,
3457
+ aiChatManager,
3846
3458
  assistantManager,
3847
3459
  skillManagerCore,
3848
3460
  llmConfigStore,
3849
3461
  customProviderStore: new CustomProviderStore(createFileConfigStorage(aiDataDir)),
3850
3462
  customModelStore: new CustomModelStore(createFileConfigStorage(aiDataDir)),
3851
- runAgentStream: createCliRunAgentStream(dbManager, convManager)
3463
+ runAgentStream: createCliRunAgentStream(dbManager, aiChatManager)
3852
3464
  }
3853
3465
  });
3854
3466
  initSync(server, dbManager, pathProvider, { port, host, token });
3855
- if (options?.webRoot && fs11.existsSync(options.webRoot)) {
3467
+ if (options?.webRoot && fs9.existsSync(options.webRoot)) {
3856
3468
  registerProxyRoutes(server);
3857
3469
  const fastifyStatic = await import("@fastify/static");
3858
3470
  await server.register(fastifyStatic.default, {
@@ -3873,9 +3485,9 @@ async function stopHttpServer() {
3873
3485
  await server.close();
3874
3486
  } finally {
3875
3487
  cleanupSync();
3876
- if (convManager) {
3877
- convManager.close();
3878
- convManager = null;
3488
+ if (aiChatManager) {
3489
+ aiChatManager.close();
3490
+ aiChatManager = null;
3879
3491
  }
3880
3492
  if (dbManager) {
3881
3493
  dbManager.closeAll();
@@ -3893,4 +3505,4 @@ export {
3893
3505
  startHttpServer,
3894
3506
  stopHttpServer
3895
3507
  };
3896
- //# sourceMappingURL=chunk-ZL322NVL.mjs.map
3508
+ //# sourceMappingURL=chunk-GTCTDD2Z.mjs.map