chatlab-cli 0.31.0 → 0.31.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 (98) hide show
  1. package/dist/{chat-command-CHV7RLBH.mjs → chat-command-MOETAGU5.mjs} +8 -8
  2. package/dist/{chunk-DBBL74RK.mjs → chunk-2IXPWPLR.mjs} +164 -82
  3. package/dist/chunk-2IXPWPLR.mjs.map +1 -0
  4. package/dist/{chunk-YPQ72HMX.mjs → chunk-3VMKS7PU.mjs} +44 -5
  5. package/dist/chunk-3VMKS7PU.mjs.map +1 -0
  6. package/dist/{chunk-SNCXU2QL.mjs → chunk-7HBVGVOB.mjs} +2 -2
  7. package/dist/{chunk-UWWFOEGF.mjs → chunk-DQ45LDKZ.mjs} +19 -2
  8. package/dist/chunk-DQ45LDKZ.mjs.map +1 -0
  9. package/dist/{chunk-WQCY45U2.mjs → chunk-E6W2RURS.mjs} +3 -3
  10. package/dist/{chunk-T64GA5HP.mjs → chunk-KCPGEILH.mjs} +388 -185
  11. package/dist/chunk-KCPGEILH.mjs.map +1 -0
  12. package/dist/{chunk-RDCUGC24.mjs → chunk-LJXSUN25.mjs} +2 -2
  13. package/dist/{chunk-EXD2SXWL.mjs → chunk-N5AGDT7I.mjs} +40 -7
  14. package/dist/chunk-N5AGDT7I.mjs.map +1 -0
  15. package/dist/{chunk-JH5RAJT2.mjs → chunk-SZEBCNBB.mjs} +121 -56
  16. package/dist/chunk-SZEBCNBB.mjs.map +1 -0
  17. package/dist/{chunk-RD335EMA.mjs → chunk-VOVLPSG6.mjs} +29 -52
  18. package/dist/chunk-VOVLPSG6.mjs.map +1 -0
  19. package/dist/{chunk-DA5T64RY.mjs → chunk-ZVWUR7ET.mjs} +2 -2
  20. package/dist/cli.mjs +9 -7
  21. package/dist/contacts-worker.mjs +2 -2
  22. package/dist/global-insight-worker.mjs +1 -1
  23. package/dist/{http-3B5ARN7A.mjs → http-M6NHWJZD.mjs} +11 -11
  24. package/dist/{import-2DZGNSEX.mjs → import-SEYHFXS5.mjs} +9 -7
  25. package/dist/index.mjs +12 -12
  26. package/dist/{mcp-44I6FUUQ.mjs → mcp-MIPFYRLV.mjs} +8 -8
  27. package/dist/people-relationships-worker.mjs +2 -2
  28. package/dist/semantic-index-worker.mjs +1 -1
  29. package/dist/{src-R3QX6L3L.mjs → src-7OD6RD5V.mjs} +18 -6
  30. package/dist/{stream-import-VUEL2TTU.mjs → stream-import-AWEHGQJY.mjs} +9 -7
  31. package/dist/{worker-runtime-GJAOIIZW.mjs → worker-runtime-TGYMASIE.mjs} +5 -5
  32. package/dist-web/assets/{ActionToolsPanel.vue_vue_type_script_setup_true_lang-CdJT0t2f.js → ActionToolsPanel.vue_vue_type_script_setup_true_lang-CkDGVRXe.js} +4 -4
  33. package/dist-web/assets/{BufferResource-BPGkshPa.js → BufferResource-CHI62pIA.js} +1 -1
  34. package/dist-web/assets/{CanvasRenderer-DTKkZhq4.js → CanvasRenderer-OZRoiF0j.js} +1 -1
  35. package/dist-web/assets/{Filter-CHXKzS2l.js → Filter-DNb5VErW.js} +1 -1
  36. package/dist-web/assets/{MessageExportModal-h-zl0dx1.js → MessageExportModal-CqP-w7HP.js} +1 -1
  37. package/dist-web/assets/{PageHeader-CK0hTsdx.js → PageHeader-Ck8ULyZH.js} +1 -1
  38. package/dist-web/assets/{RelationshipGalaxyCanvas-Dwdy5flh.js → RelationshipGalaxyCanvas-ioRNObb5.js} +3 -3
  39. package/dist-web/assets/{RelationshipGalaxyThreeCanvas-CtY4TGen.js → RelationshipGalaxyThreeCanvas-L1Y43p1A.js} +1 -1
  40. package/dist-web/assets/{RenderTargetSystem-BE56mKRG.js → RenderTargetSystem-fJ7D7Chv.js} +1 -1
  41. package/dist-web/assets/{TimeSelect.vue_vue_type_script_setup_true_lang-27hMyAUE.js → TimeSelect.vue_vue_type_script_setup_true_lang-7SEaCxDL.js} +1 -1
  42. package/dist-web/assets/{WebGLRenderer-Dm18dxOf.js → WebGLRenderer-BD3ZUtxH.js} +1 -1
  43. package/dist-web/assets/{WebGPURenderer-BF6TF-is.js → WebGPURenderer-DZXYsT6D.js} +1 -1
  44. package/dist-web/assets/{base-CFPyD9Gy.js → base-DTElkJcC.js} +1 -1
  45. package/dist-web/assets/{browserAll-Cn_CfkXl.js → browserAll-ChT6N6a9.js} +1 -1
  46. package/dist-web/assets/{dateFormat-BcqNKTQ1.js → dateFormat-D9WibwOu.js} +1 -1
  47. package/dist-web/assets/{electron-B6xOabTq.js → electron-CIzyGxH_.js} +1 -1
  48. package/dist-web/assets/{fetch-C_EfVFJi.js → fetch-Avtnh8cJ.js} +1 -1
  49. package/dist-web/assets/{fetch-DL_u25Ui.js → fetch-BFnrBahy.js} +1 -1
  50. package/dist-web/assets/fetch-C9rx2isC.js +31 -0
  51. package/dist-web/assets/{fetch-BPkgnY0R.js → fetch-Ccq_0ecb.js} +1 -1
  52. package/dist-web/assets/{fetch-DMLq3xPG.js → fetch-CuiQUcO_.js} +1 -1
  53. package/dist-web/assets/{fetch-BRXmDI_2.js → fetch-CyKILLnB.js} +1 -1
  54. package/dist-web/assets/fetch-Dd6t3p1r.js +6 -0
  55. package/dist-web/assets/{fetch-DylpNKCR.js → fetch-DnGx-1_t.js} +1 -1
  56. package/dist-web/assets/{fetch-CEhUu1Yu.js → fetch-qC7om4QG.js} +1 -1
  57. package/dist-web/assets/{fetch-etgwVKIw.js → fetch-wSSfDBdV.js} +1 -1
  58. package/dist-web/assets/index-BH9jI5kV.js +173 -0
  59. package/dist-web/assets/index-BWtNqcYK.js +22 -0
  60. package/dist-web/assets/{index-FoTy2Cce.js → index-Bkq7-GBp.js} +1 -1
  61. package/dist-web/assets/index-Bqr-LkS1.css +1 -0
  62. package/dist-web/assets/{index-aMIgqj43.js → index-C6qtsaP7.js} +1 -1
  63. package/dist-web/assets/{index-zZVsV5HB.js → index-ChFGuu70.js} +1 -1
  64. package/dist-web/assets/{index-C3TnydSt.js → index-CiS20iAR.js} +1 -1
  65. package/dist-web/assets/{index-BS6loLHW.js → index-CqD6u57u.js} +1 -1
  66. package/dist-web/assets/{index-CAWO10k1.js → index-CzDG8LVr.js} +2 -2
  67. package/dist-web/assets/{index-BrTlAl8b.js → index-D0Euk-vQ.js} +1 -1
  68. package/dist-web/assets/{index-B5S9FnfP.js → index-D26BWhHz.js} +1 -1
  69. package/dist-web/assets/{index-0x1QPzKZ.js → index-DXHYzIIj.js} +1 -1
  70. package/dist-web/assets/{index-Chm17wNe.js → index-Dq8u7gMb.js} +2 -2
  71. package/dist-web/assets/{index-Em6upenM.js → index-u_UH6rDY.js} +3 -3
  72. package/dist-web/assets/{web-BUZ-dZy0.js → web-BDBdpdK7.js} +1 -1
  73. package/dist-web/assets/{webworkerAll-BKGP--A4.js → webworkerAll-C3dAOQj4.js} +1 -1
  74. package/dist-web/index.html +2 -2
  75. package/package.json +1 -1
  76. package/dist/chunk-DBBL74RK.mjs.map +0 -1
  77. package/dist/chunk-EXD2SXWL.mjs.map +0 -1
  78. package/dist/chunk-JH5RAJT2.mjs.map +0 -1
  79. package/dist/chunk-RD335EMA.mjs.map +0 -1
  80. package/dist/chunk-T64GA5HP.mjs.map +0 -1
  81. package/dist/chunk-UWWFOEGF.mjs.map +0 -1
  82. package/dist/chunk-YPQ72HMX.mjs.map +0 -1
  83. package/dist-web/assets/fetch-BUm1isWe.js +0 -5
  84. package/dist-web/assets/fetch-CBOJwwJp.js +0 -17
  85. package/dist-web/assets/index-DAr_2DlV.js +0 -173
  86. package/dist-web/assets/index-YADL4XIp.js +0 -22
  87. package/dist-web/assets/index-_6lck7Bv.css +0 -1
  88. /package/dist/{chat-command-CHV7RLBH.mjs.map → chat-command-MOETAGU5.mjs.map} +0 -0
  89. /package/dist/{chunk-SNCXU2QL.mjs.map → chunk-7HBVGVOB.mjs.map} +0 -0
  90. /package/dist/{chunk-WQCY45U2.mjs.map → chunk-E6W2RURS.mjs.map} +0 -0
  91. /package/dist/{chunk-RDCUGC24.mjs.map → chunk-LJXSUN25.mjs.map} +0 -0
  92. /package/dist/{chunk-DA5T64RY.mjs.map → chunk-ZVWUR7ET.mjs.map} +0 -0
  93. /package/dist/{http-3B5ARN7A.mjs.map → http-M6NHWJZD.mjs.map} +0 -0
  94. /package/dist/{import-2DZGNSEX.mjs.map → import-SEYHFXS5.mjs.map} +0 -0
  95. /package/dist/{mcp-44I6FUUQ.mjs.map → mcp-MIPFYRLV.mjs.map} +0 -0
  96. /package/dist/{src-R3QX6L3L.mjs.map → src-7OD6RD5V.mjs.map} +0 -0
  97. /package/dist/{stream-import-VUEL2TTU.mjs.map → stream-import-AWEHGQJY.mjs.map} +0 -0
  98. /package/dist/{worker-runtime-GJAOIIZW.mjs.map → worker-runtime-TGYMASIE.mjs.map} +0 -0
@@ -21,7 +21,7 @@ import {
21
21
  resolveOwnerMember,
22
22
  setCache,
23
23
  shouldScopeContactToSession
24
- } from "./chunk-UWWFOEGF.mjs";
24
+ } from "./chunk-DQ45LDKZ.mjs";
25
25
 
26
26
  // ../../packages/node-runtime/src/services/people/relationships/facts-cache.ts
27
27
  var PEOPLE_RELATIONSHIPS_FACTS_FORMAT_VERSION = 3;
@@ -1326,4 +1326,4 @@ export {
1326
1326
  compareNodes,
1327
1327
  compareEdges
1328
1328
  };
1329
- //# sourceMappingURL=chunk-RDCUGC24.mjs.map
1329
+ //# sourceMappingURL=chunk-LJXSUN25.mjs.map
@@ -7,16 +7,17 @@ const __dirname = __pathDirname(__filename);
7
7
  import {
8
8
  IMPORT_IN_PROGRESS_ERROR_KEY,
9
9
  ImportInProgressError,
10
+ analyzeAutoImportFile,
10
11
  analyzeIncrementalImport,
11
12
  analyzeNewImport,
12
13
  autoImportFile,
13
14
  incrementalImport,
14
15
  streamingImport,
15
16
  withDataDirImportLock
16
- } from "./chunk-T64GA5HP.mjs";
17
+ } from "./chunk-KCPGEILH.mjs";
17
18
  import {
18
19
  DataDirCompatibilityError
19
- } from "./chunk-UWWFOEGF.mjs";
20
+ } from "./chunk-DQ45LDKZ.mjs";
20
21
 
21
22
  // src/import/stream-import.ts
22
23
  import * as crypto from "crypto";
@@ -156,6 +157,36 @@ async function autoImport(dbManager, filePath, options) {
156
157
  throw error;
157
158
  }
158
159
  }
160
+ async function analyzeAutoImport(dbManager, filePath, options) {
161
+ const { formatId, chatIndex, onProgress, sessionId } = options ?? {};
162
+ const formatOptions = {};
163
+ if (formatId) formatOptions.formatId = formatId;
164
+ if (chatIndex !== void 0) formatOptions.chatIndex = chatIndex;
165
+ const progressAdapter = createProgressAdapter(onProgress);
166
+ let readonlySessionIds;
167
+ const listSessionIdsReadonly = () => readonlySessionIds ??= dbManager.listSessionIdsReadonly();
168
+ return analyzeAutoImportFile(
169
+ filePath,
170
+ {
171
+ listSessionIds: listSessionIdsReadonly,
172
+ openReadonly: (candidateSessionId) => dbManager.openRawSessionDatabase(candidateSessionId, { readonly: true }),
173
+ onProgress: progressAdapter,
174
+ sessionExists: (candidateSessionId) => listSessionIdsReadonly().includes(candidateSessionId),
175
+ analyzeCreateSession: (sourcePath, sourceFormatOptions) => analyzeNewImport(sourcePath, progressAdapter, {
176
+ formatId: typeof sourceFormatOptions?.formatId === "string" ? sourceFormatOptions.formatId : void 0,
177
+ chatIndex: typeof sourceFormatOptions?.chatIndex === "number" ? sourceFormatOptions.chatIndex : void 0
178
+ }),
179
+ analyzeAppendSession: (targetSessionId, sourcePath, sourceFormatOptions) => analyzeIncrementalImport(targetSessionId, sourcePath, buildIncrementalDeps(dbManager, progressAdapter), {
180
+ formatId: typeof sourceFormatOptions?.formatId === "string" ? sourceFormatOptions.formatId : void 0,
181
+ chatIndex: typeof sourceFormatOptions?.chatIndex === "number" ? sourceFormatOptions.chatIndex : void 0
182
+ })
183
+ },
184
+ {
185
+ explicitSessionId: sessionId,
186
+ formatOptions
187
+ }
188
+ );
189
+ }
159
190
  function buildIncrementalDeps(dbManager, onProgress, onCompatibilityError) {
160
191
  return {
161
192
  openDatabase(sessionId, readonly) {
@@ -208,28 +239,30 @@ async function incrementalImport2(dbManager, sessionId, filePath, options) {
208
239
  throw error;
209
240
  }
210
241
  }
211
- async function analyzeIncrementalImport2(dbManager, sessionId, filePath, onProgress) {
242
+ async function analyzeIncrementalImport2(dbManager, sessionId, filePath, onProgress, options) {
212
243
  let compatibilityError = null;
213
244
  const result = await analyzeIncrementalImport(
214
245
  sessionId,
215
246
  filePath,
216
247
  buildIncrementalDeps(dbManager, onProgress, (error) => {
217
248
  compatibilityError = error;
218
- })
249
+ }),
250
+ options
219
251
  );
220
252
  if (compatibilityError) throw compatibilityError;
221
253
  return result;
222
254
  }
223
- async function analyzeNewImport2(filePath, onProgress) {
255
+ async function analyzeNewImport2(filePath, onProgress, options) {
224
256
  return analyzeNewImport(filePath, onProgress ?? (() => {
225
- }));
257
+ }), options);
226
258
  }
227
259
 
228
260
  export {
229
261
  streamImport,
230
262
  autoImport,
263
+ analyzeAutoImport,
231
264
  incrementalImport2 as incrementalImport,
232
265
  analyzeIncrementalImport2 as analyzeIncrementalImport,
233
266
  analyzeNewImport2 as analyzeNewImport
234
267
  };
235
- //# sourceMappingURL=chunk-EXD2SXWL.mjs.map
268
+ //# sourceMappingURL=chunk-N5AGDT7I.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/import/stream-import.ts"],"sourcesContent":["/**\n * Server/CLI streaming import — adapter for @openchatlab/node-runtime StreamingImporter.\n *\n * Replaces the old buffered-in-memory approach with the same high-performance\n * streaming pipeline used by Electron (batched transactions, deferred indexes,\n * nickname history, FTS, format fallback).\n */\n\nimport type { DatabaseManager } from '@openchatlab/node-runtime'\nimport {\n DataDirCompatibilityError,\n IMPORT_IN_PROGRESS_ERROR_KEY,\n ImportInProgressError,\n analyzeAutoImportFile as sharedAnalyzeAutoImportFile,\n autoImportFile as sharedAutoImportFile,\n streamingImport,\n analyzeNewImport as sharedAnalyzeNewImport,\n analyzeIncrementalImport as sharedAnalyzeIncremental,\n incrementalImport as sharedIncrementalImport,\n withDataDirImportLock,\n} from '@openchatlab/node-runtime'\nimport type {\n StreamImportResult,\n StreamImportDeps,\n ImportProgressCallback,\n IncrementalImportResult,\n IncrementalAnalyzeResult,\n IncrementalImportDeps,\n ImportOptions,\n AnalyzeNewImportResult,\n AutoImportAnalysisResult,\n AutoImportResult,\n} from '@openchatlab/node-runtime'\nimport {\n detectFormat as parserDetectFormat,\n detectAllFormats,\n getFormatFeatureById,\n getSupportedFormats as parserGetSupportedFormats,\n scanMultiChatFile as parserScanMultiChatFile,\n findEntryFileInDirectory,\n type FormatFeature,\n type MultiChatInfo,\n type ParseProgress,\n} from '@openchatlab/parser'\nimport * as crypto from 'crypto'\n\n// ==================== Legacy progress interface (for SSE routes) ====================\n\nexport interface StreamImportProgress {\n stage: 'detecting' | 'parsing' | 'saving' | 'indexing' | 'done' | 'error'\n progress: number\n message: string\n bytesRead?: number\n totalBytes?: number\n messagesProcessed?: number\n}\n\nexport interface StreamImportOptions {\n formatId?: string\n chatIndex?: number\n nativeBinding?: string\n onProgress?: (progress: StreamImportProgress) => void\n /** Fix the target session ID instead of auto-generating one. Used by sync/pull adapters. */\n sessionId?: string\n}\n\nfunction generateSessionId(): string {\n const ts = Date.now()\n const rand = crypto.randomBytes(4).toString('hex')\n return `chat_${ts}_${rand}`\n}\n\nfunction buildStreamImportDeps(dbManager: DatabaseManager, onProgress?: ImportProgressCallback): StreamImportDeps {\n return {\n openDatabase(sessionId: string) {\n return dbManager.openRawSessionDatabase(sessionId, { create: true, initializeChatTables: true })\n },\n deleteDatabase(sessionId: string) {\n dbManager.deleteSessionDatabaseFiles(sessionId)\n },\n onProgress: onProgress ?? (() => {}),\n generateSessionId,\n }\n}\n\nfunction createProgressAdapter(onProgress?: (progress: StreamImportProgress) => void): ImportProgressCallback {\n if (!onProgress) return () => {}\n return (progress) => {\n let stage: StreamImportProgress['stage'] = 'parsing'\n let pct = 0\n switch (progress.stage) {\n case 'detecting':\n stage = 'detecting'\n pct = 5\n break\n case 'parsing':\n stage = 'parsing'\n pct = Math.min(Math.round(progress.percentage * 0.7), 70)\n break\n case 'saving':\n stage = 'saving'\n pct = 80\n break\n case 'indexing':\n stage = 'indexing'\n pct = 90\n break\n case 'done':\n stage = 'done'\n pct = 100\n break\n case 'error':\n stage = 'error'\n pct = 0\n break\n }\n onProgress({\n stage,\n progress: pct,\n message: progress.message || '',\n bytesRead: progress.bytesRead,\n totalBytes: progress.totalBytes,\n messagesProcessed: progress.messagesProcessed,\n })\n }\n}\n\nfunction deleteSessionDatabase(dbManager: DatabaseManager, sessionId: string): void {\n dbManager.deleteSessionDatabaseFiles(sessionId)\n}\n\n/**\n * High-performance streaming import: parse a file and write to DB\n * with batched transactions, deferred indexes, and FTS.\n */\nasync function streamImportUnlocked(\n dbManager: DatabaseManager,\n filePath: string,\n options?: StreamImportOptions\n): Promise<StreamImportResult> {\n const { formatId, chatIndex, onProgress, sessionId } = options || {}\n\n const formatOptions: Record<string, unknown> = {}\n if (formatId) formatOptions.formatId = formatId\n if (chatIndex !== undefined) formatOptions.chatIndex = chatIndex\n\n const progressAdapter = createProgressAdapter(onProgress)\n\n const deps = buildStreamImportDeps(dbManager, progressAdapter)\n const result = await streamingImport(filePath, deps, formatOptions, sessionId)\n if (!result.success || !result.sessionId) return result\n\n try {\n dbManager.raiseCurrentChatDbCompatibilityGate()\n } catch (error) {\n deleteSessionDatabase(dbManager, result.sessionId)\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n diagnostics: result.diagnostics,\n }\n }\n\n return result\n}\n\nexport async function streamImport(\n dbManager: DatabaseManager,\n filePath: string,\n options?: StreamImportOptions\n): Promise<StreamImportResult> {\n try {\n return await withDataDirImportLock(dbManager.getUserDataDir(), () =>\n streamImportUnlocked(dbManager, filePath, options)\n )\n } catch (error) {\n if (error instanceof ImportInProgressError) {\n return { success: false, error: IMPORT_IN_PROGRESS_ERROR_KEY }\n }\n throw error\n }\n}\n\nexport async function autoImport(\n dbManager: DatabaseManager,\n filePath: string,\n options?: StreamImportOptions\n): Promise<AutoImportResult> {\n const { formatId, chatIndex, onProgress, sessionId } = options ?? {}\n const formatOptions: Record<string, unknown> = {}\n if (formatId) formatOptions.formatId = formatId\n if (chatIndex !== undefined) formatOptions.chatIndex = chatIndex\n const progressAdapter = createProgressAdapter(onProgress)\n\n try {\n return await withDataDirImportLock(dbManager.getUserDataDir(), () =>\n sharedAutoImportFile(\n filePath,\n {\n listSessionIds: () => dbManager.listSessionIds(),\n openReadonly: (candidateSessionId) =>\n dbManager.openRawSessionDatabase(candidateSessionId, { readonly: true }),\n onProgress: progressAdapter,\n sessionExists: (candidateSessionId) => dbManager.listSessionIds().includes(candidateSessionId),\n createSession: (sourcePath, sourceFormatOptions, explicitSessionId) =>\n streamImportUnlocked(dbManager, sourcePath, {\n ...options,\n ...sourceFormatOptions,\n sessionId: explicitSessionId,\n }),\n appendSession: (targetSessionId, sourcePath, sourceFormatOptions) =>\n incrementalImportUnlocked(dbManager, targetSessionId, sourcePath, {\n ...sourceFormatOptions,\n onProgress: progressAdapter,\n }),\n },\n {\n explicitSessionId: sessionId,\n formatOptions,\n }\n )\n )\n } catch (error) {\n if (error instanceof ImportInProgressError) {\n return { success: false, error: IMPORT_IN_PROGRESS_ERROR_KEY }\n }\n throw error\n }\n}\n\nexport async function analyzeAutoImport(\n dbManager: DatabaseManager,\n filePath: string,\n options?: StreamImportOptions\n): Promise<AutoImportAnalysisResult> {\n const { formatId, chatIndex, onProgress, sessionId } = options ?? {}\n const formatOptions: Record<string, unknown> = {}\n if (formatId) formatOptions.formatId = formatId\n if (chatIndex !== undefined) formatOptions.chatIndex = chatIndex\n const progressAdapter = createProgressAdapter(onProgress)\n let readonlySessionIds: string[] | undefined\n const listSessionIdsReadonly = (): string[] => (readonlySessionIds ??= dbManager.listSessionIdsReadonly())\n\n return sharedAnalyzeAutoImportFile(\n filePath,\n {\n listSessionIds: listSessionIdsReadonly,\n openReadonly: (candidateSessionId) => dbManager.openRawSessionDatabase(candidateSessionId, { readonly: true }),\n onProgress: progressAdapter,\n sessionExists: (candidateSessionId) => listSessionIdsReadonly().includes(candidateSessionId),\n analyzeCreateSession: (sourcePath, sourceFormatOptions) =>\n sharedAnalyzeNewImport(sourcePath, progressAdapter, {\n formatId: typeof sourceFormatOptions?.formatId === 'string' ? sourceFormatOptions.formatId : undefined,\n chatIndex: typeof sourceFormatOptions?.chatIndex === 'number' ? sourceFormatOptions.chatIndex : undefined,\n }),\n analyzeAppendSession: (targetSessionId, sourcePath, sourceFormatOptions) =>\n sharedAnalyzeIncremental(targetSessionId, sourcePath, buildIncrementalDeps(dbManager, progressAdapter), {\n formatId: typeof sourceFormatOptions?.formatId === 'string' ? sourceFormatOptions.formatId : undefined,\n chatIndex: typeof sourceFormatOptions?.chatIndex === 'number' ? sourceFormatOptions.chatIndex : undefined,\n }),\n },\n {\n explicitSessionId: sessionId,\n formatOptions,\n }\n )\n}\n\n// ==================== Incremental import ====================\n\nfunction buildIncrementalDeps(\n dbManager: DatabaseManager,\n onProgress?: ImportProgressCallback,\n onCompatibilityError?: (error: DataDirCompatibilityError) => void\n): IncrementalImportDeps {\n return {\n openDatabase(sessionId: string, readonly?: boolean) {\n try {\n return dbManager.openRawSessionDatabase(sessionId, { readonly: readonly ?? false })\n } catch (error) {\n if (error instanceof DataDirCompatibilityError) onCompatibilityError?.(error)\n throw error\n }\n },\n onProgress: onProgress ?? (() => {}),\n }\n}\n\nasync function incrementalImportUnlocked(\n dbManager: DatabaseManager,\n sessionId: string,\n filePath: string,\n options?: ImportOptions & { onProgress?: ImportProgressCallback }\n): Promise<IncrementalImportResult> {\n const { onProgress, ...importOpts } = options || {}\n let compatibilityError: DataDirCompatibilityError | null = null\n const result = await sharedIncrementalImport(\n sessionId,\n filePath,\n buildIncrementalDeps(dbManager, onProgress, (error) => {\n compatibilityError = error\n }),\n importOpts\n )\n if (compatibilityError) throw compatibilityError\n if (!result.success) return result\n\n try {\n dbManager.raiseCurrentChatDbCompatibilityGate()\n } catch (error) {\n return {\n ...result,\n success: false,\n newMessageCount: 0,\n error: error instanceof Error ? error.message : String(error),\n }\n }\n\n return result\n}\n\nexport async function incrementalImport(\n dbManager: DatabaseManager,\n sessionId: string,\n filePath: string,\n options?: ImportOptions & { onProgress?: ImportProgressCallback }\n): Promise<IncrementalImportResult> {\n try {\n return await withDataDirImportLock(dbManager.getUserDataDir(), () =>\n incrementalImportUnlocked(dbManager, sessionId, filePath, options)\n )\n } catch (error) {\n if (error instanceof ImportInProgressError) {\n return { success: false, newMessageCount: 0, error: IMPORT_IN_PROGRESS_ERROR_KEY }\n }\n throw error\n }\n}\n\nexport async function analyzeIncrementalImport(\n dbManager: DatabaseManager,\n sessionId: string,\n filePath: string,\n onProgress?: ImportProgressCallback,\n options?: ImportOptions\n): Promise<IncrementalAnalyzeResult> {\n let compatibilityError: DataDirCompatibilityError | null = null\n const result = await sharedAnalyzeIncremental(\n sessionId,\n filePath,\n buildIncrementalDeps(dbManager, onProgress, (error) => {\n compatibilityError = error\n }),\n options\n )\n if (compatibilityError) throw compatibilityError\n return result\n}\n\nexport async function analyzeNewImport(\n filePath: string,\n onProgress?: ImportProgressCallback,\n options?: Pick<ImportOptions, 'formatId' | 'chatIndex'>\n): Promise<AnalyzeNewImportResult> {\n return sharedAnalyzeNewImport(filePath, onProgress ?? (() => {}), options)\n}\n\n// ==================== Re-exports from parser ====================\n\nexport {\n parserDetectFormat as detectFormat,\n detectAllFormats,\n getFormatFeatureById,\n parserGetSupportedFormats as getSupportedFormats,\n parserScanMultiChatFile as scanMultiChatFile,\n findEntryFileInDirectory,\n}\nexport type { FormatFeature, MultiChatInfo, ParseProgress }\nexport type {\n StreamImportResult,\n IncrementalImportResult,\n IncrementalAnalyzeResult,\n AnalyzeNewImportResult,\n AutoImportAnalysisResult,\n ImportOptions,\n AutoImportResult,\n}\n"],"mappings":"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","names":["incrementalImport","analyzeIncrementalImport","analyzeNewImport"]}
@@ -4,26 +4,26 @@ import { fileURLToPath as __fileURLToPath } from 'url';
4
4
  const require = __createRequire(import.meta.url);
5
5
  const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __pathDirname(__filename);
7
- import {
8
- analyzeIncrementalImport,
9
- analyzeNewImport,
10
- autoImport,
11
- incrementalImport,
12
- streamImport
13
- } from "./chunk-EXD2SXWL.mjs";
14
7
  import {
15
8
  closeServerAiLogger,
16
9
  createCliRunAgentStream,
17
10
  getServerAiLogger,
18
11
  initServerAiLogger
19
- } from "./chunk-RD335EMA.mjs";
12
+ } from "./chunk-VOVLPSG6.mjs";
20
13
  import {
21
14
  AGENT_TOOL_REGISTRY,
22
15
  CoreDataProvider
23
- } from "./chunk-YPQ72HMX.mjs";
16
+ } from "./chunk-3VMKS7PU.mjs";
17
+ import {
18
+ analyzeIncrementalImport,
19
+ analyzeNewImport,
20
+ autoImport,
21
+ incrementalImport,
22
+ streamImport
23
+ } from "./chunk-N5AGDT7I.mjs";
24
24
  import {
25
25
  assertCliDataDirCompatible
26
- } from "./chunk-DA5T64RY.mjs";
26
+ } from "./chunk-ZVWUR7ET.mjs";
27
27
  import {
28
28
  getVersion
29
29
  } from "./chunk-5ADKYYNA.mjs";
@@ -41,7 +41,7 @@ import {
41
41
  getPendingNodeDataDirMigration,
42
42
  hasPendingElectronDataWarning,
43
43
  serializeChatLabToJsonl
44
- } from "./chunk-WQCY45U2.mjs";
44
+ } from "./chunk-E6W2RURS.mjs";
45
45
  import {
46
46
  AIChatManager,
47
47
  ArchiveImportError,
@@ -50,6 +50,7 @@ import {
50
50
  CustomModelStore,
51
51
  CustomProviderStore,
52
52
  IMPORT_IN_PROGRESS_ERROR_KEY,
53
+ ImportIdempotencyCache,
53
54
  ImportInProgressError,
54
55
  LLMConfigStore,
55
56
  MergeSessionCache,
@@ -75,6 +76,7 @@ import {
75
76
  getDefaultRulesForLocale,
76
77
  getDictList,
77
78
  getSupportedFormats,
79
+ hashImportBody,
78
80
  isDictDownloaded,
79
81
  isSemanticIndexConfigured,
80
82
  logNativeParserStatus,
@@ -92,7 +94,7 @@ import {
92
94
  streamParseFileInfo,
93
95
  summary_service_exports,
94
96
  validateApiKey
95
- } from "./chunk-T64GA5HP.mjs";
97
+ } from "./chunk-KCPGEILH.mjs";
96
98
  import {
97
99
  resolveCliPath
98
100
  } from "./chunk-FJ35V3TE.mjs";
@@ -158,7 +160,7 @@ import {
158
160
  verifyCliDataPath,
159
161
  writeAuthProfile,
160
162
  writeConfigField
161
- } from "./chunk-UWWFOEGF.mjs";
163
+ } from "./chunk-DQ45LDKZ.mjs";
162
164
 
163
165
  // src/http/index.ts
164
166
  import * as fs12 from "fs";
@@ -178,6 +180,8 @@ var HTTP_STATUS = {
178
180
  ["EXPORT_TOO_LARGE" /* EXPORT_TOO_LARGE */]: 400,
179
181
  ["BODY_TOO_LARGE" /* BODY_TOO_LARGE */]: 413,
180
182
  ["IMPORT_IN_PROGRESS" /* IMPORT_IN_PROGRESS */]: 409,
183
+ ["IDEMPOTENCY_CONFLICT" /* IDEMPOTENCY_CONFLICT */]: 409,
184
+ ["IDEMPOTENCY_PENDING" /* IDEMPOTENCY_PENDING */]: 409,
181
185
  ["IMPORT_FAILED" /* IMPORT_FAILED */]: 500,
182
186
  ["DATA_DIR_INCOMPATIBLE" /* DATA_DIR_INCOMPATIBLE */]: 409,
183
187
  ["SERVER_ERROR" /* SERVER_ERROR */]: 500
@@ -216,6 +220,15 @@ function serverError(message = "Internal server error") {
216
220
  function importInProgress() {
217
221
  return new ApiError("IMPORT_IN_PROGRESS" /* IMPORT_IN_PROGRESS */, "Another import is already in progress");
218
222
  }
223
+ function idempotencyConflict() {
224
+ return new ApiError("IDEMPOTENCY_CONFLICT" /* IDEMPOTENCY_CONFLICT */, "Same Idempotency-Key with different request body hash");
225
+ }
226
+ function idempotencyPending() {
227
+ return new ApiError(
228
+ "IDEMPOTENCY_PENDING" /* IDEMPOTENCY_PENDING */,
229
+ "A request with this Idempotency-Key is still in progress. Please retry later."
230
+ );
231
+ }
219
232
  function importFailed(message) {
220
233
  return new ApiError("IMPORT_FAILED" /* IMPORT_FAILED */, message);
221
234
  }
@@ -493,6 +506,7 @@ function registerRestSessionRoutes(server2, ctx) {
493
506
 
494
507
  // ../../packages/http-routes/src/routes/imports.ts
495
508
  function registerImportRoutes(server2, ctx) {
509
+ const idempotencyCache = new ImportIdempotencyCache();
496
510
  server2.post(
497
511
  "/api/v1/imports/:sessionId",
498
512
  async (request, reply) => {
@@ -506,20 +520,42 @@ function registerImportRoutes(server2, ctx) {
506
520
  const err = invalidPayload("X-Dry-Run is not yet supported");
507
521
  return reply.code(err.statusCode).send(errorResponse(err));
508
522
  }
509
- const outcome = await pushImport(ctx.dbManager, sessionId, request.body ?? {});
510
- if (!outcome.ok) {
511
- if (outcome.reason === "import_in_progress") {
512
- const err2 = importInProgress();
513
- return reply.code(err2.statusCode).send(errorResponse(err2));
523
+ const idempotencyKey = request.headers["idempotency-key"];
524
+ const cacheKey = typeof idempotencyKey === "string" && idempotencyKey ? `${idempotencyKey}:${sessionId}` : null;
525
+ if (cacheKey) {
526
+ const start = idempotencyCache.start(cacheKey, hashImportBody(request.body));
527
+ if (start.status === "conflict") {
528
+ const err = idempotencyConflict();
529
+ return reply.code(err.statusCode).send(errorResponse(err));
514
530
  }
515
- if (outcome.reason === "invalid_payload") {
516
- const err2 = invalidPayload(outcome.message);
517
- return reply.code(err2.statusCode).send(errorResponse(err2));
531
+ if (start.status === "pending") {
532
+ const err = idempotencyPending();
533
+ return reply.code(err.statusCode).send(errorResponse(err));
518
534
  }
519
- const err = importFailed(outcome.message);
520
- return reply.code(err.statusCode).send(errorResponse(err));
535
+ if (start.status === "success") return start.response;
536
+ }
537
+ try {
538
+ const outcome = await pushImport(ctx.dbManager, sessionId, request.body ?? {});
539
+ if (!outcome.ok) {
540
+ if (cacheKey) idempotencyCache.fail(cacheKey);
541
+ if (outcome.reason === "import_in_progress") {
542
+ const err2 = importInProgress();
543
+ return reply.code(err2.statusCode).send(errorResponse(err2));
544
+ }
545
+ if (outcome.reason === "invalid_payload") {
546
+ const err2 = invalidPayload(outcome.message);
547
+ return reply.code(err2.statusCode).send(errorResponse(err2));
548
+ }
549
+ const err = importFailed(outcome.message);
550
+ return reply.code(err.statusCode).send(errorResponse(err));
551
+ }
552
+ const response = successResponse(outcome.result);
553
+ if (cacheKey) idempotencyCache.success(cacheKey, response);
554
+ return response;
555
+ } catch (error) {
556
+ if (cacheKey) idempotencyCache.fail(cacheKey);
557
+ throw error;
521
558
  }
522
- return successResponse(outcome.result);
523
559
  }
524
560
  );
525
561
  }
@@ -1612,8 +1648,55 @@ data: ${JSON.stringify(data)}
1612
1648
  });
1613
1649
  }
1614
1650
 
1615
- // ../../packages/http-routes/src/routes/web/ai-tools.ts
1651
+ // ../../packages/http-routes/src/ai/tool-executor.ts
1616
1652
  var MAX_RESULT_CHARS = 5e5;
1653
+ async function executeRegistryTool(params, deps) {
1654
+ const { toolName, params: toolParams, abortSignal } = params;
1655
+ const entry = AGENT_TOOL_REGISTRY.find((tool) => tool.name === toolName);
1656
+ if (!entry) {
1657
+ return { success: false, error: `Tool not found: ${toolName}` };
1658
+ }
1659
+ try {
1660
+ if (abortSignal.aborted) return { success: false, error: "cancelled" };
1661
+ const execCtx = {
1662
+ sessionId: params.sessionId,
1663
+ abortSignal,
1664
+ db: deps.db,
1665
+ dataProvider: deps.dataProvider,
1666
+ semanticIndexService: deps.semanticIndexService,
1667
+ segmentText: deps.segmentText,
1668
+ translateTemplate: deps.translateTemplate
1669
+ };
1670
+ const startTime = Date.now();
1671
+ const result = await entry.handler(toolParams, execCtx);
1672
+ const elapsed = Date.now() - startTime;
1673
+ if (abortSignal.aborted) return { success: false, error: "cancelled" };
1674
+ let details = result.data ?? void 0;
1675
+ let truncated = false;
1676
+ if (details) {
1677
+ stripAvatarFields(details);
1678
+ const raw = JSON.stringify(details);
1679
+ if (raw.length > MAX_RESULT_CHARS) {
1680
+ truncated = true;
1681
+ details = { _truncated: true, _originalSize: raw.length, _preview: raw.slice(0, MAX_RESULT_CHARS) };
1682
+ }
1683
+ }
1684
+ return {
1685
+ success: true,
1686
+ elapsed,
1687
+ content: [{ type: "text", text: result.content }],
1688
+ details,
1689
+ truncated
1690
+ };
1691
+ } catch (error) {
1692
+ if (abortSignal.aborted) {
1693
+ return { success: false, error: "cancelled" };
1694
+ }
1695
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1696
+ }
1697
+ }
1698
+
1699
+ // ../../packages/http-routes/src/routes/web/ai-tools.ts
1617
1700
  var activeToolTests = /* @__PURE__ */ new Map();
1618
1701
  function registerAiToolRoutes(server2, ctx) {
1619
1702
  server2.get("/_web/ai/tools/full-catalog", async () => {
@@ -1640,40 +1723,22 @@ function registerAiToolRoutes(server2, ctx) {
1640
1723
  if (!db) {
1641
1724
  return reply.code(404).send({ success: false, error: `Session not found: ${sessionId}` });
1642
1725
  }
1643
- const execCtx = {
1644
- sessionId,
1645
- db,
1646
- dataProvider: new CoreDataProvider(db),
1647
- abortSignal: abortController.signal
1648
- };
1649
- const startTime = Date.now();
1650
- const result = await entry.handler(params, execCtx);
1651
- const elapsed = Date.now() - startTime;
1652
- if (abortController.signal.aborted) {
1653
- return { success: false, error: "cancelled" };
1654
- }
1655
- let details = result.data ?? void 0;
1656
- let truncated = false;
1657
- if (details) {
1658
- stripAvatarFields(details);
1659
- const raw = JSON.stringify(details);
1660
- if (raw.length > MAX_RESULT_CHARS) {
1661
- truncated = true;
1662
- details = { _truncated: true, _originalSize: raw.length, _preview: raw.slice(0, MAX_RESULT_CHARS) };
1726
+ const result = await executeRegistryTool(
1727
+ { testId, toolName, params, sessionId, abortSignal: abortController.signal },
1728
+ {
1729
+ db,
1730
+ dataProvider: new CoreDataProvider(db)
1663
1731
  }
1732
+ );
1733
+ if (!result.success && result.error !== "cancelled") {
1734
+ appLogger.error("ai-tools", `Failed to execute tool ${toolName}`, { error: result.error });
1664
1735
  }
1665
- return {
1666
- success: true,
1667
- elapsed,
1668
- content: [{ type: "text", text: result.content }],
1669
- details,
1670
- truncated
1671
- };
1736
+ return result;
1672
1737
  } catch (error) {
1673
1738
  if (abortController.signal.aborted) {
1674
1739
  return { success: false, error: "cancelled" };
1675
1740
  }
1676
- console.error(`Failed to execute tool ${toolName}:`, error);
1741
+ appLogger.error("ai-tools", `Failed to execute tool ${toolName}`, error);
1677
1742
  return { success: false, error: String(error) };
1678
1743
  } finally {
1679
1744
  activeToolTests.delete(testId);
@@ -3185,10 +3250,10 @@ function registerWebRoutes(server2, dbManager2, options) {
3185
3250
  const resolvedPathProvider = options?.pathProvider ?? fallbackPathProvider;
3186
3251
  const ai = options?.aiContext;
3187
3252
  const cliStreamImport = async (dm, filePath) => {
3188
- const { streamImport: streamImport2 } = await import("./stream-import-VUEL2TTU.mjs");
3253
+ const { streamImport: streamImport2 } = await import("./stream-import-AWEHGQJY.mjs");
3189
3254
  const result = await streamImport2(dm, filePath);
3190
3255
  if (!result.success) {
3191
- const { IMPORT_IN_PROGRESS_ERROR_KEY: IMPORT_IN_PROGRESS_ERROR_KEY2, ImportInProgressError: ImportInProgressError2 } = await import("./src-R3QX6L3L.mjs");
3256
+ const { IMPORT_IN_PROGRESS_ERROR_KEY: IMPORT_IN_PROGRESS_ERROR_KEY2, ImportInProgressError: ImportInProgressError2 } = await import("./src-7OD6RD5V.mjs");
3192
3257
  if (result.error === IMPORT_IN_PROGRESS_ERROR_KEY2) throw new ImportInProgressError2();
3193
3258
  throw new Error(result.error || "Import failed");
3194
3259
  }
@@ -4432,4 +4497,4 @@ export {
4432
4497
  startHttpServer,
4433
4498
  stopHttpServer
4434
4499
  };
4435
- //# sourceMappingURL=chunk-JH5RAJT2.mjs.map
4500
+ //# sourceMappingURL=chunk-SZEBCNBB.mjs.map