chatlab-cli 0.25.0 → 0.26.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 (70) hide show
  1. package/dist/chat-command-ZP4WJVWC.mjs +304 -0
  2. package/dist/chat-command-ZP4WJVWC.mjs.map +1 -0
  3. package/dist/{chunk-CIBTUWAE.mjs → chunk-6G7AIF7I.mjs} +38 -8
  4. package/dist/chunk-6G7AIF7I.mjs.map +1 -0
  5. package/dist/chunk-ILGSSXOG.mjs +549 -0
  6. package/dist/chunk-ILGSSXOG.mjs.map +1 -0
  7. package/dist/{chunk-E65ABM3C.mjs → chunk-IRZRIHIT.mjs} +100 -63
  8. package/dist/chunk-IRZRIHIT.mjs.map +1 -0
  9. package/dist/{chunk-4OMV4VNH.mjs → chunk-QY67NN65.mjs} +1900 -729
  10. package/dist/chunk-QY67NN65.mjs.map +1 -0
  11. package/dist/{chunk-FSHVDWI2.mjs → chunk-SJIOPSMM.mjs} +116 -569
  12. package/dist/chunk-SJIOPSMM.mjs.map +1 -0
  13. package/dist/{chunk-GNT5G74Z.mjs → chunk-TC74HESZ.mjs} +59 -33
  14. package/dist/chunk-TC74HESZ.mjs.map +1 -0
  15. package/dist/chunk-UB4XBM4R.mjs +40 -0
  16. package/dist/chunk-UB4XBM4R.mjs.map +1 -0
  17. package/dist/{chunk-TCPXAX3F.mjs → chunk-WXC6RZCX.mjs} +17 -25
  18. package/dist/chunk-WXC6RZCX.mjs.map +1 -0
  19. package/dist/cli.mjs +3 -2
  20. package/dist/{http-PMNZ42EN.mjs → http-J3IOFFIA.mjs} +8 -6
  21. package/dist/{import-OP7R4CYY.mjs → import-POYG5LOX.mjs} +4 -4
  22. package/dist/index.mjs +10 -8
  23. package/dist/{mcp-ABXNFUJO.mjs → mcp-7HH7UMXT.mjs} +11 -6
  24. package/dist/mcp-7HH7UMXT.mjs.map +1 -0
  25. package/dist/{stream-import-L6RJHH4L.mjs → stream-import-O3H3FGV2.mjs} +3 -3
  26. package/dist-web/assets/{DebugToolsPanel-DaSNc1o-.css → DebugToolsPanel-CrqULdXp.css} +1 -1
  27. package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-BTJxEma5.js +182 -0
  28. package/dist-web/assets/{EChartWordcloud-CzhfrEF_.js → EChartWordcloud-B_YisOW5.js} +1 -1
  29. package/dist-web/assets/{MessageExportModal-BAJKWX4y.js → MessageExportModal-C7NgEL8T.js} +1 -1
  30. package/dist-web/assets/{electron-CZt36wW5.js → electron-B3DFm1cC.js} +1 -1
  31. package/dist-web/assets/electron-BMM4Nfty.js +1 -0
  32. package/dist-web/assets/{fetch-qoGEVjNg.js → fetch-ArMjdMcy.js} +1 -1
  33. package/dist-web/assets/fetch-BFtuJaa1.js +1 -0
  34. package/dist-web/assets/{fetch-yWwp067l.js → fetch-BGfaAqO9.js} +1 -1
  35. package/dist-web/assets/{fetch-DD1EGRKV.js → fetch-BaJDB31c.js} +1 -1
  36. package/dist-web/assets/{fetch-JzVEwamn.js → fetch-BjDJgdN0.js} +1 -1
  37. package/dist-web/assets/{fetch-GMkMBzBS.js → fetch-C5CLcpQW.js} +1 -1
  38. package/dist-web/assets/{fetch-DXfZysDf.js → fetch-DQZvdHnG.js} +1 -1
  39. package/dist-web/assets/{fetch-D4p9vj1A.js → fetch-Dhfbt1BQ.js} +3 -3
  40. package/dist-web/assets/fetch-DnEP0uyF.js +1 -0
  41. package/dist-web/assets/{fetch-CgBIWyAo.js → fetch-SYrb-sZe.js} +1 -1
  42. package/dist-web/assets/index-CWfkrx37.js +173 -0
  43. package/dist-web/assets/index-D3N4NDFx.css +1 -0
  44. package/dist-web/assets/{index-O0PG26_v.js → index-D7_ch4zf.js} +1 -1
  45. package/dist-web/assets/{index-BrS_VrIY.js → index-DK9LEEzT.js} +1 -1
  46. package/dist-web/assets/index-DqDa_on9.js +9 -0
  47. package/dist-web/assets/{index-Cvlw0RLu.js → index-DrN1G9bl.js} +2 -2
  48. package/dist-web/assets/{index-DvWI6Yqa.js → index-MdYeovYo.js} +4 -4
  49. package/dist-web/assets/{vendor-nuxt-ui-C_8CsH6e.js → vendor-nuxt-ui-Zy8txNdC.js} +1 -1
  50. package/dist-web/assets/{vendor-reka-ui-CIMXwvEp.js → vendor-reka-ui-mMvma1EP.js} +1 -1
  51. package/dist-web/assets/{web-4rtrAcLu.js → web-zEXsvoZW.js} +1 -1
  52. package/dist-web/index.html +4 -4
  53. package/package.json +1 -1
  54. package/dist/chunk-4OMV4VNH.mjs.map +0 -1
  55. package/dist/chunk-CIBTUWAE.mjs.map +0 -1
  56. package/dist/chunk-E65ABM3C.mjs.map +0 -1
  57. package/dist/chunk-FSHVDWI2.mjs.map +0 -1
  58. package/dist/chunk-GNT5G74Z.mjs.map +0 -1
  59. package/dist/chunk-TCPXAX3F.mjs.map +0 -1
  60. package/dist/mcp-ABXNFUJO.mjs.map +0 -1
  61. package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-BUwpIerl.js +0 -161
  62. package/dist-web/assets/electron-CwERrTWp.js +0 -1
  63. package/dist-web/assets/fetch-BxFAkm7O.js +0 -1
  64. package/dist-web/assets/fetch-DO8lty7_.js +0 -1
  65. package/dist-web/assets/index-C1t-kzfo.css +0 -1
  66. package/dist-web/assets/index-DABpUm3J.js +0 -9
  67. package/dist-web/assets/index-OsjX5hXw.js +0 -173
  68. /package/dist/{http-PMNZ42EN.mjs.map → http-J3IOFFIA.mjs.map} +0 -0
  69. /package/dist/{import-OP7R4CYY.mjs.map → import-POYG5LOX.mjs.map} +0 -0
  70. /package/dist/{stream-import-L6RJHH4L.mjs.map → stream-import-O3H3FGV2.mjs.map} +0 -0
@@ -7,33 +7,38 @@ const __dirname = __pathDirname(__filename);
7
7
  import {
8
8
  importData,
9
9
  parseFile
10
- } from "./chunk-TCPXAX3F.mjs";
10
+ } from "./chunk-WXC6RZCX.mjs";
11
11
  import {
12
12
  analyzeIncrementalImport,
13
13
  analyzeNewImport,
14
14
  incrementalImport,
15
15
  streamImport
16
- } from "./chunk-GNT5G74Z.mjs";
16
+ } from "./chunk-TC74HESZ.mjs";
17
17
  import {
18
- AGENT_TOOL_REGISTRY,
19
- CoreDataProvider
20
- } from "./chunk-E65ABM3C.mjs";
18
+ assertCliDataDirCompatible
19
+ } from "./chunk-UB4XBM4R.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-ILGSSXOG.mjs";
28
+ import {
29
+ AGENT_TOOL_REGISTRY,
30
+ CoreDataProvider
31
+ } from "./chunk-IRZRIHIT.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
- CHART_CAPABILITY_CORE_TOOLS,
34
39
  CustomModelStore,
35
40
  CustomProviderStore,
36
- DEFAULT_MAX_TOOL_ROUNDS,
41
+ DataDirCompatibilityError,
37
42
  DatabaseManager,
38
43
  LLMConfigStore,
39
44
  MergeSessionCache,
@@ -41,24 +46,14 @@ import {
41
46
  NodePathProvider,
42
47
  POS_TAG_DEFINITIONS,
43
48
  PreferencesManager,
44
- SkillManager,
45
49
  SkillManagerCore,
46
50
  TempDbWriter,
47
51
  applyPendingNodeDataDirMigrationIfNeeded,
48
- applyPreprocessingPipeline,
49
- batchSegmentWithFrequency,
50
52
  buildMergedOutput,
51
53
  buildPiModel,
52
- buildSkillMenuWithBuiltinChart,
53
- buildSystemPrompt,
54
- checkAndCompress,
55
54
  checkConflictsFromSources,
56
55
  computeWordFrequency,
57
56
  countMessagesTokens,
58
- createActivateSkillTool,
59
- createAiTranslate,
60
- createChartSchemaGateState,
61
- createCompressionLlmAdapter,
62
57
  createDatabaseManagerAdapter,
63
58
  createJiebaNlpProvider,
64
59
  createNodeDataDirSwitch,
@@ -74,13 +69,9 @@ import {
74
69
  fetchRemoteModels,
75
70
  filterMessagesWithContext,
76
71
  findEntryFileInDirectory,
77
- formatAIError,
78
- getAllowedBuiltinToolsForChartAutoSkill,
79
72
  getAvailableYears,
80
73
  getBuiltinModelsByProvider,
81
74
  getCatchphraseAnalysis,
82
- getChartCapabilitySkill,
83
- getChatOverview,
84
75
  getClusterGraph,
85
76
  getDailyActivity,
86
77
  getDefaultNodeUserDataDir,
@@ -104,25 +95,19 @@ import {
104
95
  getSessionInfo,
105
96
  getSessionMeta,
106
97
  getSessionOverview,
107
- getSkillConfigWithBuiltinChart,
108
98
  getSupportedFormats,
109
99
  getTimeRange,
110
100
  getWeekdayActivity,
111
101
  getYearlyActivity,
112
102
  hasPendingElectronDataWarning,
113
103
  initNlpDir,
114
- initTokenizer,
115
104
  isDictDownloaded,
116
105
  isNewerStableVersion,
117
106
  loadConfig,
118
107
  member_service_exports,
119
108
  mergeRulesForLocale,
120
- openBetterSqliteDatabase,
121
- parseAssistantFile,
122
109
  queryMessages,
123
110
  resolveApiKey,
124
- resolveChartRuntimeForRequest,
125
- runAgentCore,
126
111
  runSimpleLlmStream,
127
112
  scanMultiChatFile,
128
113
  segmentText,
@@ -134,16 +119,15 @@ import {
134
119
  summary_service_exports,
135
120
  validateApiKey,
136
121
  verifyCliDataPath,
137
- wrapWithChartSchemaGate,
138
122
  writeAuthProfile,
139
123
  writeConfigField
140
- } from "./chunk-4OMV4VNH.mjs";
124
+ } from "./chunk-QY67NN65.mjs";
141
125
  import {
142
126
  resolveCliPath
143
127
  } from "./chunk-FJ35V3TE.mjs";
144
128
 
145
129
  // src/http/index.ts
146
- import * as fs11 from "fs";
130
+ import * as fs9 from "fs";
147
131
  import * as crypto4 from "crypto";
148
132
 
149
133
  // src/http/server.ts
@@ -159,6 +143,7 @@ var HTTP_STATUS = {
159
143
  ["SQL_EXECUTION_ERROR" /* SQL_EXECUTION_ERROR */]: 400,
160
144
  ["EXPORT_TOO_LARGE" /* EXPORT_TOO_LARGE */]: 400,
161
145
  ["BODY_TOO_LARGE" /* BODY_TOO_LARGE */]: 413,
146
+ ["DATA_DIR_INCOMPATIBLE" /* DATA_DIR_INCOMPATIBLE */]: 409,
162
147
  ["SERVER_ERROR" /* SERVER_ERROR */]: 500
163
148
  };
164
149
  var ApiError = class extends Error {
@@ -189,6 +174,14 @@ function exportTooLarge(count, limit) {
189
174
  function serverError(message = "Internal server error") {
190
175
  return new ApiError("SERVER_ERROR" /* SERVER_ERROR */, message);
191
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
+ }
192
185
  function successResponse(data, meta) {
193
186
  return {
194
187
  success: true,
@@ -799,7 +792,7 @@ function registerExportRoutes(server2, ctx) {
799
792
  timeFilter: body.timeFilter,
800
793
  senderIds: body.senderIds,
801
794
  contextSize: body.contextSize,
802
- chatSessionIds: body.chatSessionIds
795
+ segmentIds: body.segmentIds
803
796
  });
804
797
  if (!result.success) {
805
798
  return reply.code(500).send({ error: result.error });
@@ -1181,10 +1174,10 @@ function registerAiFilterRoutes(server2, ctx) {
1181
1174
  return filterMessagesWithContext(db, { keywords, timeFilter, senderIds, contextSize, page, pageSize });
1182
1175
  });
1183
1176
  server2.post("/_web/ai/multiple-sessions-messages", async (request, reply) => {
1184
- const { sessionId, chatSessionIds, page, pageSize } = request.body;
1177
+ const { sessionId, segmentIds, page, pageSize } = request.body;
1185
1178
  const db = ctx.dbManager.open(sessionId);
1186
1179
  if (!db) return reply.code(404).send({ error: `Session not found: ${sessionId}` });
1187
- return getMultipleSessionsMessages(db, chatSessionIds, page, pageSize);
1180
+ return getMultipleSessionsMessages(db, segmentIds, page, pageSize);
1188
1181
  });
1189
1182
  }
1190
1183
 
@@ -1263,31 +1256,31 @@ function registerAiToolRoutes(server2, ctx) {
1263
1256
  });
1264
1257
  }
1265
1258
 
1266
- // ../../packages/http-routes/src/routes/web/ai-conversations.ts
1267
- function registerAiConversationRoutes(server2, ctx) {
1268
- const cm = ctx.conversationManager;
1259
+ // ../../packages/http-routes/src/routes/web/ai-chats.ts
1260
+ function registerAiChatRoutes(server2, ctx) {
1261
+ const cm = ctx.aiChatManager;
1269
1262
  if (!cm) return;
1270
- server2.post("/_web/ai/conversations", async (request) => {
1263
+ server2.post("/_web/ai/chats", async (request) => {
1271
1264
  const { sessionId, title, assistantId } = request.body;
1272
- return cm.createConversation(sessionId, title, assistantId);
1265
+ return cm.createAIChat(sessionId, title, assistantId);
1273
1266
  });
1274
- server2.get("/_web/ai/conversations", async (request) => {
1267
+ server2.get("/_web/ai/chats", async (request) => {
1275
1268
  const { sessionId } = request.query;
1276
1269
  if (!sessionId) return [];
1277
- return cm.getConversations(sessionId);
1270
+ return cm.getAIChats(sessionId);
1278
1271
  });
1279
- server2.get("/_web/ai/conversations/:id", async (request, reply) => {
1280
- const conv = cm.getConversation(request.params.id);
1281
- 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" });
1282
1275
  return conv;
1283
1276
  });
1284
- server2.put("/_web/ai/conversations/:id/title", async (request) => {
1285
- 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);
1286
1279
  });
1287
- server2.delete("/_web/ai/conversations/:id", async (request) => {
1288
- return cm.deleteConversation(request.params.id);
1280
+ server2.delete("/_web/ai/chats/:id", async (request) => {
1281
+ return cm.deleteAIChat(request.params.id);
1289
1282
  });
1290
- server2.post("/_web/ai/conversations/:id/messages", async (request) => {
1283
+ server2.post("/_web/ai/chats/:id/messages", async (request) => {
1291
1284
  const { role, content, dataKeywords, dataMessageCount, contentBlocks, tokenUsage } = request.body;
1292
1285
  return cm.addMessage(
1293
1286
  request.params.id,
@@ -1299,23 +1292,23 @@ function registerAiConversationRoutes(server2, ctx) {
1299
1292
  tokenUsage
1300
1293
  );
1301
1294
  });
1302
- server2.get("/_web/ai/conversations/:id/messages", async (request) => {
1295
+ server2.get("/_web/ai/chats/:id/messages", async (request) => {
1303
1296
  return cm.getMessages(request.params.id);
1304
1297
  });
1305
- 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) => {
1306
1299
  const { id, messageId } = request.params;
1307
1300
  if (!id || typeof id !== "string" || !messageId || typeof messageId !== "string") {
1308
- return reply.code(400).send({ error: "conversation id and messageId are required" });
1301
+ return reply.code(400).send({ error: "aiChatId and messageId are required" });
1309
1302
  }
1310
1303
  cm.deleteMessagesFrom(id, messageId);
1311
1304
  return { success: true };
1312
1305
  });
1313
- server2.post("/_web/ai/conversations/:id/fork", async (request, reply) => {
1306
+ server2.post("/_web/ai/chats/:id/fork", async (request, reply) => {
1314
1307
  const { upToMessageId, title } = request.body;
1315
1308
  if (!upToMessageId || typeof upToMessageId !== "string") {
1316
1309
  return reply.code(400).send({ error: "upToMessageId is required" });
1317
1310
  }
1318
- return cm.forkConversation(request.params.id, upToMessageId, title);
1311
+ return cm.forkAIChat(request.params.id, upToMessageId, title);
1319
1312
  });
1320
1313
  server2.put("/_web/ai/messages/:messageId/content", async (request, reply) => {
1321
1314
  const { content } = request.body;
@@ -1325,23 +1318,23 @@ function registerAiConversationRoutes(server2, ctx) {
1325
1318
  cm.updateMessageContent(request.params.messageId, content);
1326
1319
  return { success: true };
1327
1320
  });
1328
- 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) => {
1329
1322
  const { id, messageId } = request.params;
1330
1323
  if (!id || !messageId) {
1331
- return reply.code(400).send({ error: "conversation id and messageId are required" });
1324
+ return reply.code(400).send({ error: "aiChatId and messageId are required" });
1332
1325
  }
1333
1326
  cm.deleteAndRelinkMessage(id, messageId);
1334
1327
  return { success: true };
1335
1328
  });
1336
- 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) => {
1337
1330
  const { afterMessageId, role, content, contentBlocks, tokenUsage } = request.body;
1338
1331
  if (!afterMessageId || typeof afterMessageId !== "string") {
1339
1332
  return reply.code(400).send({ error: "afterMessageId is required" });
1340
1333
  }
1341
1334
  return cm.insertMessageAfter(request.params.id, afterMessageId, role, content, contentBlocks, tokenUsage);
1342
1335
  });
1343
- server2.get("/_web/ai/conversations/:id/token-usage", async (request) => {
1344
- return cm.getConversationTokenUsage(request.params.id);
1336
+ server2.get("/_web/ai/chats/:id/token-usage", async (request) => {
1337
+ return cm.getAIChatTokenUsage(request.params.id);
1345
1338
  });
1346
1339
  server2.get("/_web/ai/debug/schema", async () => {
1347
1340
  return cm.getAiSchema();
@@ -1362,7 +1355,7 @@ function registerAiConversationRoutes(server2, ctx) {
1362
1355
  const cleared = cm.clearAllDebugContext();
1363
1356
  return { success: true, cleared };
1364
1357
  });
1365
- server2.get("/_web/ai/conversations/:id/estimate-tokens", async (request) => {
1358
+ server2.get("/_web/ai/chats/:id/estimate-tokens", async (request) => {
1366
1359
  const history = cm.getHistoryForAgent(request.params.id);
1367
1360
  const tokens = countMessagesTokens(history.map((m) => ({ role: m.role, content: m.content })));
1368
1361
  return { success: true, tokens, messageCount: history.length };
@@ -1389,8 +1382,8 @@ function registerAiSummaryRoutes(server2, ctx) {
1389
1382
  if (!deps) return;
1390
1383
  const { sessionAdapter: adapter } = ctx;
1391
1384
  server2.post("/_web/sessions/:id/summaries/generate", async (request, reply) => {
1392
- const { chatSessionId, locale, forceRegenerate, strategy } = request.body;
1393
- 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, {
1394
1387
  locale,
1395
1388
  forceRegenerate,
1396
1389
  strategy
@@ -1412,8 +1405,8 @@ function registerAiSummaryRoutes(server2, ctx) {
1412
1405
  return result;
1413
1406
  });
1414
1407
  server2.post("/_web/sessions/:id/summaries/check-can-generate", async (request) => {
1415
- const { chatSessionIds } = request.body;
1416
- 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);
1417
1410
  });
1418
1411
  }
1419
1412
 
@@ -1853,7 +1846,7 @@ function registerSharedRoutes(server2, ctx, options) {
1853
1846
  if (options?.requireAi) {
1854
1847
  const missing = [];
1855
1848
  if (!ctx.aiDataDir) missing.push("aiDataDir");
1856
- if (!ctx.conversationManager) missing.push("conversationManager");
1849
+ if (!ctx.aiChatManager) missing.push("aiChatManager");
1857
1850
  if (!ctx.assistantManager) missing.push("assistantManager");
1858
1851
  if (!ctx.skillManagerCore) missing.push("skillManagerCore");
1859
1852
  if (!ctx.llmConfigStore) missing.push("llmConfigStore");
@@ -1871,7 +1864,7 @@ function registerSharedRoutes(server2, ctx, options) {
1871
1864
  registerAiAgentStreamRoutes(server2, ctx);
1872
1865
  registerAiFilterRoutes(server2, ctx);
1873
1866
  registerAiToolRoutes(server2, ctx);
1874
- registerAiConversationRoutes(server2, ctx);
1867
+ registerAiChatRoutes(server2, ctx);
1875
1868
  registerAiSummaryRoutes(server2, ctx);
1876
1869
  registerMergeRoutes(server2, ctx);
1877
1870
  registerCacheRoutes(server2, ctx);
@@ -1929,8 +1922,9 @@ function createServer() {
1929
1922
  });
1930
1923
  server2.addHook("onRequest", authHook);
1931
1924
  server2.setErrorHandler((error, _request, reply) => {
1932
- if (error instanceof ApiError) {
1933
- reply.code(error.statusCode).send(errorResponse(error));
1925
+ const apiError = apiErrorFromUnknown(error);
1926
+ if (apiError) {
1927
+ reply.code(apiError.statusCode).send(errorResponse(apiError));
1934
1928
  return;
1935
1929
  }
1936
1930
  if (error.statusCode === 413) {
@@ -2346,7 +2340,7 @@ function registerWebRoutes(server2, dbManager2, options) {
2346
2340
  const resolvedPathProvider = options?.pathProvider ?? fallbackPathProvider;
2347
2341
  const ai = options?.aiContext;
2348
2342
  const cliStreamImport = async (dm, filePath) => {
2349
- const { streamImport: streamImport2 } = await import("./stream-import-L6RJHH4L.mjs");
2343
+ const { streamImport: streamImport2 } = await import("./stream-import-O3H3FGV2.mjs");
2350
2344
  const result = await streamImport2(dm, filePath);
2351
2345
  if (!result.sessionId) throw new Error("Import succeeded but no sessionId returned");
2352
2346
  return { sessionId: result.sessionId };
@@ -2382,7 +2376,7 @@ function registerWebRoutes(server2, dbManager2, options) {
2382
2376
  },
2383
2377
  ...ai && {
2384
2378
  aiDataDir: ai.aiDataDir,
2385
- conversationManager: ai.convManager,
2379
+ aiChatManager: ai.aiChatManager,
2386
2380
  assistantManager: ai.assistantManager,
2387
2381
  skillManagerCore: ai.skillManagerCore,
2388
2382
  llmConfigStore: ai.llmConfigStore,
@@ -2442,24 +2436,6 @@ function registerProxyRoutes(server2) {
2442
2436
  });
2443
2437
  }
2444
2438
 
2445
- // src/ai/logger.ts
2446
- var logger = null;
2447
- function initServerAiLogger(logsDir) {
2448
- if (!logger) {
2449
- logger = new AiLogger(logsDir);
2450
- }
2451
- return logger;
2452
- }
2453
- function getServerAiLogger() {
2454
- return logger;
2455
- }
2456
- function closeServerAiLogger() {
2457
- if (logger) {
2458
- logger.close();
2459
- logger = null;
2460
- }
2461
- }
2462
-
2463
2439
  // src/ai/manager-factory.ts
2464
2440
  import * as fs5 from "fs";
2465
2441
  import * as path7 from "path";
@@ -2519,435 +2495,14 @@ function getSkillManagerCore(aiDataDir) {
2519
2495
  return cached.skill;
2520
2496
  }
2521
2497
 
2522
- // src/ai/tool-adapter.ts
2523
- var DEFAULT_MAX_TOOL_RESULT_TOKENS = 8e3;
2524
- var TOOL_TRUNCATION_STRATEGY = {
2525
- search_messages: "keep_first",
2526
- deep_search_messages: "keep_first",
2527
- get_recent_messages: "keep_last",
2528
- get_message_context: "keep_last",
2529
- get_session_messages: "keep_last",
2530
- get_conversation_between: "keep_last"
2531
- };
2532
- function convertJsonSchemaToParameters(schema) {
2533
- const properties = {};
2534
- for (const [key, prop] of Object.entries(schema.properties)) {
2535
- properties[key] = { ...prop };
2536
- }
2537
- return {
2538
- type: "object",
2539
- properties,
2540
- required: schema.required || []
2541
- };
2542
- }
2543
- function adaptToolsForAgent(tools, getContext, options) {
2544
- const tokenBudget = options?.maxToolResultTokens ?? DEFAULT_MAX_TOOL_RESULT_TOKENS;
2545
- const chartSchemaGateState = createChartSchemaGateState();
2546
- return tools.map(
2547
- (tool) => wrapWithChartSchemaGate(
2548
- {
2549
- name: tool.name,
2550
- label: tool.name,
2551
- description: tool.description,
2552
- parameters: convertJsonSchemaToParameters(tool.inputSchema),
2553
- async execute(_toolCallId, params) {
2554
- const toolParams = params && typeof params === "object" ? params : {};
2555
- const ctx = getContext();
2556
- const execCtx = {
2557
- db: ctx.db,
2558
- dataProvider: new CoreDataProvider(ctx.db),
2559
- sessionId: ctx.sessionId,
2560
- locale: ctx.locale,
2561
- segmentText: (texts, locale, options2) => batchSegmentWithFrequency(texts, locale, options2)
2562
- };
2563
- try {
2564
- const result = await tool.handler(toolParams, execCtx);
2565
- const chartDetails = result.chart || result.charts ? {
2566
- ...result.chart ? { chart: result.chart } : {},
2567
- ...result.charts ? { charts: result.charts } : {}
2568
- } : {};
2569
- if (result.rawMessages && result.rawMessages.length > 0) {
2570
- const pipelineResult = applyPreprocessingPipeline({
2571
- rawMessages: result.rawMessages,
2572
- locale: ctx.locale,
2573
- maxToolResultTokens: tokenBudget,
2574
- truncationStrategy: TOOL_TRUNCATION_STRATEGY[tool.name] ?? "keep_last",
2575
- extraDetails: result.data ?? {},
2576
- logger: getServerAiLogger() ?? void 0
2577
- });
2578
- return {
2579
- content: [{ type: "text", text: pipelineResult.text }],
2580
- details: Object.keys(chartDetails).length > 0 ? chartDetails : null
2581
- };
2582
- }
2583
- const baseDetails = typeof result.data === "object" && result.data !== null ? result.data : result.data === void 0 ? null : { value: result.data };
2584
- return {
2585
- content: [{ type: "text", text: result.content }],
2586
- details: Object.keys(chartDetails).length > 0 ? { ...baseDetails ?? {}, ...chartDetails } : baseDetails
2587
- };
2588
- } catch (error) {
2589
- const msg = error instanceof Error ? error.message : String(error);
2590
- return { content: [{ type: "text", text: `Error: ${msg}` }], details: null };
2591
- }
2592
- }
2593
- },
2594
- chartSchemaGateState
2595
- )
2596
- );
2597
- }
2598
-
2599
- // src/ai/llm-config.ts
2600
- import * as fs6 from "fs";
2601
- import * as path8 from "path";
2602
- function loadLlmConfig(aiDataDir) {
2603
- const configPath = path8.join(aiDataDir, "llm-config.json");
2604
- if (!fs6.existsSync(configPath)) {
2605
- return { configs: [], defaultAssistant: null, fastModel: null };
2606
- }
2607
- try {
2608
- const data = JSON.parse(fs6.readFileSync(configPath, "utf-8"));
2609
- const configs = (data.configs || []).map((c) => {
2610
- const provider = c.provider || "";
2611
- const authProfile = c.authProfile;
2612
- const profileKey = resolveApiKey(provider, authProfile);
2613
- const rawKey = c.apiKey || "";
2614
- const fallbackKey = rawKey.startsWith("enc:") ? "" : rawKey;
2615
- return {
2616
- ...c,
2617
- apiKey: profileKey || fallbackKey
2618
- };
2619
- });
2620
- return {
2621
- configs,
2622
- defaultAssistant: data.defaultAssistant ?? null,
2623
- fastModel: data.fastModel ?? null
2624
- };
2625
- } catch {
2626
- return { configs: [], defaultAssistant: null, fastModel: null };
2627
- }
2628
- }
2629
- function resolveSlot(slot, configs) {
2630
- if (slot && configs.some((c) => c.id === slot.configId)) return slot;
2631
- const fallback = configs[0];
2632
- if (!fallback) return null;
2633
- return { configId: fallback.id, modelId: fallback.model };
2634
- }
2635
- function getDefaultAssistantConfig(aiDataDir) {
2636
- const store = loadLlmConfig(aiDataDir);
2637
- const slot = resolveSlot(store.defaultAssistant, store.configs);
2638
- if (!slot) return null;
2639
- const config = store.configs.find((c) => c.id === slot.configId);
2640
- if (!config) return null;
2641
- return { ...config, model: slot.modelId || config.model };
2642
- }
2643
- function buildPiModel2(config) {
2644
- return buildPiModel(config);
2645
- }
2646
-
2647
- // src/ai/assistant-loader.ts
2648
- import * as fs7 from "fs";
2649
- import * as path9 from "path";
2650
- function loadAssistantConfig(aiDataDir, assistantId) {
2651
- const filePath = path9.join(aiDataDir, "assistants", `${assistantId}.md`);
2652
- if (!fs7.existsSync(filePath)) return null;
2653
- try {
2654
- const content = fs7.readFileSync(filePath, "utf-8");
2655
- return parseAssistantFile(content, filePath);
2656
- } catch {
2657
- return null;
2658
- }
2659
- }
2660
-
2661
- // src/ai/agent.ts
2662
- async function runServerAgent(options) {
2663
- const {
2664
- userMessage,
2665
- conversationId,
2666
- historyLeafMessageId,
2667
- chatType = "group",
2668
- locale = "zh-CN",
2669
- assistantSystemPrompt,
2670
- skillMenu,
2671
- skillDef,
2672
- compressionConfig,
2673
- tools = [],
2674
- aiDataDir,
2675
- convManager: convManager2,
2676
- onEvent,
2677
- abortSignal,
2678
- ownerInfo,
2679
- mentionedMembers,
2680
- dataSnapshot,
2681
- thinkingLevel
2682
- } = options;
2683
- const aiLogger = getServerAiLogger();
2684
- await initTokenizer();
2685
- const llmConfig = getDefaultAssistantConfig(aiDataDir);
2686
- if (!llmConfig) {
2687
- onEvent({ type: "error", error: { name: "ConfigError", message: "LLM service not configured" } });
2688
- onEvent({ type: "done", isFinished: true });
2689
- return;
2690
- }
2691
- const piModel = buildPiModel2(llmConfig);
2692
- const t = createAiTranslate(locale);
2693
- let skillCtx;
2694
- if (skillDef) {
2695
- skillCtx = { skillDef };
2696
- } else if (skillMenu) {
2697
- skillCtx = { skillMenu };
2698
- }
2699
- const systemPrompt = buildSystemPrompt({
2700
- t,
2701
- chatType,
2702
- assistantSystemPrompt,
2703
- ownerInfo,
2704
- locale,
2705
- skillCtx,
2706
- mentionedMembers,
2707
- dataSnapshot
2708
- });
2709
- const handler = new AgentEventHandler({
2710
- onChunk: onEvent,
2711
- context: {},
2712
- systemPrompt
2713
- });
2714
- if (compressionConfig?.enabled && historyLeafMessageId === void 0) {
2715
- const llmAdapter = createCompressionLlmAdapter({
2716
- piModel,
2717
- apiKey: llmConfig.apiKey,
2718
- onCompressing: () => handler.emitStatus("compressing", [])
2719
- });
2720
- const compressionResult = await checkAndCompress(
2721
- conversationId,
2722
- compressionConfig,
2723
- systemPrompt,
2724
- llmAdapter,
2725
- convManager2,
2726
- aiLogger ?? void 0
2727
- );
2728
- if (compressionResult.compressed) {
2729
- onEvent({
2730
- type: "compression_done",
2731
- compressionResult: {
2732
- summaryContent: compressionResult.summaryContent ?? "",
2733
- tokensBefore: compressionResult.tokensBefore ?? 0,
2734
- tokensAfter: compressionResult.tokensAfter ?? 0,
2735
- timestamp: Date.now()
2736
- }
2737
- });
2738
- }
2739
- } else if (compressionConfig?.enabled && historyLeafMessageId !== void 0) {
2740
- aiLogger?.info?.("Compression", "Skipping compression for edited branch request", {
2741
- conversationId,
2742
- historyLeafMessageId
2743
- });
2744
- }
2745
- if (abortSignal?.aborted) {
2746
- handler.emitStatus("aborted", [], { force: true });
2747
- onEvent({ type: "done", isFinished: true, usage: handler.cloneUsage() });
2748
- return;
2749
- }
2750
- let history = [];
2751
- try {
2752
- history = convManager2.getHistoryForAgent(conversationId, void 0, historyLeafMessageId);
2753
- } catch {
2754
- }
2755
- handler.emitStatus("preparing", [], { pendingUserMessage: userMessage, force: true });
2756
- const steerMessage = t("ai.agent.answerWithoutTools");
2757
- let cachedMessages = [];
2758
- try {
2759
- const result = await runAgentCore({
2760
- piModel,
2761
- apiKey: llmConfig.apiKey,
2762
- systemPrompt,
2763
- tools,
2764
- history,
2765
- userMessage,
2766
- maxToolRounds: DEFAULT_MAX_TOOL_ROUNDS,
2767
- abortSignal,
2768
- steerMessage,
2769
- thinkingLevel,
2770
- onConvertToLlm: (filteredMessages) => {
2771
- cachedMessages = filteredMessages;
2772
- },
2773
- onEvent: (coreEvent) => handler.handleCoreEvent(coreEvent, cachedMessages),
2774
- onDebugContext: (messages) => {
2775
- try {
2776
- convManager2.setPendingDebugContext(conversationId, JSON.stringify(messages, null, 2));
2777
- } catch {
2778
- }
2779
- }
2780
- });
2781
- if (result.error) {
2782
- const friendlyMessage = formatAIError(result.error);
2783
- onEvent({ type: "error", error: { name: "AgentError", message: friendlyMessage } });
2784
- }
2785
- handler.emitStatus("completed", cachedMessages, { force: true });
2786
- onEvent({ type: "done", isFinished: true, usage: result.usage });
2787
- } catch (error) {
2788
- const friendlyMessage = formatAIError(error);
2789
- aiLogger?.error("ServerAgent", "Agent execution error", { error: String(error) });
2790
- handler.emitStatus("error", cachedMessages, { force: true });
2791
- onEvent({ type: "error", error: { name: "AgentError", message: friendlyMessage } });
2792
- onEvent({ type: "done", isFinished: true, usage: handler.cloneUsage() });
2793
- }
2794
- }
2795
-
2796
- // src/ai/agent-stream-runner.ts
2797
- function getAiDir(dbManager2) {
2798
- const pathProvider = dbManager2["pathProvider"];
2799
- if (!pathProvider) {
2800
- throw Object.assign(new Error("PathProvider not available"), { statusCode: 500 });
2801
- }
2802
- return pathProvider.getAiDataDir();
2803
- }
2804
- var RAW_SQL_TOOL_NAMES = /* @__PURE__ */ new Set(["execute_sql"]);
2805
- function getAvailableToolDefs(isChartCapability, allowedToolSet) {
2806
- if (isChartCapability) {
2807
- const chartCoreTools = new Set(CHART_CAPABILITY_CORE_TOOLS);
2808
- return AGENT_TOOL_REGISTRY.filter(
2809
- (tool) => chartCoreTools.has(tool.name) || tool.category === "analysis" && allowedToolSet?.has(tool.name) && !RAW_SQL_TOOL_NAMES.has(tool.name)
2810
- );
2811
- }
2812
- return allowedToolSet ? AGENT_TOOL_REGISTRY.filter((tool) => tool.category !== "analysis" || allowedToolSet.has(tool.name)) : AGENT_TOOL_REGISTRY;
2813
- }
2814
- function getAllowedToolSet(isChartCapability, allowedBuiltinTools) {
2815
- if (isChartCapability) {
2816
- return new Set(allowedBuiltinTools);
2817
- }
2818
- return allowedBuiltinTools === void 0 ? null : new Set(allowedBuiltinTools);
2819
- }
2820
- function createCliRunAgentStream(dbManager2, convManager2) {
2821
- return async (params, onEvent, abortSignal) => {
2822
- const {
2823
- userMessage,
2824
- conversationId,
2825
- historyLeafMessageId,
2826
- sessionId,
2827
- chatType,
2828
- locale,
2829
- assistantId,
2830
- skillId,
2831
- enableAutoSkill,
2832
- compressionConfig,
2833
- ownerInfo,
2834
- mentionedMembers,
2835
- thinkingLevel
2836
- } = params;
2837
- const aiDataDir = getAiDir(dbManager2);
2838
- let assistantSystemPrompt;
2839
- let assistantAllowedTools;
2840
- if (assistantId) {
2841
- const assistantConfig = loadAssistantConfig(aiDataDir, assistantId);
2842
- if (assistantConfig?.systemPrompt) {
2843
- assistantSystemPrompt = assistantConfig.systemPrompt;
2844
- }
2845
- assistantAllowedTools = assistantConfig?.allowedBuiltinTools;
2846
- }
2847
- const llmConfig = getDefaultAssistantConfig(aiDataDir);
2848
- const maxToolResultPercent = compressionConfig?.maxToolResultPercent ?? 50;
2849
- const contextWindow = llmConfig ? buildPiModel2(llmConfig).contextWindow ?? 128e3 : 128e3;
2850
- const maxToolResultTokens = Math.floor(contextWindow * (maxToolResultPercent / 100));
2851
- const db = dbManager2.open?.(sessionId);
2852
- const chartRuntime = resolveChartRuntimeForRequest({
2853
- skillId,
2854
- userMessage,
2855
- locale,
2856
- assistantAllowedTools
2857
- });
2858
- const isChartCapability = chartRuntime.isChartCapability;
2859
- const autoSkillAllowedTools = !skillId && enableAutoSkill ? getAllowedBuiltinToolsForChartAutoSkill(assistantAllowedTools) : assistantAllowedTools;
2860
- const allowedToolSet = getAllowedToolSet(
2861
- isChartCapability,
2862
- isChartCapability ? chartRuntime.allowedBuiltinTools : autoSkillAllowedTools
2863
- );
2864
- const availableToolDefs = getAvailableToolDefs(isChartCapability, allowedToolSet);
2865
- const agentTools = db ? adaptToolsForAgent(availableToolDefs, () => ({ db, sessionId, locale }), { maxToolResultTokens }) : [];
2866
- const skillMgr = new SkillManager(aiDataDir);
2867
- skillMgr.init();
2868
- const toolNames = agentTools.map((t) => t.name);
2869
- let resolvedSkillDef;
2870
- let resolvedSkillMenu;
2871
- if (isChartCapability) {
2872
- const def = chartRuntime.skillDef ?? getChartCapabilitySkill(locale ?? "zh-CN");
2873
- resolvedSkillDef = { name: def.name, prompt: def.prompt };
2874
- } else if (skillId) {
2875
- const def = skillMgr.getSkillConfig(skillId);
2876
- if (def) resolvedSkillDef = { name: def.name, prompt: def.prompt };
2877
- } else if (enableAutoSkill) {
2878
- const menu = buildSkillMenuWithBuiltinChart(
2879
- skillMgr.getSkillMenu(chatType ?? "group", toolNames),
2880
- locale,
2881
- toolNames
2882
- );
2883
- if (menu) resolvedSkillMenu = menu;
2884
- }
2885
- if (resolvedSkillMenu) {
2886
- const activateSkillTool = createActivateSkillTool({
2887
- chatType: chatType ?? "group",
2888
- allowedTools: toolNames,
2889
- coreToolNames: new Set(CHART_CAPABILITY_CORE_TOOLS),
2890
- locale,
2891
- getSkillConfig: (id) => getSkillConfigWithBuiltinChart(id, locale, (skillConfigId) => skillMgr.getSkillConfig(skillConfigId))
2892
- });
2893
- agentTools.push(activateSkillTool);
2894
- }
2895
- const resolvedCompression = compressionConfig?.enabled ? {
2896
- enabled: true,
2897
- tokenThresholdPercent: compressionConfig.tokenThresholdPercent ?? 75,
2898
- bufferSizePercent: compressionConfig.bufferSizePercent ?? 20,
2899
- maxToolResultPercent: compressionConfig.maxToolResultPercent
2900
- } : void 0;
2901
- let dataSnapshot;
2902
- if (db) {
2903
- try {
2904
- const overview = getChatOverview(db, 5);
2905
- if (overview) {
2906
- dataSnapshot = {
2907
- name: overview.name,
2908
- platform: overview.platform,
2909
- type: overview.type,
2910
- totalMessages: overview.totalMessages,
2911
- totalMembers: overview.totalMembers,
2912
- firstMessageTs: overview.firstMessageTs,
2913
- lastMessageTs: overview.lastMessageTs,
2914
- capturedAt: Math.floor(Date.now() / 1e3)
2915
- };
2916
- }
2917
- } catch {
2918
- }
2919
- }
2920
- await runServerAgent({
2921
- userMessage,
2922
- conversationId,
2923
- historyLeafMessageId,
2924
- chatType,
2925
- locale,
2926
- assistantSystemPrompt,
2927
- skillMenu: resolvedSkillMenu,
2928
- skillDef: resolvedSkillDef,
2929
- compressionConfig: resolvedCompression,
2930
- tools: agentTools,
2931
- aiDataDir,
2932
- convManager: convManager2,
2933
- onEvent,
2934
- abortSignal,
2935
- ownerInfo,
2936
- mentionedMembers,
2937
- dataSnapshot,
2938
- thinkingLevel
2939
- });
2940
- };
2941
- }
2942
-
2943
2498
  // ../../packages/sync/src/types.ts
2944
2499
  var noop = () => {
2945
2500
  };
2946
2501
  var NOOP_LOGGER = { info: noop, warn: noop, error: noop };
2947
2502
 
2948
2503
  // ../../packages/sync/src/data-source-manager.ts
2949
- import * as fs8 from "fs";
2950
- import * as path10 from "path";
2504
+ import * as fs6 from "fs";
2505
+ import * as path8 from "path";
2951
2506
  import * as crypto from "crypto";
2952
2507
  var CONFIG_FILE = "data-sources.json";
2953
2508
  function generateId(prefix = "ds") {
@@ -2970,22 +2525,22 @@ function isValidDataSourceArray(data) {
2970
2525
  var DataSourceManager = class {
2971
2526
  configDir;
2972
2527
  logger;
2973
- constructor(configDir, logger2) {
2528
+ constructor(configDir, logger) {
2974
2529
  this.configDir = configDir;
2975
- this.logger = logger2 ?? NOOP_LOGGER;
2530
+ this.logger = logger ?? NOOP_LOGGER;
2976
2531
  }
2977
2532
  getConfigPath() {
2978
- return path10.join(this.configDir, CONFIG_FILE);
2533
+ return path8.join(this.configDir, CONFIG_FILE);
2979
2534
  }
2980
2535
  ensureDir() {
2981
- fs8.mkdirSync(this.configDir, { recursive: true });
2536
+ fs6.mkdirSync(this.configDir, { recursive: true });
2982
2537
  }
2983
2538
  // ==================== Load / Save ====================
2984
2539
  loadAll() {
2985
2540
  try {
2986
2541
  const filePath = this.getConfigPath();
2987
- if (fs8.existsSync(filePath)) {
2988
- const raw = fs8.readFileSync(filePath, "utf-8");
2542
+ if (fs6.existsSync(filePath)) {
2543
+ const raw = fs6.readFileSync(filePath, "utf-8");
2989
2544
  const parsed = JSON.parse(raw);
2990
2545
  if (!isValidDataSourceArray(parsed)) {
2991
2546
  this.logger.warn("[DataSource] Incompatible config format detected, returning empty.");
@@ -3004,7 +2559,7 @@ var DataSourceManager = class {
3004
2559
  saveAll(sources) {
3005
2560
  try {
3006
2561
  this.ensureDir();
3007
- fs8.writeFileSync(this.getConfigPath(), JSON.stringify(sources, null, 2), "utf-8");
2562
+ fs6.writeFileSync(this.getConfigPath(), JSON.stringify(sources, null, 2), "utf-8");
3008
2563
  } catch (err) {
3009
2564
  this.logger.error("[DataSource] Failed to save config", err);
3010
2565
  }
@@ -3129,7 +2684,7 @@ function parseRemoteSessionsResponse(body) {
3129
2684
  }
3130
2685
 
3131
2686
  // ../../packages/sync/src/pull-engine.ts
3132
- import * as fs9 from "fs";
2687
+ import * as fs7 from "fs";
3133
2688
  import * as crypto2 from "crypto";
3134
2689
  var MAX_PAGES_PER_PULL = 5e3;
3135
2690
  var PULL_OVERLAP_SECONDS = 60;
@@ -3149,7 +2704,7 @@ function parseSyncFromFile(filePath) {
3149
2704
  try {
3150
2705
  const isJsonl = filePath.endsWith(".jsonl");
3151
2706
  if (isJsonl) {
3152
- const content = fs9.readFileSync(filePath, "utf-8");
2707
+ const content = fs7.readFileSync(filePath, "utf-8");
3153
2708
  const lines = content.trimEnd().split("\n");
3154
2709
  for (let i = lines.length - 1; i >= Math.max(0, lines.length - 5); i--) {
3155
2710
  try {
@@ -3168,7 +2723,7 @@ function parseSyncFromFile(filePath) {
3168
2723
  }
3169
2724
  return null;
3170
2725
  }
3171
- const raw = fs9.readFileSync(filePath, "utf-8");
2726
+ const raw = fs7.readFileSync(filePath, "utf-8");
3172
2727
  const parsed = JSON.parse(raw);
3173
2728
  if (parsed.sync && typeof parsed.sync === "object") {
3174
2729
  const s = parsed.sync;
@@ -3182,7 +2737,7 @@ function parseSyncFromFile(filePath) {
3182
2737
  function fileContainsMessages(filePath) {
3183
2738
  try {
3184
2739
  if (filePath.endsWith(".jsonl")) {
3185
- const content = fs9.readFileSync(filePath, "utf-8");
2740
+ const content = fs7.readFileSync(filePath, "utf-8");
3186
2741
  for (const line of content.split("\n")) {
3187
2742
  const trimmed = line.trim();
3188
2743
  if (!trimmed) continue;
@@ -3195,7 +2750,7 @@ function fileContainsMessages(filePath) {
3195
2750
  }
3196
2751
  return false;
3197
2752
  }
3198
- const raw = fs9.readFileSync(filePath, "utf-8");
2753
+ const raw = fs7.readFileSync(filePath, "utf-8");
3199
2754
  const parsed = JSON.parse(raw);
3200
2755
  return Array.isArray(parsed.messages) && parsed.messages.length > 0;
3201
2756
  } catch {
@@ -3204,7 +2759,7 @@ function fileContainsMessages(filePath) {
3204
2759
  }
3205
2760
  function cleanupTempFile(filePath) {
3206
2761
  try {
3207
- if (fs9.existsSync(filePath)) fs9.unlinkSync(filePath);
2762
+ if (fs7.existsSync(filePath)) fs7.unlinkSync(filePath);
3208
2763
  } catch {
3209
2764
  }
3210
2765
  }
@@ -3264,7 +2819,7 @@ var PullEngine = class {
3264
2819
  limit: ds.pullLimit
3265
2820
  });
3266
2821
  try {
3267
- const stat2 = fs9.statSync(tempFile);
2822
+ const stat2 = fs7.statSync(tempFile);
3268
2823
  this.logger.info(`[Pull] "${sess.name}" page ${pageCount}: fetched ${stat2.size} bytes`);
3269
2824
  const sync0 = parseSyncFromFile(tempFile);
3270
2825
  if (stat2.size < 1024) {
@@ -3282,7 +2837,7 @@ var PullEngine = class {
3282
2837
  since,
3283
2838
  limit: ds.pullLimit
3284
2839
  });
3285
- const retryStat = fs9.statSync(retryFile);
2840
+ const retryStat = fs7.statSync(retryFile);
3286
2841
  this.logger.info(`[Pull] "${sess.name}" retry ${ri + 1}: fetched ${retryStat.size} bytes`);
3287
2842
  const retrySync = parseSyncFromFile(retryFile);
3288
2843
  if (retryStat.size < 1024 && !fileContainsMessages(retryFile) && retrySync?.hasMore === false) {
@@ -3556,13 +3111,13 @@ function reloadTimer(dsId, skipInitialPull = false) {
3556
3111
  }
3557
3112
 
3558
3113
  // src/sync/adapters.ts
3559
- import * as fs10 from "fs";
3114
+ import * as fs8 from "fs";
3560
3115
  import * as os4 from "os";
3561
- import * as path11 from "path";
3116
+ import * as path9 from "path";
3562
3117
  import * as crypto3 from "crypto";
3563
3118
  function getTempFilePath(ext) {
3564
3119
  const id = crypto3.randomBytes(8).toString("hex");
3565
- return path11.join(os4.tmpdir(), `chatlab-pull-${id}${ext}`);
3120
+ return path9.join(os4.tmpdir(), `chatlab-pull-${id}${ext}`);
3566
3121
  }
3567
3122
  var NodeFetcher = class {
3568
3123
  async fetchToTempFile(baseUrl, remoteSessionId, token, params) {
@@ -3579,45 +3134,38 @@ var NodeFetcher = class {
3579
3134
  const isJsonl = contentType.includes("ndjson") || contentType.includes("jsonl");
3580
3135
  const tempFile = getTempFilePath(isJsonl ? ".jsonl" : ".json");
3581
3136
  const buffer = Buffer.from(await response.arrayBuffer());
3582
- fs10.writeFileSync(tempFile, buffer);
3137
+ fs8.writeFileSync(tempFile, buffer);
3583
3138
  return tempFile;
3584
3139
  }
3585
3140
  };
3586
- function resolveNativeBinding2() {
3587
- if (process.versions.electron) return void 0;
3588
- const nativePath = resolveCliPath("native/better_sqlite3.node");
3589
- if (fs10.existsSync(nativePath)) return nativePath;
3590
- return void 0;
3591
- }
3592
3141
  var DirectImporter = class {
3593
3142
  dbManager;
3594
- nativeBinding;
3595
3143
  logger;
3596
- constructor(dbManager2, logger2) {
3144
+ constructor(dbManager2, logger) {
3597
3145
  this.dbManager = dbManager2;
3598
- this.nativeBinding = resolveNativeBinding2();
3599
- this.logger = logger2 ?? NOOP_LOGGER;
3146
+ this.logger = logger ?? NOOP_LOGGER;
3600
3147
  }
3601
3148
  sessionExists(sessionId) {
3602
3149
  const dbPath = this.dbManager.getDbPath(sessionId);
3603
- if (!fs10.existsSync(dbPath)) return false;
3150
+ if (!fs8.existsSync(dbPath)) return false;
3604
3151
  try {
3605
- const db = openBetterSqliteDatabase(dbPath, { readonly: true, nativeBinding: this.nativeBinding });
3152
+ const db = this.dbManager.openRawSessionDatabase(sessionId, { readonly: true });
3606
3153
  const row = db.prepare("SELECT COUNT(*) as cnt FROM sqlite_master WHERE type='table' AND name='message'").get();
3607
3154
  db.close();
3608
3155
  if (row.cnt === 0) {
3609
3156
  this.logger.warn(`[DirectImporter] DB file exists but has no message table: ${sessionId}, removing`);
3610
3157
  try {
3611
- fs10.unlinkSync(dbPath);
3158
+ fs8.unlinkSync(dbPath);
3612
3159
  } catch {
3613
3160
  }
3614
3161
  return false;
3615
3162
  }
3616
3163
  return true;
3617
- } catch {
3164
+ } catch (error) {
3165
+ if (error instanceof DataDirCompatibilityError) throw error;
3618
3166
  this.logger.warn(`[DirectImporter] Cannot validate DB file: ${sessionId}, removing`);
3619
3167
  try {
3620
- fs10.unlinkSync(dbPath);
3168
+ fs8.unlinkSync(dbPath);
3621
3169
  } catch {
3622
3170
  }
3623
3171
  return false;
@@ -3638,8 +3186,7 @@ var DirectImporter = class {
3638
3186
  const data = await parseFile(tempFile);
3639
3187
  this.dbManager.close(sessionId);
3640
3188
  const result = await importData(this.dbManager, data, {
3641
- sessionId,
3642
- nativeBinding: this.nativeBinding
3189
+ sessionId
3643
3190
  });
3644
3191
  if (result.success) {
3645
3192
  this.logger.info(
@@ -3664,8 +3211,7 @@ var DirectImporter = class {
3664
3211
  try {
3665
3212
  const data = await parseFile(tempFile);
3666
3213
  const result = await importData(this.dbManager, data, {
3667
- sessionId: externalId,
3668
- nativeBinding: this.nativeBinding
3214
+ sessionId: externalId
3669
3215
  });
3670
3216
  if (result.success) {
3671
3217
  this.logger.info(
@@ -3737,8 +3283,8 @@ function registerAutomationRoutes(server2, ctx) {
3737
3283
  if (request.query.deleteData === "true" && removed.targetSessionId) {
3738
3284
  dbManager2.close(removed.targetSessionId);
3739
3285
  const dbPath = dbManager2.getDbPath(removed.targetSessionId);
3740
- const fs12 = await import("fs");
3741
- if (fs12.existsSync(dbPath)) fs12.unlinkSync(dbPath);
3286
+ const fs10 = await import("fs");
3287
+ if (fs10.existsSync(dbPath)) fs10.unlinkSync(dbPath);
3742
3288
  }
3743
3289
  return { success: true };
3744
3290
  });
@@ -3813,26 +3359,26 @@ function cleanupSync() {
3813
3359
  // src/http/index.ts
3814
3360
  var server = null;
3815
3361
  var dbManager = null;
3816
- var convManager = null;
3362
+ var aiChatManager = null;
3817
3363
  function createFileConfigStorage(aiDataDir) {
3818
3364
  return {
3819
3365
  readJson(key) {
3820
3366
  try {
3821
- return JSON.parse(fs11.readFileSync(`${aiDataDir}/${key}.json`, "utf-8"));
3367
+ return JSON.parse(fs9.readFileSync(`${aiDataDir}/${key}.json`, "utf-8"));
3822
3368
  } catch {
3823
3369
  return null;
3824
3370
  }
3825
3371
  },
3826
3372
  writeJson(key, data) {
3827
- if (!fs11.existsSync(aiDataDir)) fs11.mkdirSync(aiDataDir, { recursive: true });
3828
- 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");
3829
3375
  }
3830
3376
  };
3831
3377
  }
3832
- function resolveNativeBinding3() {
3378
+ function resolveNativeBinding2() {
3833
3379
  if (process.versions.electron) return void 0;
3834
3380
  const nativePath = resolveCliPath("native/better_sqlite3.node");
3835
- if (fs11.existsSync(nativePath)) return nativePath;
3381
+ if (fs9.existsSync(nativePath)) return nativePath;
3836
3382
  return void 0;
3837
3383
  }
3838
3384
  function ensureToken(config) {
@@ -3864,6 +3410,7 @@ async function startHttpServer(options) {
3864
3410
  const userDataDir = config.data.user_data_dir || void 0;
3865
3411
  const pathProvider = new NodePathProvider(userDataDir);
3866
3412
  pathProvider.ensureAllDirs();
3413
+ const runtime = assertCliDataDirCompatible(pathProvider, "cli");
3867
3414
  if (hasPendingElectronDataWarning() || !verifyCliDataPath(pathProvider.getDatabaseDir())) {
3868
3415
  console.error(
3869
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"
@@ -3879,10 +3426,10 @@ async function startHttpServer(options) {
3879
3426
  }
3880
3427
  });
3881
3428
  await migrationRunner.run();
3882
- const nativeBinding = resolveNativeBinding3();
3883
- dbManager = new DatabaseManager(pathProvider, { nativeBinding });
3429
+ const nativeBinding = resolveNativeBinding2();
3430
+ dbManager = new DatabaseManager(pathProvider, { nativeBinding, runtime });
3884
3431
  const aiDataDir = pathProvider.getAiDataDir();
3885
- convManager = new AIConversationManager(aiDataDir, { nativeBinding });
3432
+ aiChatManager = new AIChatManager(aiDataDir, { nativeBinding });
3886
3433
  const assistantManager = getAssistantManager(aiDataDir);
3887
3434
  const skillManagerCore = getSkillManagerCore(aiDataDir);
3888
3435
  const llmConfigStore = new LLMConfigStore(createFileConfigStorage(aiDataDir), {
@@ -3907,17 +3454,17 @@ async function startHttpServer(options) {
3907
3454
  nativeBinding,
3908
3455
  aiContext: {
3909
3456
  aiDataDir,
3910
- convManager,
3457
+ aiChatManager,
3911
3458
  assistantManager,
3912
3459
  skillManagerCore,
3913
3460
  llmConfigStore,
3914
3461
  customProviderStore: new CustomProviderStore(createFileConfigStorage(aiDataDir)),
3915
3462
  customModelStore: new CustomModelStore(createFileConfigStorage(aiDataDir)),
3916
- runAgentStream: createCliRunAgentStream(dbManager, convManager)
3463
+ runAgentStream: createCliRunAgentStream(dbManager, aiChatManager)
3917
3464
  }
3918
3465
  });
3919
3466
  initSync(server, dbManager, pathProvider, { port, host, token });
3920
- if (options?.webRoot && fs11.existsSync(options.webRoot)) {
3467
+ if (options?.webRoot && fs9.existsSync(options.webRoot)) {
3921
3468
  registerProxyRoutes(server);
3922
3469
  const fastifyStatic = await import("@fastify/static");
3923
3470
  await server.register(fastifyStatic.default, {
@@ -3938,9 +3485,9 @@ async function stopHttpServer() {
3938
3485
  await server.close();
3939
3486
  } finally {
3940
3487
  cleanupSync();
3941
- if (convManager) {
3942
- convManager.close();
3943
- convManager = null;
3488
+ if (aiChatManager) {
3489
+ aiChatManager.close();
3490
+ aiChatManager = null;
3944
3491
  }
3945
3492
  if (dbManager) {
3946
3493
  dbManager.closeAll();
@@ -3958,4 +3505,4 @@ export {
3958
3505
  startHttpServer,
3959
3506
  stopHttpServer
3960
3507
  };
3961
- //# sourceMappingURL=chunk-FSHVDWI2.mjs.map
3508
+ //# sourceMappingURL=chunk-SJIOPSMM.mjs.map