chatlab-cli 0.34.1 → 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 (124) hide show
  1. package/dist/{chat-command-OWKJJ736.mjs → chat-command-6IOH2QRF.mjs} +9 -9
  2. package/dist/{chunk-ZM5DSHFF.mjs → chunk-2XCNTG4O.mjs} +313 -76
  3. package/dist/chunk-2XCNTG4O.mjs.map +1 -0
  4. package/dist/{chunk-RRC6U56Y.mjs → chunk-4LW6443F.mjs} +1570 -687
  5. package/dist/chunk-4LW6443F.mjs.map +1 -0
  6. package/dist/{chunk-OHFVX2HH.mjs → chunk-4RLZFGO5.mjs} +2 -2
  7. package/dist/{chunk-GHZFNAMF.mjs → chunk-52P5ZRBD.mjs} +2 -2
  8. package/dist/{chunk-XEGEOU2D.mjs → chunk-652KEAX3.mjs} +2 -2
  9. package/dist/{chunk-J7HAIT3T.mjs → chunk-72RWABYJ.mjs} +2 -2
  10. package/dist/{chunk-MPHFZYB7.mjs → chunk-H6D4DZOC.mjs} +4 -4
  11. package/dist/{chunk-3RWYALUP.mjs → chunk-INBJ7SND.mjs} +50 -25
  12. package/dist/chunk-INBJ7SND.mjs.map +1 -0
  13. package/dist/{chunk-VTCZM2JS.mjs → chunk-JX6MFS6F.mjs} +43 -23
  14. package/dist/chunk-JX6MFS6F.mjs.map +1 -0
  15. package/dist/{chunk-RMW3524R.mjs → chunk-MENKFEPC.mjs} +149 -44
  16. package/dist/chunk-MENKFEPC.mjs.map +1 -0
  17. package/dist/{chunk-YRCFDZ5Q.mjs → chunk-U6MVJSXX.mjs} +170 -66
  18. package/dist/chunk-U6MVJSXX.mjs.map +1 -0
  19. package/dist/chunk-UMBEHBIZ.mjs +41 -0
  20. package/dist/chunk-UMBEHBIZ.mjs.map +1 -0
  21. package/dist/{chunk-GFHSSCCR.mjs → chunk-VSOWNKPA.mjs} +1 -11
  22. package/dist/cli.mjs +10 -9
  23. package/dist/contacts-worker.mjs +3 -3
  24. package/dist/global-insight-worker.mjs +2 -2
  25. package/dist/{http-X55S6MTO.mjs → http-HSK46XEU.mjs} +13 -12
  26. package/dist/{import-4AX6IX57.mjs → import-DF2WD2HE.mjs} +10 -8
  27. package/dist/index.mjs +13 -12
  28. package/dist/{mcp-GWC52AWE.mjs → mcp-A2RND7KN.mjs} +12 -12
  29. package/dist/people-relationships-worker.mjs +3 -3
  30. package/dist/semantic-index-worker.mjs +1 -1
  31. package/dist/{service-KGL3RAIA.mjs → service-KZTHBDQ5.mjs} +2 -2
  32. package/dist/{src-DLLM4SEO.mjs → src-SHFHW2QB.mjs} +27 -7
  33. package/dist/{stream-import-K24HWAAZ.mjs → stream-import-GZ2QDE3Z.mjs} +10 -8
  34. package/dist/{undici-ZSXBT7EA.mjs → undici-MU5I3L6Q.mjs} +2 -2
  35. package/dist/{update-checker-LGMTEKMT.mjs → update-checker-3N7HQEP2.mjs} +2 -2
  36. package/dist/{worker-runtime-6KKR55TD.mjs → worker-runtime-OWN56GG5.mjs} +14 -8
  37. package/dist/worker-runtime-OWN56GG5.mjs.map +1 -0
  38. package/dist-cli-web/assets/{ActionToolsPanel.vue_vue_type_script_setup_true_lang-D1BiZuQL.js → ActionToolsPanel.vue_vue_type_script_setup_true_lang-yr_T4ttU.js} +14 -14
  39. package/dist-cli-web/assets/{BufferResource-IPkSmPao.js → BufferResource-B-LHxriL.js} +1 -1
  40. package/dist-cli-web/assets/{CanvasRenderer-OAQy65em.js → CanvasRenderer-W3h_GGHM.js} +1 -1
  41. package/dist-cli-web/assets/{DataDirCleanupNotice-jEI-YjFp.js → DataDirCleanupNotice-C6CMNhfs.js} +1 -1
  42. package/dist-cli-web/assets/{EChartWordcloud-Pi48JdN2.js → EChartWordcloud-Dt6rCzHf.js} +1 -1
  43. package/dist-cli-web/assets/{Filter-FQD30cRE.js → Filter-BpSopVKd.js} +1 -1
  44. package/dist-cli-web/assets/{LoadingState.vue_vue_type_script_setup_true_lang-CCK5yTju.js → LoadingState.vue_vue_type_script_setup_true_lang-Bi_Uag3T.js} +1 -1
  45. package/dist-cli-web/assets/{MessageExportModal-CZn3LbeY.js → MessageExportModal-BoK-_h25.js} +1 -1
  46. package/dist-cli-web/assets/{PageHeader-B9B9K9by.js → PageHeader-CD8B7Emf.js} +1 -1
  47. package/dist-cli-web/assets/{RelationshipGalaxyCanvas-CbTmpnZ6.js → RelationshipGalaxyCanvas-BO3mo-Re.js} +7 -7
  48. package/dist-cli-web/assets/RelationshipGalaxyThreeCanvas-Brnpz6Ig.js +4108 -0
  49. package/dist-cli-web/assets/{RelationshipGalaxyThreeCanvas-CeYJABxI.css → RelationshipGalaxyThreeCanvas-CMuibfiA.css} +1 -1
  50. package/dist-cli-web/assets/{RenderTargetSystem-DnptJCQ0.js → RenderTargetSystem-CNP4JLfK.js} +1 -1
  51. package/dist-cli-web/assets/{ThemeCard.vue_vue_type_script_setup_true_lang-JXMFY6aD.js → ThemeCard.vue_vue_type_script_setup_true_lang-Na3LIoSJ.js} +1 -1
  52. package/dist-cli-web/assets/{TimeSelect.vue_vue_type_script_setup_true_lang-QAZFwx5S.js → TimeSelect.vue_vue_type_script_setup_true_lang-CKe1YZrV.js} +1 -1
  53. package/dist-cli-web/assets/{WebGLRenderer-BmjIF5se.js → WebGLRenderer-CIR5cTQN.js} +1 -1
  54. package/dist-cli-web/assets/{WebGPURenderer-DkNcKkqj.js → WebGPURenderer-Dz3pCrzX.js} +1 -1
  55. package/dist-cli-web/assets/{annual-summary-time-range-DJ0HWI_t.js → annual-summary-time-range-QhoA3uC6.js} +1 -1
  56. package/dist-cli-web/assets/{base-CnuE0ss0.js → base-p9yfnTpk.js} +1 -1
  57. package/dist-cli-web/assets/{browserAll-C_NnyNBz.js → browserAll-DMaXjf8N.js} +1 -1
  58. package/dist-cli-web/assets/cli-web-Dvy2aHxG.js +1 -0
  59. package/dist-cli-web/assets/{dateFormat-p6nibkgt.js → dateFormat-5x3JKlIk.js} +1 -1
  60. package/dist-cli-web/assets/{fetch-Ch4IMKin.js → fetch-B0p6QRQ8.js} +1 -1
  61. package/dist-cli-web/assets/{fetch-DajjPQtq.js → fetch-BI-Se2p7.js} +1 -1
  62. package/dist-cli-web/assets/{fetch-WElo3Vix.js → fetch-BderOzzL.js} +1 -1
  63. package/dist-cli-web/assets/{fetch-Bsm5YQ_7.js → fetch-BtJWW2-O.js} +1 -1
  64. package/dist-cli-web/assets/fetch-CBaZNOpK.js +4 -0
  65. package/dist-cli-web/assets/{fetch-BBUvWvOM.js → fetch-CH9Hm20R.js} +1 -1
  66. package/dist-cli-web/assets/{fetch-CMhV3TYQ.js → fetch-CbpKKkdO.js} +1 -1
  67. package/dist-cli-web/assets/{fetch-C4KJ7tGz.js → fetch-Cne-uL1m.js} +1 -1
  68. package/dist-cli-web/assets/{fetch-WIOgRPd9.js → fetch-DRGykJYb.js} +1 -1
  69. package/dist-cli-web/assets/{fetch-BfYranz7.js → fetch-QLurhC_z.js} +1 -1
  70. package/dist-cli-web/assets/{index-CjoTcSEc.js → index-4NL2pYn0.js} +1 -1
  71. package/dist-cli-web/assets/{index-CsyURmWU.js → index-B-KdENnr.js} +1 -1
  72. package/dist-cli-web/assets/{index-DLnlRLCx.js → index-BDyixm5n.js} +1 -1
  73. package/dist-cli-web/assets/{index-BE4nd1aX.js → index-BaCd1avL.js} +1 -1
  74. package/dist-cli-web/assets/{index-CKkIHbie.js → index-CVBBDI3B.js} +3 -3
  75. package/dist-cli-web/assets/index-CXh01dqh.js +2 -0
  76. package/dist-cli-web/assets/index-CioAsn_2.js +137 -0
  77. package/dist-cli-web/assets/{index-x74lBtei.js → index-Ct90lmPb.js} +1 -1
  78. package/dist-cli-web/assets/index-CumZ5uQ4.js +53 -0
  79. package/dist-cli-web/assets/index-CxGtGxLW.css +1 -0
  80. package/dist-cli-web/assets/{index-BcWaPFz7.js → index-DF2Dijfg.js} +1 -1
  81. package/dist-cli-web/assets/{index-CbacXZN3.js → index-DYCPQMOl.js} +2 -2
  82. package/dist-cli-web/assets/{index-Bb6EtLMB.js → index-Dp2uglLH.js} +1 -1
  83. package/dist-cli-web/assets/{index-dObiAHg6.js → index-IvxuxPNt.js} +1 -1
  84. package/dist-cli-web/assets/{people-page-header-BW5cNPl7.js → people-page-header-BRb9BrgP.js} +1 -1
  85. package/dist-cli-web/assets/telemetry-DPC69b73.js +1 -0
  86. package/dist-cli-web/assets/{webworkerAll-8AFsQkH1.js → webworkerAll-BoY19vZt.js} +1 -1
  87. package/dist-cli-web/index.html +1 -1
  88. package/package.json +3 -2
  89. package/dist/chunk-3RWYALUP.mjs.map +0 -1
  90. package/dist/chunk-RMW3524R.mjs.map +0 -1
  91. package/dist/chunk-RRC6U56Y.mjs.map +0 -1
  92. package/dist/chunk-VTCZM2JS.mjs.map +0 -1
  93. package/dist/chunk-YRCFDZ5Q.mjs.map +0 -1
  94. package/dist/chunk-ZM5DSHFF.mjs.map +0 -1
  95. package/dist/onnxruntime_binding-6Q6HXASN.node +0 -0
  96. package/dist/onnxruntime_binding-EKZT2NRK.node +0 -0
  97. package/dist/onnxruntime_binding-P6S7V3CI.node +0 -0
  98. package/dist/onnxruntime_binding-PJNNIIUO.node +0 -0
  99. package/dist/onnxruntime_binding-UN6SPTQK.node +0 -0
  100. package/dist/transformers.node-PUMHAODN.mjs +0 -42889
  101. package/dist/transformers.node-PUMHAODN.mjs.map +0 -1
  102. package/dist/worker-runtime-6KKR55TD.mjs.map +0 -1
  103. package/dist-cli-web/assets/RelationshipGalaxyThreeCanvas-Cu6NmKOq.js +0 -4108
  104. package/dist-cli-web/assets/cli-web-t1gabACJ.js +0 -1
  105. package/dist-cli-web/assets/fetch-_Hb-KRSr.js +0 -3
  106. package/dist-cli-web/assets/index-B8I5Pax_.js +0 -2
  107. package/dist-cli-web/assets/index-CsX1Wt8l.js +0 -173
  108. package/dist-cli-web/assets/index-DmrrdYXH.css +0 -1
  109. package/dist-cli-web/assets/index-YzfjPohq.js +0 -53
  110. /package/dist/{chat-command-OWKJJ736.mjs.map → chat-command-6IOH2QRF.mjs.map} +0 -0
  111. /package/dist/{chunk-OHFVX2HH.mjs.map → chunk-4RLZFGO5.mjs.map} +0 -0
  112. /package/dist/{chunk-GHZFNAMF.mjs.map → chunk-52P5ZRBD.mjs.map} +0 -0
  113. /package/dist/{chunk-XEGEOU2D.mjs.map → chunk-652KEAX3.mjs.map} +0 -0
  114. /package/dist/{chunk-J7HAIT3T.mjs.map → chunk-72RWABYJ.mjs.map} +0 -0
  115. /package/dist/{chunk-MPHFZYB7.mjs.map → chunk-H6D4DZOC.mjs.map} +0 -0
  116. /package/dist/{chunk-GFHSSCCR.mjs.map → chunk-VSOWNKPA.mjs.map} +0 -0
  117. /package/dist/{http-X55S6MTO.mjs.map → http-HSK46XEU.mjs.map} +0 -0
  118. /package/dist/{import-4AX6IX57.mjs.map → import-DF2WD2HE.mjs.map} +0 -0
  119. /package/dist/{mcp-GWC52AWE.mjs.map → mcp-A2RND7KN.mjs.map} +0 -0
  120. /package/dist/{service-KGL3RAIA.mjs.map → service-KZTHBDQ5.mjs.map} +0 -0
  121. /package/dist/{src-DLLM4SEO.mjs.map → src-SHFHW2QB.mjs.map} +0 -0
  122. /package/dist/{stream-import-K24HWAAZ.mjs.map → stream-import-GZ2QDE3Z.mjs.map} +0 -0
  123. /package/dist/{undici-ZSXBT7EA.mjs.map → undici-MU5I3L6Q.mjs.map} +0 -0
  124. /package/dist/{update-checker-LGMTEKMT.mjs.map → update-checker-3N7HQEP2.mjs.map} +0 -0
@@ -6,17 +6,17 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __pathDirname(__filename);
7
7
  import {
8
8
  createCliRunAgentStream
9
- } from "./chunk-MPHFZYB7.mjs";
10
- import "./chunk-J7HAIT3T.mjs";
11
- import "./chunk-ZM5DSHFF.mjs";
12
- import "./chunk-RRC6U56Y.mjs";
13
- import "./chunk-GHZFNAMF.mjs";
14
- import "./chunk-XEGEOU2D.mjs";
9
+ } from "./chunk-H6D4DZOC.mjs";
10
+ import "./chunk-72RWABYJ.mjs";
11
+ import "./chunk-2XCNTG4O.mjs";
12
+ import "./chunk-4LW6443F.mjs";
13
+ import "./chunk-52P5ZRBD.mjs";
14
+ import "./chunk-652KEAX3.mjs";
15
15
  import "./chunk-QZCNVAH6.mjs";
16
16
  import {
17
17
  getDefaultGeneralAssistantId
18
- } from "./chunk-3RWYALUP.mjs";
19
- import "./chunk-GFHSSCCR.mjs";
18
+ } from "./chunk-INBJ7SND.mjs";
19
+ import "./chunk-VSOWNKPA.mjs";
20
20
 
21
21
  // src/ai/chat-command.ts
22
22
  import { createInterface } from "readline/promises";
@@ -312,4 +312,4 @@ export {
312
312
  runChatCommand,
313
313
  runChatTurn
314
314
  };
315
- //# sourceMappingURL=chat-command-OWKJJ736.mjs.map
315
+ //# sourceMappingURL=chat-command-6IOH2QRF.mjs.map
@@ -14,6 +14,8 @@ import {
14
14
  DESENSITIZE_RULES_SCHEMA_VERSION,
15
15
  EMBEDDING_INDEX_SCHEMA,
16
16
  EmbeddingIndexStore,
17
+ LOCAL_EMBEDDING_RUNTIME_PACKAGE,
18
+ LOCAL_EMBEDDING_RUNTIME_VERSION,
17
19
  LocalEmbeddingProvider,
18
20
  OpenAICompatibleEmbeddingProvider,
19
21
  QWEN3_PROFILE,
@@ -43,6 +45,7 @@ import {
43
45
  createChatDbMessageSource,
44
46
  createChatLabTempDir,
45
47
  createEmbedder,
48
+ createLocalEmbeddingRuntimeManager,
46
49
  createSemanticIndexService,
47
50
  defaultSemanticIndexConfig,
48
51
  deriveParentId,
@@ -66,7 +69,7 @@ import {
66
69
  runWarmup,
67
70
  vecTableName,
68
71
  vecTableSchema
69
- } from "./chunk-RRC6U56Y.mjs";
72
+ } from "./chunk-4LW6443F.mjs";
70
73
  import {
71
74
  CHATLAB_FORMAT_VERSION,
72
75
  MEANINGFUL_POS_TAGS,
@@ -81,13 +84,16 @@ import {
81
84
  mergeMembers2 as mergeMembers,
82
85
  migrateFromElectronIfNeeded,
83
86
  normalizePlatformId,
87
+ readJsonFile,
84
88
  resolveApiKey,
85
89
  snapshotPathProvider,
86
- writeConfigField
87
- } from "./chunk-3RWYALUP.mjs";
90
+ withFileLock,
91
+ writeConfigField,
92
+ writeJsonFileAtomically
93
+ } from "./chunk-INBJ7SND.mjs";
88
94
  import {
89
95
  __export
90
- } from "./chunk-GFHSSCCR.mjs";
96
+ } from "./chunk-VSOWNKPA.mjs";
91
97
 
92
98
  // ../../packages/node-runtime/src/node-path-provider.ts
93
99
  import * as fs2 from "fs";
@@ -340,7 +346,7 @@ function deletePendingDataDirCleanup(systemDir, currentDir, cleanupId, deps = {}
340
346
  if (!cleanup) return { success: false, error: "Pending data directory cleanup not found" };
341
347
  const sourceDir = cleanup.sourceDir;
342
348
  const overlapsCurrentDir = normalizePathForCompare(sourceDir) === normalizePathForCompare(currentDir) || isSubPath(sourceDir, currentDir) || isSubPath(currentDir, sourceDir);
343
- const overlapsSystemDir = normalizePathForCompare(sourceDir) === normalizePathForCompare(systemDir) || isSubPath(sourceDir, systemDir);
349
+ const overlapsSystemDir = normalizePathForCompare(sourceDir) === normalizePathForCompare(systemDir) || isSubPath(sourceDir, systemDir) || isSubPath(systemDir, sourceDir);
344
350
  if (overlapsCurrentDir || overlapsSystemDir) {
345
351
  appLogger.warn("data-dir", "Old data directory cleanup rejected because the path is still in use", { cleanupId });
346
352
  return { success: false, error: "Old data directory overlaps a directory still in use" };
@@ -876,102 +882,281 @@ function* serializeChatLabToJsonl(data) {
876
882
  }
877
883
 
878
884
  // ../../packages/node-runtime/src/services/analytics.ts
879
- import * as fs4 from "fs";
880
885
  import * as path4 from "path";
881
- var REGIONS = {
882
- US: "https://us.aptabase.com",
883
- EU: "https://eu.aptabase.com"
886
+ import { randomUUID as randomUUID2 } from "crypto";
887
+ var DEFAULT_DATA = {
888
+ lastReportDate: null,
889
+ firstReportDate: null,
890
+ anonymousId: null,
891
+ enabled: true
884
892
  };
885
- var DEFAULT_DATA = { lastReportDate: null, firstReportDate: null, enabled: true };
893
+ var EVENT_NAMES = /* @__PURE__ */ new Set([
894
+ "app_started",
895
+ "app_active_new",
896
+ "app_active",
897
+ "chat_import_started",
898
+ "chat_import_completed",
899
+ "chat_import_failed",
900
+ "incremental_import_used",
901
+ "feature_used",
902
+ "ai_setup_completed",
903
+ "ai_request_started",
904
+ "ai_request_completed"
905
+ ]);
906
+ var FEATURE_IDS = /* @__PURE__ */ new Set([
907
+ "insights",
908
+ "ranking",
909
+ "ai_chat",
910
+ "sql_lab",
911
+ "message_search",
912
+ "member_management",
913
+ "session_merge",
914
+ "export"
915
+ ]);
916
+ var FAILURE_REASONS = /* @__PURE__ */ new Set([
917
+ "auth",
918
+ "network",
919
+ "rate_limit",
920
+ "model_not_found",
921
+ "aborted",
922
+ "parse",
923
+ "write",
924
+ "unknown"
925
+ ]);
926
+ var APP_LOCALES = /* @__PURE__ */ new Set(["zh-CN", "zh-TW", "en-US", "ja-JP"]);
927
+ function getUmamiConfigFromEnv() {
928
+ const endpoint = "https://t.feapp.cn/api/send"?.trim();
929
+ const websiteId = "3fbbc313-d122-4649-9c50-eef4bfad2650"?.trim();
930
+ return endpoint && websiteId ? { endpoint, websiteId } : void 0;
931
+ }
932
+ function normalizeOs() {
933
+ if (process.platform === "darwin") return "macos";
934
+ if (process.platform === "win32") return "windows";
935
+ if (process.platform === "linux") return "linux";
936
+ return "other";
937
+ }
938
+ function normalizeLocale(value) {
939
+ if (typeof value !== "string") return "unknown";
940
+ const trimmed = value.trim();
941
+ return APP_LOCALES.has(trimmed) ? trimmed : "unknown";
942
+ }
943
+ function normalizeAnalyticsImportPlatform(value) {
944
+ if (typeof value !== "string") return "unknown";
945
+ const platform = value.trim();
946
+ const hasPathOrControlCharacter = [...platform].some(
947
+ (char) => char === "/" || char === "\\" || char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127
948
+ );
949
+ return platform.length > 0 && platform.length <= 64 && !hasPathOrControlCharacter ? platform : "unknown";
950
+ }
951
+ function normalizeDuration(value) {
952
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return null;
953
+ return Math.min(Math.round(value), 24 * 60 * 60 * 1e3);
954
+ }
955
+ function normalizeEvent(eventName, props = {}) {
956
+ if (!EVENT_NAMES.has(eventName)) return null;
957
+ const name = eventName;
958
+ const properties = {};
959
+ if (name.startsWith("chat_import_")) {
960
+ properties.chat_platform = normalizeAnalyticsImportPlatform(props.chat_platform);
961
+ }
962
+ if (name === "chat_import_completed" || name === "ai_request_completed") {
963
+ const duration = normalizeDuration(props.duration_ms);
964
+ if (duration !== null) properties.duration_ms = duration;
965
+ }
966
+ if (name === "feature_used") {
967
+ if (typeof props.feature_id !== "string" || !FEATURE_IDS.has(props.feature_id)) return null;
968
+ properties.feature_id = props.feature_id;
969
+ }
970
+ if (name === "ai_request_completed") {
971
+ if (typeof props.success !== "boolean") return null;
972
+ properties.success = props.success;
973
+ }
974
+ if (name === "chat_import_failed" || name === "ai_request_completed" && props.success === false) {
975
+ const reason = typeof props.failure_reason === "string" ? props.failure_reason : "unknown";
976
+ properties.failure_reason = FAILURE_REASONS.has(reason) ? reason : "unknown";
977
+ }
978
+ return { name, properties };
979
+ }
980
+ function eventPath(event) {
981
+ if (event.name === "incremental_import_used") return "/import/incremental";
982
+ if (event.name.startsWith("chat_import_")) return "/import";
983
+ if (event.name.startsWith("ai_")) return "/ai";
984
+ if (event.name === "feature_used") return `/features/${event.properties.feature_id}`;
985
+ return "/app";
986
+ }
886
987
  var AnalyticsService = class {
887
988
  dataPath;
888
- endpoint;
889
- appKey;
890
- appVersion;
891
- sessionId;
892
- constructor(systemDir, appKey, appVersion) {
989
+ options;
990
+ sessionId = randomUUID2();
991
+ appLocale = "unknown";
992
+ startupAttempted = false;
993
+ // Product constraint: only one ChatLab runtime is expected to use a system directory at a time.
994
+ // Daily-active deduplication is intentionally process-local unless concurrent runtimes become supported.
995
+ dailyActivePromise = null;
996
+ constructor(systemDir, options) {
893
997
  this.dataPath = path4.join(systemDir, "analytics.json");
894
- this.appKey = appKey;
895
- this.appVersion = appVersion;
896
- this.sessionId = `${Math.floor(Date.now() / 1e3)}${Math.floor(Math.random() * 1e8).toString().padStart(8, "0")}`;
897
- const parts = appKey.split("-");
898
- const base = parts.length === 3 ? REGIONS[parts[1]] : void 0;
899
- this.endpoint = base ? `${base}/api/v0/event` : null;
998
+ this.options = {
999
+ ...options,
1000
+ umami: options.umami ?? getUmamiConfigFromEnv()
1001
+ };
900
1002
  }
901
1003
  load() {
902
1004
  try {
903
- if (fs4.existsSync(this.dataPath)) {
904
- return { ...DEFAULT_DATA, ...JSON.parse(fs4.readFileSync(this.dataPath, "utf-8")) };
905
- }
906
- } catch (_e) {
1005
+ const stored = readJsonFile(this.dataPath);
1006
+ if (stored) return { ...DEFAULT_DATA, ...stored };
1007
+ } catch (error) {
1008
+ appLogger.error("analytics", "Failed to read analytics settings; using defaults", error);
907
1009
  }
908
1010
  return { ...DEFAULT_DATA };
909
1011
  }
910
- save(data) {
1012
+ updateData(update, fallback) {
911
1013
  try {
912
- fs4.writeFileSync(this.dataPath, JSON.stringify(data, null, 2), "utf-8");
913
- } catch (e) {
914
- console.error("[Analytics] Failed to save:", e);
1014
+ return withFileLock(this.dataPath, () => {
1015
+ const data = this.load();
1016
+ const result = update(data);
1017
+ writeJsonFileAtomically(this.dataPath, data, 384);
1018
+ return result;
1019
+ });
1020
+ } catch (error) {
1021
+ appLogger.error("analytics", "Failed to update analytics settings", error);
1022
+ return fallback;
915
1023
  }
916
1024
  }
917
- getEnabled() {
918
- return this.load().enabled;
1025
+ getOrCreateAnonymousId() {
1026
+ const fallback = randomUUID2();
1027
+ return this.updateData((data) => {
1028
+ data.anonymousId ??= randomUUID2();
1029
+ return data.anonymousId;
1030
+ }, fallback);
919
1031
  }
920
- setEnabled(enabled) {
921
- const data = this.load();
922
- data.enabled = enabled;
923
- this.save(data);
1032
+ isAiModelConfigured() {
1033
+ try {
1034
+ return this.options.getAiModelConfigured?.() === true;
1035
+ } catch (error) {
1036
+ appLogger.error("analytics", "Failed to resolve AI configuration state", error);
1037
+ return false;
1038
+ }
924
1039
  }
925
- async track(eventName, props) {
926
- if (!this.endpoint) return false;
927
- if (!this.getEnabled()) return false;
1040
+ buildEnvelope(event) {
1041
+ return {
1042
+ ...event,
1043
+ anonymousId: this.getOrCreateAnonymousId(),
1044
+ sessionId: this.sessionId,
1045
+ appVersion: this.options.appVersion,
1046
+ appType: this.options.appType,
1047
+ os: normalizeOs(),
1048
+ appLocale: this.appLocale,
1049
+ aiModelConfigured: this.isAiModelConfigured()
1050
+ };
1051
+ }
1052
+ commonProperties(envelope) {
1053
+ return {
1054
+ session_id: envelope.sessionId,
1055
+ app_version: envelope.appVersion,
1056
+ app_type: envelope.appType,
1057
+ os: envelope.os,
1058
+ app_locale: envelope.appLocale,
1059
+ ai_model_configured: envelope.aiModelConfigured,
1060
+ schema_version: 1
1061
+ };
1062
+ }
1063
+ async sendToUmami(envelope) {
1064
+ const umami = this.options.umami;
1065
+ if (!umami) return false;
928
1066
  try {
929
- const resp = await fetch(this.endpoint, {
1067
+ const response = await fetch(umami.endpoint, {
930
1068
  method: "POST",
931
- headers: { "Content-Type": "application/json", "App-Key": this.appKey },
1069
+ headers: {
1070
+ "Content-Type": "application/json",
1071
+ "User-Agent": `ChatLab/${envelope.appVersion} (${envelope.os}; ${envelope.appType})`
1072
+ },
932
1073
  body: JSON.stringify({
933
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
934
- sessionId: this.sessionId,
935
- eventName,
936
- systemProps: {
937
- isDebug: false,
938
- locale: "",
939
- osName: process.platform,
940
- osVersion: "",
941
- engineName: "Node.js",
942
- engineVersion: process.versions.node,
943
- appVersion: this.appVersion,
944
- sdkVersion: "chatlab@1"
945
- },
946
- props
947
- })
1074
+ type: "event",
1075
+ payload: {
1076
+ website: umami.websiteId,
1077
+ hostname: "chatlab",
1078
+ url: eventPath(envelope),
1079
+ language: envelope.appLocale,
1080
+ name: envelope.name,
1081
+ id: envelope.anonymousId,
1082
+ data: {
1083
+ ...this.commonProperties(envelope),
1084
+ ...envelope.properties
1085
+ }
1086
+ }
1087
+ }),
1088
+ signal: AbortSignal.timeout(5e3)
948
1089
  });
949
- return resp.ok;
950
- } catch (e) {
951
- console.error(`[Analytics] Failed to track ${eventName}:`, e);
1090
+ if (!response.ok) {
1091
+ appLogger.warn("analytics", "Umami rejected analytics event", {
1092
+ eventName: envelope.name,
1093
+ status: response.status
1094
+ });
1095
+ }
1096
+ return response.ok;
1097
+ } catch (error) {
1098
+ appLogger.error("analytics", "Failed to send analytics event to Umami", error);
952
1099
  return false;
953
1100
  }
954
1101
  }
955
- async trackDailyActive(props) {
956
- if (!this.endpoint) return;
1102
+ getEnabled() {
1103
+ return this.load().enabled;
1104
+ }
1105
+ setEnabled(enabled) {
1106
+ this.updateData((data) => {
1107
+ data.enabled = enabled;
1108
+ }, void 0);
1109
+ }
1110
+ setAppLocale(locale) {
1111
+ this.appLocale = normalizeLocale(locale);
1112
+ }
1113
+ async track(eventName, props) {
1114
+ if (!this.getEnabled()) return false;
1115
+ if (props?.app_locale !== void 0) this.setAppLocale(String(props.app_locale));
1116
+ const event = normalizeEvent(eventName, props);
1117
+ if (!event) return false;
1118
+ if (!this.options.umami) return false;
1119
+ const envelope = this.buildEnvelope(event);
1120
+ const delivered = await this.sendToUmami(envelope);
1121
+ appLogger.debug("analytics", delivered ? "Analytics event delivered" : "Analytics event was not delivered", {
1122
+ eventName: envelope.name
1123
+ });
1124
+ return delivered;
1125
+ }
1126
+ trackDailyActive(props) {
1127
+ if (this.dailyActivePromise) {
1128
+ const locale = props?.app_locale ?? props?.locale;
1129
+ if (locale !== void 0) this.setAppLocale(String(locale));
1130
+ return this.dailyActivePromise;
1131
+ }
1132
+ this.dailyActivePromise = this.trackDailyActiveInternal(props).finally(() => {
1133
+ this.dailyActivePromise = null;
1134
+ });
1135
+ return this.dailyActivePromise;
1136
+ }
1137
+ async trackDailyActiveInternal(props) {
1138
+ const locale = props?.app_locale ?? props?.locale;
1139
+ if (locale !== void 0) this.setAppLocale(String(locale));
957
1140
  const data = this.load();
958
1141
  if (!data.enabled) return;
1142
+ if (!this.startupAttempted) {
1143
+ this.startupAttempted = true;
1144
+ await this.track("app_started");
1145
+ }
959
1146
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
960
1147
  const isNew = data.firstReportDate === null;
961
- if (isNew) data.firstReportDate = today;
962
- if (data.lastReportDate === today) {
963
- if (isNew) this.save(data);
964
- return;
965
- }
966
- const tracked = await this.track(isNew ? "app_active_new" : "app_active", props);
1148
+ if (data.lastReportDate === today) return;
1149
+ const tracked = await this.track(isNew ? "app_active_new" : "app_active");
967
1150
  if (!tracked) return;
968
- data.lastReportDate = today;
969
- this.save(data);
1151
+ this.updateData((persisted) => {
1152
+ persisted.firstReportDate ??= today;
1153
+ persisted.lastReportDate = today;
1154
+ }, void 0);
970
1155
  }
971
1156
  };
972
1157
 
973
1158
  // ../../packages/node-runtime/src/services/demo-import.ts
974
- import * as fs5 from "fs";
1159
+ import * as fs4 from "fs";
975
1160
  import * as path5 from "path";
976
1161
  var DEMO_BASE_URL = "https://chatlab.fun/assets/demo";
977
1162
  var DEMO_FILES = ["demo-group.json", "demo-private-B-wukong.json"];
@@ -1005,7 +1190,7 @@ async function importDemoSessions(options) {
1005
1190
  const rebased = rebaseChatLabDemoDocuments(downloaded, options.now?.() ?? /* @__PURE__ */ new Date(), options.targetTimeZone);
1006
1191
  const localPaths = rebased.documents.map((document, index) => {
1007
1192
  const localPath = path5.join(createdTempDir, DEMO_FILES[index]);
1008
- fs5.writeFileSync(localPath, document, "utf8");
1193
+ fs4.writeFileSync(localPath, document, "utf8");
1009
1194
  return localPath;
1010
1195
  });
1011
1196
  appLogger.info("demo-import", "Demo timeline prepared", {
@@ -1066,6 +1251,8 @@ __export(semantic_index_exports, {
1066
1251
  DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE: () => DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE,
1067
1252
  EMBEDDING_INDEX_SCHEMA: () => EMBEDDING_INDEX_SCHEMA,
1068
1253
  EmbeddingIndexStore: () => EmbeddingIndexStore,
1254
+ LOCAL_EMBEDDING_RUNTIME_PACKAGE: () => LOCAL_EMBEDDING_RUNTIME_PACKAGE,
1255
+ LOCAL_EMBEDDING_RUNTIME_VERSION: () => LOCAL_EMBEDDING_RUNTIME_VERSION,
1069
1256
  SEARCH_MAX_RESULTS_DEFAULT: () => SEARCH_MAX_RESULTS_DEFAULT,
1070
1257
  SEARCH_MAX_RESULTS_MAX: () => SEARCH_MAX_RESULTS_MAX,
1071
1258
  SEARCH_MAX_RESULTS_MIN: () => SEARCH_MAX_RESULTS_MIN,
@@ -1091,6 +1278,7 @@ __export(semantic_index_exports, {
1091
1278
  createChatDbMessageRangeReader: () => createChatDbMessageRangeReader,
1092
1279
  createChatDbMessageSource: () => createChatDbMessageSource,
1093
1280
  createEmbedder: () => createEmbedder,
1281
+ createLocalEmbeddingRuntimeManager: () => createLocalEmbeddingRuntimeManager,
1094
1282
  createSemanticIndexService: () => createSemanticIndexService,
1095
1283
  createSemanticIndexWorkerClient: () => createSemanticIndexWorkerClient,
1096
1284
  createSemanticIndexWorkerRuntimeClient: () => createSemanticIndexWorkerRuntimeClient,
@@ -1206,6 +1394,7 @@ function createSemanticIndexWorkerThreadTransport(options) {
1206
1394
 
1207
1395
  // ../../packages/node-runtime/src/semantic-index/worker-client.ts
1208
1396
  var DEFAULT_IDLE_TIMEOUT_MS = 10 * 60 * 1e3;
1397
+ var MODEL_PRELOAD_STATUS_POLL_MS = 2e3;
1209
1398
  var defaultTimers = {
1210
1399
  setTimeout: (callback, ms) => setTimeout(callback, ms),
1211
1400
  clearTimeout: (timer) => clearTimeout(timer)
@@ -1214,8 +1403,10 @@ var SemanticIndexWorkerClient = class {
1214
1403
  transport = null;
1215
1404
  pendingRequests = 0;
1216
1405
  idleTimer = null;
1406
+ modelPreloadPollTimer = null;
1217
1407
  activeBuildSessionIds = /* @__PURE__ */ new Set();
1218
1408
  hasUnknownActiveBuild = false;
1409
+ hasActiveModelPreload = false;
1219
1410
  activeModelDownloadProxyUrl;
1220
1411
  configStore;
1221
1412
  transportFactory;
@@ -1241,7 +1432,10 @@ var SemanticIndexWorkerClient = class {
1241
1432
  apiKey: options?.apiKey,
1242
1433
  writeAuthProfile: this.writeAuthProfile
1243
1434
  });
1244
- if (!saved.enabled) this.clearActiveBuildTracking();
1435
+ if (!saved.enabled) {
1436
+ this.clearActiveBuildTracking();
1437
+ }
1438
+ if (!saved.enabled || saved.mode !== "local") this.clearModelPreloadTracking();
1245
1439
  const needsWorker = saved.enabled && saved.mode === "local" && this.configStore.isConfigured();
1246
1440
  if (!this.transport && !needsWorker) return saved;
1247
1441
  if (needsWorker) await this.closeTransportForLocalModelProxyChangeIfNeeded();
@@ -1254,8 +1448,10 @@ var SemanticIndexWorkerClient = class {
1254
1448
  return resolveSemanticIndexApiKeySet(this.configStore.get(), this.resolveApiKey);
1255
1449
  }
1256
1450
  async getModelStatus() {
1257
- if (!this.transport) return "idle";
1258
- return this.call("getModelStatus", []);
1451
+ if (!this.transport && !this.shouldStartLocalModelWorker()) return "idle";
1452
+ const status = await this.call("getModelStatus", [], { scheduleIdle: false });
1453
+ this.updateModelPreloadStatus(status);
1454
+ return status;
1259
1455
  }
1260
1456
  enable(sessionId) {
1261
1457
  return this.call("enable", [sessionId]);
@@ -1393,6 +1589,10 @@ var SemanticIndexWorkerClient = class {
1393
1589
  if (isKeylessSemanticIndexApiBaseUrl(config.api?.baseUrl)) return true;
1394
1590
  return resolveSemanticIndexApiKeySet(config, this.resolveApiKey);
1395
1591
  }
1592
+ shouldStartLocalModelWorker() {
1593
+ const config = this.configStore.get();
1594
+ return config.enabled && config.mode === "local" && this.configStore.isConfigured();
1595
+ }
1396
1596
  updateActiveBuildFromCompleteSnapshot(statuses) {
1397
1597
  this.hasUnknownActiveBuild = false;
1398
1598
  this.activeBuildSessionIds = new Set(
@@ -1414,8 +1614,43 @@ var SemanticIndexWorkerClient = class {
1414
1614
  this.hasUnknownActiveBuild = false;
1415
1615
  this.activeBuildSessionIds.clear();
1416
1616
  }
1617
+ updateModelPreloadStatus(status) {
1618
+ this.hasActiveModelPreload = status === "installing-runtime" || status === "downloading-model";
1619
+ if (this.hasActiveModelPreload) this.scheduleModelPreloadPoll();
1620
+ else {
1621
+ this.clearModelPreloadPoll();
1622
+ this.scheduleIdleCloseIfNeeded();
1623
+ }
1624
+ }
1625
+ scheduleModelPreloadPoll() {
1626
+ this.clearModelPreloadPoll();
1627
+ if (!this.transport || !this.hasActiveModelPreload) return;
1628
+ this.modelPreloadPollTimer = this.timers.setTimeout(() => {
1629
+ this.modelPreloadPollTimer = null;
1630
+ void this.pollModelPreloadStatus();
1631
+ }, MODEL_PRELOAD_STATUS_POLL_MS);
1632
+ }
1633
+ async pollModelPreloadStatus() {
1634
+ if (!this.transport || !this.hasActiveModelPreload) return;
1635
+ try {
1636
+ await this.getModelStatus();
1637
+ } catch (error) {
1638
+ appLogger.error("semantic-index", "Background model preload status poll failed; closing worker", error);
1639
+ await this.closeFailedProbeTransport();
1640
+ }
1641
+ }
1642
+ clearModelPreloadPoll() {
1643
+ if (this.modelPreloadPollTimer) {
1644
+ this.timers.clearTimeout(this.modelPreloadPollTimer);
1645
+ this.modelPreloadPollTimer = null;
1646
+ }
1647
+ }
1648
+ clearModelPreloadTracking() {
1649
+ this.hasActiveModelPreload = false;
1650
+ this.clearModelPreloadPoll();
1651
+ }
1417
1652
  scheduleIdleCloseIfNeeded() {
1418
- if (!this.transport || this.pendingRequests > 0 || this.hasUnknownActiveBuild || this.activeBuildSessionIds.size > 0)
1653
+ if (!this.transport || this.pendingRequests > 0 || this.hasUnknownActiveBuild || this.hasActiveModelPreload || this.activeBuildSessionIds.size > 0)
1419
1654
  return;
1420
1655
  this.clearIdleTimer();
1421
1656
  this.idleTimer = this.timers.setTimeout(() => {
@@ -1434,6 +1669,7 @@ var SemanticIndexWorkerClient = class {
1434
1669
  const transport = this.transport;
1435
1670
  this.transport = null;
1436
1671
  this.activeModelDownloadProxyUrl = void 0;
1672
+ this.clearModelPreloadTracking();
1437
1673
  this.clearActiveBuildTracking();
1438
1674
  if (transport) await transport.close();
1439
1675
  }
@@ -1465,7 +1701,8 @@ function createSemanticIndexWorkerRuntimeClient(options) {
1465
1701
  runtime: options.runtime,
1466
1702
  nativeBinding: options.nativeBinding,
1467
1703
  sqliteVecLoadablePath: options.sqliteVecLoadablePath,
1468
- modelDownloadProxyUrl
1704
+ modelDownloadProxyUrl,
1705
+ localEmbeddingRuntime: options.localEmbeddingRuntime
1469
1706
  }
1470
1707
  })
1471
1708
  });
@@ -1514,4 +1751,4 @@ export {
1514
1751
  createSemanticIndexWorkerRuntimeClient,
1515
1752
  semantic_index_exports
1516
1753
  };
1517
- //# sourceMappingURL=chunk-ZM5DSHFF.mjs.map
1754
+ //# sourceMappingURL=chunk-2XCNTG4O.mjs.map