chatlab-cli 0.34.0 → 0.34.2-beta.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 (125) hide show
  1. package/dist/{chat-command-XPY3WURC.mjs → chat-command-6IOH2QRF.mjs} +9 -9
  2. package/dist/{chunk-S5NCEESV.mjs → chunk-2XCNTG4O.mjs} +403 -76
  3. package/dist/chunk-2XCNTG4O.mjs.map +1 -0
  4. package/dist/{chunk-AQPDZAWB.mjs → chunk-4LW6443F.mjs} +1802 -712
  5. package/dist/chunk-4LW6443F.mjs.map +1 -0
  6. package/dist/{chunk-ISRLGLUL.mjs → chunk-4RLZFGO5.mjs} +2 -2
  7. package/dist/{chunk-IGEHMLHM.mjs → chunk-52P5ZRBD.mjs} +2 -2
  8. package/dist/{chunk-JTOHAMIW.mjs → chunk-652KEAX3.mjs} +2 -2
  9. package/dist/{chunk-DGF3S3TZ.mjs → chunk-72RWABYJ.mjs} +15 -9
  10. package/dist/chunk-72RWABYJ.mjs.map +1 -0
  11. package/dist/{chunk-JCSPDTZL.mjs → chunk-H6D4DZOC.mjs} +4 -4
  12. package/dist/{chunk-OLE2USEN.mjs → chunk-INBJ7SND.mjs} +53 -26
  13. package/dist/chunk-INBJ7SND.mjs.map +1 -0
  14. package/dist/{chunk-IGK6UMN2.mjs → chunk-JX6MFS6F.mjs} +43 -23
  15. package/dist/chunk-JX6MFS6F.mjs.map +1 -0
  16. package/dist/{chunk-UO2XVFY6.mjs → chunk-MENKFEPC.mjs} +147 -73
  17. package/dist/chunk-MENKFEPC.mjs.map +1 -0
  18. package/dist/{chunk-BQ3QN4QT.mjs → chunk-U6MVJSXX.mjs} +170 -66
  19. package/dist/chunk-U6MVJSXX.mjs.map +1 -0
  20. package/dist/chunk-UMBEHBIZ.mjs +41 -0
  21. package/dist/chunk-UMBEHBIZ.mjs.map +1 -0
  22. package/dist/{chunk-GFHSSCCR.mjs → chunk-VSOWNKPA.mjs} +1 -11
  23. package/dist/cli.mjs +10 -9
  24. package/dist/contacts-worker.mjs +3 -3
  25. package/dist/global-insight-worker.mjs +2 -2
  26. package/dist/{http-HV6XWU6X.mjs → http-HSK46XEU.mjs} +13 -12
  27. package/dist/{import-DP2XLZ2H.mjs → import-DF2WD2HE.mjs} +10 -8
  28. package/dist/index.mjs +13 -12
  29. package/dist/{mcp-QDPFBPGW.mjs → mcp-A2RND7KN.mjs} +12 -12
  30. package/dist/people-relationships-worker.mjs +3 -3
  31. package/dist/semantic-index-worker.mjs +1 -1
  32. package/dist/{service-KGL3RAIA.mjs → service-KZTHBDQ5.mjs} +2 -2
  33. package/dist/{src-B3A2QHP5.mjs → src-SHFHW2QB.mjs} +29 -7
  34. package/dist/{stream-import-KEGNP3QK.mjs → stream-import-GZ2QDE3Z.mjs} +10 -8
  35. package/dist/{undici-ZSXBT7EA.mjs → undici-MU5I3L6Q.mjs} +2 -2
  36. package/dist/{update-checker-LGMTEKMT.mjs → update-checker-3N7HQEP2.mjs} +2 -2
  37. package/dist/{worker-runtime-MDYKX3BW.mjs → worker-runtime-OWN56GG5.mjs} +14 -8
  38. package/dist/worker-runtime-OWN56GG5.mjs.map +1 -0
  39. package/dist-cli-web/assets/{ActionToolsPanel.vue_vue_type_script_setup_true_lang-JxPR2O6b.js → ActionToolsPanel.vue_vue_type_script_setup_true_lang-yr_T4ttU.js} +14 -14
  40. package/dist-cli-web/assets/{BufferResource--dSbJb0k.js → BufferResource-B-LHxriL.js} +1 -1
  41. package/dist-cli-web/assets/{CanvasRenderer-Cm_dmJXZ.js → CanvasRenderer-W3h_GGHM.js} +1 -1
  42. package/dist-cli-web/assets/{DataDirCleanupNotice-B0s5txX3.js → DataDirCleanupNotice-C6CMNhfs.js} +1 -1
  43. package/dist-cli-web/assets/{EChartWordcloud-CwMVJLBO.js → EChartWordcloud-Dt6rCzHf.js} +1 -1
  44. package/dist-cli-web/assets/{Filter-BjYScRpK.js → Filter-BpSopVKd.js} +1 -1
  45. package/dist-cli-web/assets/{LoadingState.vue_vue_type_script_setup_true_lang-BshQybD_.js → LoadingState.vue_vue_type_script_setup_true_lang-Bi_Uag3T.js} +1 -1
  46. package/dist-cli-web/assets/{MessageExportModal-DAJW2mFj.js → MessageExportModal-BoK-_h25.js} +1 -1
  47. package/dist-cli-web/assets/{PageHeader-BKAjCuqs.js → PageHeader-CD8B7Emf.js} +1 -1
  48. package/dist-cli-web/assets/{RelationshipGalaxyCanvas-mlZs7k4L.js → RelationshipGalaxyCanvas-BO3mo-Re.js} +7 -7
  49. package/dist-cli-web/assets/RelationshipGalaxyThreeCanvas-Brnpz6Ig.js +4108 -0
  50. package/dist-cli-web/assets/{RelationshipGalaxyThreeCanvas-CeYJABxI.css → RelationshipGalaxyThreeCanvas-CMuibfiA.css} +1 -1
  51. package/dist-cli-web/assets/{RenderTargetSystem-D00Ex44y.js → RenderTargetSystem-CNP4JLfK.js} +1 -1
  52. package/dist-cli-web/assets/{ThemeCard.vue_vue_type_script_setup_true_lang-Dsb6lzs-.js → ThemeCard.vue_vue_type_script_setup_true_lang-Na3LIoSJ.js} +1 -1
  53. package/dist-cli-web/assets/{TimeSelect.vue_vue_type_script_setup_true_lang-BfR3tlkz.js → TimeSelect.vue_vue_type_script_setup_true_lang-CKe1YZrV.js} +1 -1
  54. package/dist-cli-web/assets/{WebGLRenderer-CTTusm2n.js → WebGLRenderer-CIR5cTQN.js} +1 -1
  55. package/dist-cli-web/assets/{WebGPURenderer-pyv3EXor.js → WebGPURenderer-Dz3pCrzX.js} +1 -1
  56. package/dist-cli-web/assets/{annual-summary-time-range-C_d1oZrj.js → annual-summary-time-range-QhoA3uC6.js} +1 -1
  57. package/dist-cli-web/assets/{base-D91aVUwM.js → base-p9yfnTpk.js} +1 -1
  58. package/dist-cli-web/assets/{browserAll-C9fW936Y.js → browserAll-DMaXjf8N.js} +1 -1
  59. package/dist-cli-web/assets/cli-web-Dvy2aHxG.js +1 -0
  60. package/dist-cli-web/assets/{dateFormat-rY43adcv.js → dateFormat-5x3JKlIk.js} +1 -1
  61. package/dist-cli-web/assets/{fetch-CbnX5VoM.js → fetch-B0p6QRQ8.js} +1 -1
  62. package/dist-cli-web/assets/{fetch-DYNgtIcU.js → fetch-BI-Se2p7.js} +1 -1
  63. package/dist-cli-web/assets/{fetch-Kk2knkEo.js → fetch-BderOzzL.js} +1 -1
  64. package/dist-cli-web/assets/{fetch-DG3AeEjW.js → fetch-BtJWW2-O.js} +1 -1
  65. package/dist-cli-web/assets/fetch-CBaZNOpK.js +4 -0
  66. package/dist-cli-web/assets/{fetch-CNy9OQ2g.js → fetch-CH9Hm20R.js} +1 -1
  67. package/dist-cli-web/assets/{fetch-CrSz5KJy.js → fetch-CbpKKkdO.js} +1 -1
  68. package/dist-cli-web/assets/{fetch-PLrI3V67.js → fetch-Cne-uL1m.js} +1 -1
  69. package/dist-cli-web/assets/{fetch-DZPC3D8R.js → fetch-DRGykJYb.js} +1 -1
  70. package/dist-cli-web/assets/{fetch-CS3T-v-1.js → fetch-QLurhC_z.js} +1 -1
  71. package/dist-cli-web/assets/{index-JYfjMRb-.js → index-4NL2pYn0.js} +1 -1
  72. package/dist-cli-web/assets/{index-2-OaYdzt.js → index-B-KdENnr.js} +1 -1
  73. package/dist-cli-web/assets/{index-CGI3Y8pq.js → index-BDyixm5n.js} +1 -1
  74. package/dist-cli-web/assets/{index-BKo68Iu5.js → index-BaCd1avL.js} +1 -1
  75. package/dist-cli-web/assets/{index-ZTgfCZvY.js → index-CVBBDI3B.js} +3 -3
  76. package/dist-cli-web/assets/index-CXh01dqh.js +2 -0
  77. package/dist-cli-web/assets/index-CioAsn_2.js +137 -0
  78. package/dist-cli-web/assets/{index-DA3Q0TGT.js → index-Ct90lmPb.js} +1 -1
  79. package/dist-cli-web/assets/index-CumZ5uQ4.js +53 -0
  80. package/dist-cli-web/assets/index-CxGtGxLW.css +1 -0
  81. package/dist-cli-web/assets/{index-DsdMsKYT.js → index-DF2Dijfg.js} +1 -1
  82. package/dist-cli-web/assets/{index-3YO6RI5e.js → index-DYCPQMOl.js} +2 -2
  83. package/dist-cli-web/assets/{index-DFHYr_-u.js → index-Dp2uglLH.js} +1 -1
  84. package/dist-cli-web/assets/{index-BrkDgcJ6.js → index-IvxuxPNt.js} +1 -1
  85. package/dist-cli-web/assets/{people-page-header-D-LWaEqn.js → people-page-header-BRb9BrgP.js} +1 -1
  86. package/dist-cli-web/assets/telemetry-DPC69b73.js +1 -0
  87. package/dist-cli-web/assets/{webworkerAll-CPOVECup.js → webworkerAll-BoY19vZt.js} +1 -1
  88. package/dist-cli-web/index.html +1 -1
  89. package/package.json +3 -2
  90. package/dist/chunk-AQPDZAWB.mjs.map +0 -1
  91. package/dist/chunk-BQ3QN4QT.mjs.map +0 -1
  92. package/dist/chunk-DGF3S3TZ.mjs.map +0 -1
  93. package/dist/chunk-IGK6UMN2.mjs.map +0 -1
  94. package/dist/chunk-OLE2USEN.mjs.map +0 -1
  95. package/dist/chunk-S5NCEESV.mjs.map +0 -1
  96. package/dist/chunk-UO2XVFY6.mjs.map +0 -1
  97. package/dist/onnxruntime_binding-6Q6HXASN.node +0 -0
  98. package/dist/onnxruntime_binding-EKZT2NRK.node +0 -0
  99. package/dist/onnxruntime_binding-P6S7V3CI.node +0 -0
  100. package/dist/onnxruntime_binding-PJNNIIUO.node +0 -0
  101. package/dist/onnxruntime_binding-UN6SPTQK.node +0 -0
  102. package/dist/transformers.node-PUMHAODN.mjs +0 -42889
  103. package/dist/transformers.node-PUMHAODN.mjs.map +0 -1
  104. package/dist/worker-runtime-MDYKX3BW.mjs.map +0 -1
  105. package/dist-cli-web/assets/RelationshipGalaxyThreeCanvas-DgMG3jdU.js +0 -4108
  106. package/dist-cli-web/assets/cli-web-C7uGKz_E.js +0 -1
  107. package/dist-cli-web/assets/fetch-C6po4XYB.js +0 -3
  108. package/dist-cli-web/assets/index-2S80bo1s.js +0 -2
  109. package/dist-cli-web/assets/index-CW9H_fBd.js +0 -53
  110. package/dist-cli-web/assets/index-DmrrdYXH.css +0 -1
  111. package/dist-cli-web/assets/index-DmwA85vG.js +0 -173
  112. /package/dist/{chat-command-XPY3WURC.mjs.map → chat-command-6IOH2QRF.mjs.map} +0 -0
  113. /package/dist/{chunk-ISRLGLUL.mjs.map → chunk-4RLZFGO5.mjs.map} +0 -0
  114. /package/dist/{chunk-IGEHMLHM.mjs.map → chunk-52P5ZRBD.mjs.map} +0 -0
  115. /package/dist/{chunk-JTOHAMIW.mjs.map → chunk-652KEAX3.mjs.map} +0 -0
  116. /package/dist/{chunk-JCSPDTZL.mjs.map → chunk-H6D4DZOC.mjs.map} +0 -0
  117. /package/dist/{chunk-GFHSSCCR.mjs.map → chunk-VSOWNKPA.mjs.map} +0 -0
  118. /package/dist/{http-HV6XWU6X.mjs.map → http-HSK46XEU.mjs.map} +0 -0
  119. /package/dist/{import-DP2XLZ2H.mjs.map → import-DF2WD2HE.mjs.map} +0 -0
  120. /package/dist/{mcp-QDPFBPGW.mjs.map → mcp-A2RND7KN.mjs.map} +0 -0
  121. /package/dist/{service-KGL3RAIA.mjs.map → service-KZTHBDQ5.mjs.map} +0 -0
  122. /package/dist/{src-B3A2QHP5.mjs.map → src-SHFHW2QB.mjs.map} +0 -0
  123. /package/dist/{stream-import-KEGNP3QK.mjs.map → stream-import-GZ2QDE3Z.mjs.map} +0 -0
  124. /package/dist/{undici-ZSXBT7EA.mjs.map → undici-MU5I3L6Q.mjs.map} +0 -0
  125. /package/dist/{update-checker-LGMTEKMT.mjs.map → update-checker-3N7HQEP2.mjs.map} +0 -0
@@ -11,24 +11,31 @@ import {
11
11
  getServerAiLogger,
12
12
  getSkillManagerCore,
13
13
  initServerAiLogger
14
- } from "./chunk-JCSPDTZL.mjs";
14
+ } from "./chunk-H6D4DZOC.mjs";
15
15
  import {
16
16
  AGENT_TOOL_REGISTRY,
17
17
  CoreDataProvider
18
- } from "./chunk-DGF3S3TZ.mjs";
18
+ } from "./chunk-72RWABYJ.mjs";
19
+ import {
20
+ resolveCliLocalEmbeddingRuntimeConfig
21
+ } from "./chunk-UMBEHBIZ.mjs";
19
22
  import {
20
23
  analyzeIncrementalImport,
21
24
  analyzeNewImport,
22
25
  autoImport,
26
+ autoImportBatch,
23
27
  incrementalImport,
24
28
  streamImport
25
- } from "./chunk-BQ3QN4QT.mjs";
29
+ } from "./chunk-U6MVJSXX.mjs";
26
30
  import {
27
31
  assertCliDataDirCompatible
28
- } from "./chunk-ISRLGLUL.mjs";
32
+ } from "./chunk-4RLZFGO5.mjs";
29
33
  import {
30
34
  getVersion
31
35
  } from "./chunk-5ADKYYNA.mjs";
36
+ import {
37
+ resolveCliPath
38
+ } from "./chunk-FJ35V3TE.mjs";
32
39
  import {
33
40
  AnalyticsService,
34
41
  NodePathProvider,
@@ -45,8 +52,9 @@ import {
45
52
  getPendingDataDirCleanups,
46
53
  getPendingNodeDataDirMigration,
47
54
  hasPendingElectronDataWarning,
55
+ importDemoSessions,
48
56
  serializeChatLabToJsonl
49
- } from "./chunk-S5NCEESV.mjs";
57
+ } from "./chunk-2XCNTG4O.mjs";
50
58
  import {
51
59
  AIChatManager,
52
60
  ArchiveImportError,
@@ -98,10 +106,7 @@ import {
98
106
  streamParseFileInfo,
99
107
  summary_service_exports,
100
108
  validateApiKey
101
- } from "./chunk-AQPDZAWB.mjs";
102
- import {
103
- resolveCliPath
104
- } from "./chunk-FJ35V3TE.mjs";
109
+ } from "./chunk-4LW6443F.mjs";
105
110
  import {
106
111
  ALL_MIGRATIONS,
107
112
  BUILTIN_MODELS,
@@ -162,7 +167,7 @@ import {
162
167
  stripAvatarFields,
163
168
  verifyCliDataPath,
164
169
  writeConfigField
165
- } from "./chunk-OLE2USEN.mjs";
170
+ } from "./chunk-INBJ7SND.mjs";
166
171
 
167
172
  // src/http/index.ts
168
173
  import * as fs11 from "fs";
@@ -2437,7 +2442,7 @@ function registerMergeRoutes(server2, ctx) {
2437
2442
  }
2438
2443
  });
2439
2444
  server2.post("/_web/merge/execute", async (request, reply) => {
2440
- const { handles, outputName, format = "json", andImport } = request.body;
2445
+ const { handles, outputName, format = "json", andImport, sessionGapThreshold } = request.body;
2441
2446
  if (!handles || !Array.isArray(handles) || handles.length === 0) {
2442
2447
  return reply.code(400).send({ error: "Missing handles" });
2443
2448
  }
@@ -2465,7 +2470,7 @@ function registerMergeRoutes(server2, ctx) {
2465
2470
  const tmpPath = path6.join(tmpDir, `${safeName}.json`);
2466
2471
  fs4.writeFileSync(tmpPath, jsonData, "utf-8");
2467
2472
  try {
2468
- const importResult = await streamImport2(dbManager2, tmpPath);
2473
+ const importResult = await streamImport2(dbManager2, tmpPath, { sessionGapThreshold });
2469
2474
  sessionId = importResult.sessionId;
2470
2475
  } finally {
2471
2476
  try {
@@ -3046,8 +3051,13 @@ function resolveNativeBinding() {
3046
3051
  }
3047
3052
 
3048
3053
  // src/http/routes/web/import.ts
3049
- var DEMO_BASE_URL = "https://chatlab.fun/assets/demo";
3050
3054
  var ARCHIVE_UPLOAD_LIMIT = 50 * 1024 * 1024 * 1024;
3055
+ function parseOptionalInteger(value) {
3056
+ if (typeof value === "number") return Number.isInteger(value) ? value : void 0;
3057
+ if (typeof value !== "string" || value.trim() === "") return void 0;
3058
+ const parsed = Number(value);
3059
+ return Number.isInteger(parsed) ? parsed : void 0;
3060
+ }
3051
3061
  function cleanupTemp(...paths) {
3052
3062
  for (const p of paths) {
3053
3063
  try {
@@ -3062,11 +3072,14 @@ function cleanupTemp(...paths) {
3062
3072
  }
3063
3073
  }
3064
3074
  function registerImportRoutes2(server2, dbManager2, options = {}) {
3075
+ const activeBatchControllers = /* @__PURE__ */ new Map();
3065
3076
  const sourceManager = options.sourceManager ?? new ArchiveImportSourceManager();
3066
3077
  const runAutoImport = options.runAutoImport ?? autoImport.bind(null, dbManager2);
3067
- const runPreparedImport = options.runPreparedImport ?? (async (manifestPath, onProgress) => {
3078
+ const runAutoImportBatch = options.runAutoImportBatch ?? autoImportBatch.bind(null, dbManager2);
3079
+ const runPreparedImport = options.runPreparedImport ?? (async (manifestPath, onProgress, sessionGapThreshold) => {
3068
3080
  const result = await runAutoImport(manifestPath, {
3069
3081
  formatId: "google-chat-takeout",
3082
+ sessionGapThreshold,
3070
3083
  nativeBinding: resolveNativeBinding(),
3071
3084
  onProgress
3072
3085
  });
@@ -3117,10 +3130,11 @@ data: ${JSON.stringify(eventData)}
3117
3130
  `);
3118
3131
  }
3119
3132
  try {
3133
+ const sessionGapThreshold = parseOptionalInteger(request.body?.sessionGapThreshold);
3120
3134
  const result = await sourceManager.withMaterializedChat(
3121
3135
  request.params.sourceId,
3122
3136
  chatId,
3123
- (manifestPath) => runPreparedImport(manifestPath, (progress) => sendEvent("progress", progress))
3137
+ (manifestPath) => runPreparedImport(manifestPath, (progress) => sendEvent("progress", progress), sessionGapThreshold)
3124
3138
  );
3125
3139
  if (result.success) {
3126
3140
  sendEvent("done", result);
@@ -3192,6 +3206,7 @@ data: ${JSON.stringify(eventData)}
3192
3206
  const formatId = data.fields?.formatId?.value;
3193
3207
  const chatIndexStr = data.fields?.chatIndex?.value;
3194
3208
  const chatIndex = chatIndexStr !== void 0 ? parseInt(chatIndexStr, 10) : void 0;
3209
+ const sessionGapThreshold = parseOptionalInteger(data.fields?.sessionGapThreshold?.value);
3195
3210
  reply.raw.writeHead(200, {
3196
3211
  "Content-Type": "text/event-stream",
3197
3212
  "Cache-Control": "no-cache",
@@ -3208,13 +3223,14 @@ data: ${JSON.stringify(eventData)}
3208
3223
  const result = await runAutoImport(tmpPath, {
3209
3224
  formatId,
3210
3225
  chatIndex,
3226
+ sessionGapThreshold,
3211
3227
  nativeBinding,
3212
3228
  onProgress: (p) => sendEvent("progress", p)
3213
3229
  });
3214
3230
  if (result.success) {
3215
3231
  sendEvent("done", result);
3216
3232
  } else {
3217
- sendEvent("error", { success: false, error: result.error });
3233
+ sendEvent("error", result);
3218
3234
  }
3219
3235
  } catch (err) {
3220
3236
  sendEvent("error", { success: false, error: err instanceof Error ? err.message : String(err) });
@@ -3223,12 +3239,89 @@ data: ${JSON.stringify(eventData)}
3223
3239
  cleanupTemp(tmpPath, tmpDir);
3224
3240
  }
3225
3241
  });
3242
+ server2.post("/_web/import/batch", async (request, reply) => {
3243
+ const parts = request.parts();
3244
+ if (!parts) return reply.code(400).send({ error: "No files uploaded" });
3245
+ const requestedBatchId = request.headers["x-chatlab-import-batch-id"];
3246
+ const batchId = typeof requestedBatchId === "string" && requestedBatchId ? requestedBatchId : randomUUID();
3247
+ if (activeBatchControllers.has(batchId)) {
3248
+ return reply.code(409).send({ error: "Batch import id is already active" });
3249
+ }
3250
+ const tmpDir = createChatLabTempDir("imports", "batch-");
3251
+ const items = [];
3252
+ let sessionGapThreshold;
3253
+ let completed = false;
3254
+ const controller = new AbortController();
3255
+ activeBatchControllers.set(batchId, controller);
3256
+ try {
3257
+ for await (const part of parts) {
3258
+ if (part.type === "field" && part.fieldname === "sessionGapThreshold") {
3259
+ sessionGapThreshold = parseOptionalInteger(part.value);
3260
+ continue;
3261
+ }
3262
+ if (part.type !== "file") continue;
3263
+ const index = items.length;
3264
+ const safeName = path8.basename(part.filename || `upload-${index}`);
3265
+ const filePath = path8.join(tmpDir, `${index}-${safeName}`);
3266
+ await pipeline(part.file, fs7.createWriteStream(filePath, { flags: "wx" }));
3267
+ items.push({ id: String(index), filePath });
3268
+ }
3269
+ if (items.length === 0) return reply.code(400).send({ error: "No files uploaded" });
3270
+ reply.raw.writeHead(200, {
3271
+ "Content-Type": "text/event-stream",
3272
+ "Cache-Control": "no-cache",
3273
+ Connection: "keep-alive"
3274
+ });
3275
+ reply.raw.once("close", () => {
3276
+ if (!completed) controller.abort();
3277
+ });
3278
+ const sendEvent = (event, eventData) => {
3279
+ if (!reply.raw.destroyed) {
3280
+ reply.raw.write(`event: ${event}
3281
+ data: ${JSON.stringify(eventData)}
3282
+
3283
+ `);
3284
+ }
3285
+ };
3286
+ const results = await runAutoImportBatch(items, {
3287
+ sessionGapThreshold,
3288
+ signal: controller.signal,
3289
+ onItemStart: (_item, index) => sendEvent("batch-start", { index }),
3290
+ onItemProgress: (_item, index, progress) => sendEvent("batch-progress", { index, progress }),
3291
+ onItemComplete: (_item, index, result) => sendEvent("batch-complete", { index, result })
3292
+ });
3293
+ completed = true;
3294
+ sendEvent("done", results);
3295
+ } catch (error) {
3296
+ appLogger.error("import-batch", "CLI Web batch import failed", error);
3297
+ const payload = { error: error instanceof Error ? error.message : String(error) };
3298
+ if (!reply.raw.headersSent) return reply.code(500).send(payload);
3299
+ if (!reply.raw.destroyed) {
3300
+ reply.raw.write(`event: error
3301
+ data: ${JSON.stringify(payload)}
3302
+
3303
+ `);
3304
+ }
3305
+ } finally {
3306
+ completed = true;
3307
+ if (activeBatchControllers.get(batchId) === controller) activeBatchControllers.delete(batchId);
3308
+ reply.raw.end();
3309
+ cleanupTemp(tmpDir);
3310
+ }
3311
+ });
3312
+ server2.post("/_web/import/batch/:batchId/cancel", async (request) => {
3313
+ const controller = activeBatchControllers.get(request.params.batchId);
3314
+ if (!controller) return { success: false, active: false };
3315
+ controller.abort();
3316
+ return { success: true, active: true };
3317
+ });
3226
3318
  server2.post("/_web/import-directory", async (request, reply) => {
3227
3319
  const parts = request.parts();
3228
3320
  if (!parts) return reply.code(400).send({ error: "No files uploaded" });
3229
3321
  const tmpDir = createChatLabTempDir("imports", "directory-");
3230
3322
  const relativePaths = [];
3231
3323
  const fileBuffers = [];
3324
+ let sessionGapThreshold;
3232
3325
  try {
3233
3326
  let sendEvent2 = function(event, eventData) {
3234
3327
  reply.raw.write(`event: ${event}
@@ -3240,6 +3333,8 @@ data: ${JSON.stringify(eventData)}
3240
3333
  for await (const part of parts) {
3241
3334
  if (part.type === "field" && part.fieldname === "relativePaths") {
3242
3335
  relativePaths.push(String(part.value));
3336
+ } else if (part.type === "field" && part.fieldname === "sessionGapThreshold") {
3337
+ sessionGapThreshold = parseOptionalInteger(part.value);
3243
3338
  } else if (part.type === "file") {
3244
3339
  const chunks = [];
3245
3340
  for await (const chunk of part.file) {
@@ -3270,13 +3365,14 @@ data: ${JSON.stringify(eventData)}
3270
3365
  });
3271
3366
  const nativeBinding = resolveNativeBinding();
3272
3367
  const result = await runAutoImport(entryPath, {
3368
+ sessionGapThreshold,
3273
3369
  nativeBinding,
3274
3370
  onProgress: (p) => sendEvent2("progress", p)
3275
3371
  });
3276
3372
  if (result.success) {
3277
3373
  sendEvent2("done", result);
3278
3374
  } else {
3279
- sendEvent2("error", { success: false, error: result.error });
3375
+ sendEvent2("error", result);
3280
3376
  }
3281
3377
  } catch (err) {
3282
3378
  if (!reply.raw.headersSent) {
@@ -3368,65 +3464,38 @@ data: ${JSON.stringify(eventData)}
3368
3464
  cleanupTemp(tmpPath, tmpDir);
3369
3465
  }
3370
3466
  });
3371
- const DEMO_FILES = [
3372
- "demo-group.json",
3373
- "demo-private-A-cuilan.json",
3374
- "demo-private-B-wukong.json",
3375
- "demo-private-C-spider.json"
3376
- ];
3377
- server2.post("/_web/demo/import", async (request, reply) => {
3378
- const locale = request.body?.locale || "en";
3379
- const nativeBinding = resolveNativeBinding();
3380
- const total = DEMO_FILES.length;
3381
- reply.raw.writeHead(200, {
3382
- "Content-Type": "text/event-stream",
3383
- "Cache-Control": "no-cache",
3384
- Connection: "keep-alive"
3385
- });
3386
- function sendEvent(event, eventData) {
3387
- reply.raw.write(`event: ${event}
3467
+ server2.post(
3468
+ "/_web/demo/import",
3469
+ async (request, reply) => {
3470
+ const locale = request.body?.locale === "cn" ? "cn" : "en";
3471
+ const targetTimeZone = typeof request.body?.timeZone === "string" ? request.body.timeZone : void 0;
3472
+ const sessionGapThreshold = parseOptionalInteger(request.body?.sessionGapThreshold);
3473
+ const nativeBinding = resolveNativeBinding();
3474
+ reply.raw.writeHead(200, {
3475
+ "Content-Type": "text/event-stream",
3476
+ "Cache-Control": "no-cache",
3477
+ Connection: "keep-alive"
3478
+ });
3479
+ function sendEvent(event, eventData) {
3480
+ reply.raw.write(`event: ${event}
3388
3481
  data: ${JSON.stringify(eventData)}
3389
3482
 
3390
3483
  `);
3391
- }
3392
- const tmpDir = createChatLabTempDir("imports", "cli-demo-");
3393
- try {
3394
- const localPaths = [];
3395
- for (let i = 0; i < total; i++) {
3396
- sendEvent("progress", { stage: "downloading", current: i + 1, total });
3397
- const localPath = path8.join(tmpDir, DEMO_FILES[i]);
3398
- const resp = await fetch(`${DEMO_BASE_URL}/${locale}/${DEMO_FILES[i]}`, {
3399
- signal: AbortSignal.timeout(6e4)
3400
- });
3401
- if (!resp.ok) throw new Error(`Download demo failed (${DEMO_FILES[i]}): ${resp.status}`);
3402
- fs7.writeFileSync(localPath, Buffer.from(await resp.arrayBuffer()));
3403
- localPaths.push(localPath);
3404
3484
  }
3405
- sendEvent("progress", { stage: "importing", current: 1, total });
3406
- const groupResult = await streamImport(dbManager2, localPaths[0], { nativeBinding });
3407
- if (!groupResult.success) throw new Error(groupResult.error || "Failed to import group demo");
3408
- const privateSessionIds = [];
3409
- for (let i = 1; i < localPaths.length; i++) {
3410
- sendEvent("progress", { stage: "importing", current: i + 1, total });
3411
- const result = await streamImport(dbManager2, localPaths[i], { nativeBinding });
3412
- if (!result.success) throw new Error(result.error || `Failed to import private demo: ${DEMO_FILES[i]}`);
3413
- if (result.sessionId) privateSessionIds.push(result.sessionId);
3414
- }
3415
- sendEvent("progress", { stage: "done", current: total, total });
3416
- sendEvent("result", {
3417
- success: true,
3418
- groupSessionId: groupResult.sessionId,
3419
- privateSessionIds
3485
+ const result = await importDemoSessions({
3486
+ locale,
3487
+ tempPrefix: "cli-demo-",
3488
+ targetTimeZone,
3489
+ importFile: (filePath) => streamImport(dbManager2, filePath, { nativeBinding, sessionGapThreshold }),
3490
+ deleteSession: (sessionId) => {
3491
+ dbManager2.deleteSessionDatabaseFiles(sessionId);
3492
+ },
3493
+ onProgress: (progress) => sendEvent("progress", progress)
3420
3494
  });
3421
- } catch (err) {
3422
- const message = err instanceof Error ? err.message : String(err);
3423
- sendEvent("progress", { stage: "error", current: 0, total, message });
3424
- sendEvent("result", { success: false, error: message });
3425
- } finally {
3495
+ sendEvent("result", result);
3426
3496
  reply.raw.end();
3427
- cleanupTemp(tmpDir);
3428
3497
  }
3429
- });
3498
+ );
3430
3499
  }
3431
3500
 
3432
3501
  // src/http/routes/web/cache.ts
@@ -3495,10 +3564,10 @@ function registerWebRoutes2(server2, dbManager2, options) {
3495
3564
  const resolvedPathProvider = options?.pathProvider ?? fallbackPathProvider;
3496
3565
  const ai = options?.aiContext;
3497
3566
  const cliStreamImport = async (dm, filePath) => {
3498
- const { streamImport: streamImport2 } = await import("./stream-import-KEGNP3QK.mjs");
3567
+ const { streamImport: streamImport2 } = await import("./stream-import-GZ2QDE3Z.mjs");
3499
3568
  const result = await streamImport2(dm, filePath);
3500
3569
  if (!result.success) {
3501
- const { IMPORT_IN_PROGRESS_ERROR_KEY: IMPORT_IN_PROGRESS_ERROR_KEY2, ImportInProgressError: ImportInProgressError2 } = await import("./src-B3A2QHP5.mjs");
3570
+ const { IMPORT_IN_PROGRESS_ERROR_KEY: IMPORT_IN_PROGRESS_ERROR_KEY2, ImportInProgressError: ImportInProgressError2 } = await import("./src-SHFHW2QB.mjs");
3502
3571
  if (result.error === IMPORT_IN_PROGRESS_ERROR_KEY2) throw new ImportInProgressError2();
3503
3572
  throw new Error(result.error || "Import failed");
3504
3573
  }
@@ -3508,7 +3577,11 @@ function registerWebRoutes2(server2, dbManager2, options) {
3508
3577
  const defaultUserDataDir = getDefaultNodeUserDataDir();
3509
3578
  const isCustom = path10.resolve(resolvedPathProvider.getUserDataDir()) !== path10.resolve(defaultUserDataDir);
3510
3579
  const semanticIndexService = options?.semanticIndexService;
3511
- const analyticsService = "A-US-0629338532" ? new AnalyticsService(resolvedPathProvider.getSystemDir(), "A-US-0629338532", getVersion()) : void 0;
3580
+ const analyticsService = new AnalyticsService(resolvedPathProvider.getSystemDir(), {
3581
+ appVersion: getVersion(),
3582
+ appType: "cli_web",
3583
+ getAiModelConfigured: () => ai?.llmConfigStore.hasConfiguredModel() === true
3584
+ });
3512
3585
  registerSharedRoutes(
3513
3586
  server2,
3514
3587
  {
@@ -4601,6 +4674,7 @@ async function startHttpServer(options) {
4601
4674
  pathProvider,
4602
4675
  runtime,
4603
4676
  nativeBinding,
4677
+ localEmbeddingRuntime: resolveCliLocalEmbeddingRuntimeConfig(pathProvider.getAiDataDir()),
4604
4678
  workerEntryUrl: import.meta.url.endsWith(".ts") ? void 0 : new URL("./semantic-index-worker.mjs", import.meta.url)
4605
4679
  });
4606
4680
  server.addHook("onClose", async () => semanticIndexService?.close());
@@ -4669,4 +4743,4 @@ export {
4669
4743
  startHttpServer,
4670
4744
  stopHttpServer
4671
4745
  };
4672
- //# sourceMappingURL=chunk-UO2XVFY6.mjs.map
4746
+ //# sourceMappingURL=chunk-MENKFEPC.mjs.map